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/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new be1c03afacd Refresh apache-magpie setup skill with trusted 
skill-sources support (#69376)
be1c03afacd is described below

commit be1c03afacd520406231b7f741ba0c03b53e8055
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sat Jul 4 14:49:42 2026 +0200

    Refresh apache-magpie setup skill with trusted skill-sources support 
(#69376)
    
    The committed magpie-setup skill is the one apache-magpie artefact tracked
    in this repo — every contributor's /magpie-setup loads it directly. Syncing
    it to the framework's pinned main tip keeps adopt/upgrade/verify running the
    current flow, which now includes fetching and pinning skills from trusted
    external sources.
---
 .agents/skills/magpie-setup/SKILL.md         |  36 +++-
 .agents/skills/magpie-setup/adopt.md         |  34 ++++
 .agents/skills/magpie-setup/skill-sources.md | 278 +++++++++++++++++++++++++++
 .agents/skills/magpie-setup/upgrade.md       |  35 ++++
 .agents/skills/magpie-setup/verify.md        |  29 +++
 .agents/skills/magpie-setup/worktree-init.md |  13 ++
 6 files changed, 421 insertions(+), 4 deletions(-)

diff --git a/.agents/skills/magpie-setup/SKILL.md 
b/.agents/skills/magpie-setup/SKILL.md
index 4458c03a85f..ac8e394b03d 100644
--- a/.agents/skills/magpie-setup/SKILL.md
+++ b/.agents/skills/magpie-setup/SKILL.md
@@ -10,6 +10,7 @@ description: |
     `/magpie-setup upgrade` - refresh the gitignored snapshot per the 
committed lock (main-checkout only)
     `/magpie-setup worktree-init` - symlink a worktree's snapshot to the main's
     `/magpie-setup verify` - health check + drift detection
+    `/magpie-setup skill-sources` - fetch/pin/symlink skills from trusted 
external sources listed in the adopter trust list (main-checkout only)
     `/magpie-setup override <skill>` - open or scaffold an agentic override in 
`.apache-magpie-overrides/`
     `/magpie-setup unadopt` - reverse the adoption (snapshot, locks, symlinks, 
hook, doc sections); preserves `.apache-magpie-overrides/` by default 
(main-checkout only)
 when_to_use: |
@@ -163,6 +164,24 @@ The drift check on every framework-skill invocation 
compares
 this against `<committed-lock>` and surfaces any mismatch as a
 proposed `/magpie-setup upgrade`.
 
+### Source locks — the same split, for trusted external sources
+
+Skills pulled from [trusted external
+sources](../../docs/skill-sources/README.md) use their **own**
+pair of locks with the identical committed-pin / local-fingerprint
+split, kept separate from the framework locks so a source re-pin
+never entangles a framework upgrade:
+
+- **`.apache-magpie.sources.lock`** (committed) — the project's
+  per-source pins, one block per source keyed by `id`
+  (`method`/`url`/`ref` + `commit`|`sha512`).
+- **`.apache-magpie.sources.local.lock`** (gitignored) — this
+  machine's per-source fetch fingerprint.
+
+They are written and reconciled by
+[`skill-sources.md`](skill-sources.md) and re-fetched on
+`upgrade`; the format and drift semantics live there.
+
 ## Detail files in this directory
 
 | File | Purpose |
@@ -170,6 +189,7 @@ proposed `/magpie-setup upgrade`.
 | [`adopt.md`](adopt.md) | First-time adoption walk-through — recognise 
existing-snapshot vs needs-bootstrap, write the two lock files, ask the user 
which skill families to wire up, create the gitignored symlinks, scaffold 
`.apache-magpie-overrides/`, install the post-checkout hook, update project 
docs. The default sub-action. |
 | [`upgrade.md`](upgrade.md) | Refresh the gitignored snapshot per the 
committed lock, reconcile any agentic overrides + symlinks against the new 
framework structure, surface conflicts. Drives the on-drift remediation flow. |
 | [`verify.md`](verify.md) | Read-only health check — snapshot present + 
intact, both lock files in sync, symlinks point at live targets, `.gitignore` 
correct, `.apache-magpie-overrides/` exists, drift status (committed vs local), 
the `setup` skill itself is current. |
+| [`skill-sources.md`](skill-sources.md) | Fetch/verify skills from trusted 
external sources listed in `<project-config>/skill-sources.md`, pin them in the 
committed `.apache-magpie.sources.lock`, and symlink the provided skills in 
exactly like framework skills. The runnable half of [trusted external skill 
sources](../../docs/skill-sources/README.md); the install gate is the adopter 
trust list. |
 | [`agents.md`](agents.md) | The agent-target registry — *which* directories 
framework-skill symlinks land in across vendors, and the 
**canonical-plus-relay** model: `.agents/skills/` is the one canonical home 
(links into the snapshot/source); every other target (`claude-code`, `github`, 
holdout natives like Windsurf / Goose) gets a per-skill relay symlink into 
`.agents/skills/`. Defines active-target selection, SKILL.md format 
portability, and the Claude-Code-only layer (sandbox/hooks). [...]
 | [`overrides.md`](overrides.md) | Agentic-override file management — open / 
scaffold an override for a framework skill, list existing overrides, help 
reconcile when the framework changes the underlying skill's structure on 
upgrade. |
 | [`unadopt.md`](unadopt.md) | Reverse the adoption — remove snapshot, locks, 
symlinks, post-checkout hook, `.gitignore` entries, the adoption sections in 
`README.md` / `AGENTS.md` / `CONTRIBUTING.md`, and the committed `setup` skill 
itself. Preserves `.apache-magpie-overrides/` by default; `--purge-overrides` 
removes it too. Surfaces the full removal plan before any write. |
@@ -217,7 +237,7 @@ accept, `upgrade`:
 5. Updates `<local-lock>` to the new fetch.
 
 **Golden rule 4 — `.gitignore` keeps the adopter repo clean.**
-Three things gitignored in the adopter repo:
+Gitignored in the adopter repo:
 
 - `<snapshot-dir>` (the entire framework snapshot — gigabytes
   potentially).
@@ -228,12 +248,19 @@ Three things gitignored in the adopter repo:
   `.claude/skills/` / `.github/skills/` / holdouts (they target
   the canonical entries) — both would dangle in a fresh clone.
   The one exception un-ignored in each dir is `magpie-setup`.
+- `.apache-magpie-sources/` (the gitignored fetch of every
+  trusted external skill source) and
+  `.apache-magpie.sources.local.lock` (per-machine source-fetch
+  fingerprint), when the adopter trusts any source. See
+  [`skill-sources.md`](skill-sources.md).
 
 **Committed**: this skill (`setup`, as the canonical
 `.agents/skills/magpie-setup/` plus its relays), the
-`<committed-lock>`, the `.apache-magpie-overrides/`
-directory, the `.gitignore` entries themselves, any
-project-doc updates the `adopt` sub-action makes.
+`<committed-lock>`, the **`.apache-magpie.sources.lock`**
+per-source pins (the project's committed vouch for each trusted
+source), the `.apache-magpie-overrides/` directory, the
+`.gitignore` entries themselves, any project-doc updates the
+`adopt` sub-action makes.
 
 **Golden rule 5 — `.agents/skills/` is canonical; everything
 else just relays into it.** Regardless of how an adopting
@@ -334,6 +361,7 @@ The skill dispatches by the first positional argument:
 | `/magpie-setup upgrade` | [`upgrade.md`](upgrade.md) | Refresh snapshot per 
`<committed-lock>` + reconcile overrides + refresh symlinks. **Main-checkout 
only** — worktrees pick up upgrades automatically via the symlink installed by 
`worktree-init`. |
 | `/magpie-setup worktree-init` | [`worktree-init.md`](worktree-init.md) | 
**Worktree-only.** Symlink the worktree's `<snapshot-dir>` to the main 
checkout's so this worktree shares one framework state. No fetch, no lock files 
written; idempotent. |
 | `/magpie-setup verify` | [`verify.md`](verify.md) | Read-only health check + 
drift status report. Works in both main and worktrees. |
+| `/magpie-setup skill-sources` (aka `skill-sources add <id>`) | 
[`skill-sources.md`](skill-sources.md) | Fetch/verify/pin/symlink skills from 
the trusted external sources the adopter listed in 
`<project-config>/skill-sources.md`. **Main-checkout only** — worktrees share 
the source snapshots via `worktree-init`. |
 | `/magpie-setup override <skill>` | [`overrides.md`](overrides.md) | Open / 
scaffold an override file. |
 | `/magpie-setup unadopt` | [`unadopt.md`](unadopt.md) | Reverse the adoption. 
Removes snapshot, locks, symlinks, hook, doc sections, and this skill itself. 
Preserves `.apache-magpie-overrides/` unless `--purge-overrides` is passed. 
**Main-checkout only.** |
 
diff --git a/.agents/skills/magpie-setup/adopt.md 
b/.agents/skills/magpie-setup/adopt.md
index 927d7871e1e..1bcf79c64cb 100644
--- a/.agents/skills/magpie-setup/adopt.md
+++ b/.agents/skills/magpie-setup/adopt.md
@@ -502,6 +502,8 @@ idempotent — re-add them if they're missing.
 ```text
 /.apache-magpie/
 /.apache-magpie.local.lock
+/.apache-magpie-sources/
+/.apache-magpie.sources.local.lock
 /.claude/settings.local.json
 /.claude/hooks/agent-guard.py
 /.claude/hooks/guards.d/
@@ -509,6 +511,19 @@ __pycache__/
 *.pyc
 ```
 
+The `/.apache-magpie-sources/` and
+`/.apache-magpie.sources.local.lock` lines keep the gitignored
+fetch of every [trusted external skill
+source](../../docs/skill-sources/README.md) and its per-machine
+fetch fingerprint out of the tree — the source counterpart of
+`/.apache-magpie/` + `/.apache-magpie.local.lock`. The committed
+per-source pins (`.apache-magpie.sources.lock`) are **not** ignored;
+they travel with the repo like `<committed-lock>`. These two lines
+are harmless when the adopter trusts no source (the paths simply
+never appear); [`skill-sources.md`](skill-sources.md) also adds
+them idempotently the first time a source is pinned on an older
+adoption.
+
 The `__pycache__/` and `*.pyc` lines (non-anchored — they match at
 any depth) keep the byte-compiled artefacts that framework skill
 scripts emit when run from the adopter checkout (e.g.
@@ -643,6 +658,25 @@ confirm, then create them. Always-on entries are surfaced
 read-only — the prompt is "confirm this list" not "edit this
 list".
 
+## Step 8b — Wire up trusted external-source skills
+
+If `<project-config>/skill-sources.md` (the adopter trust list)
+exists and lists any source, run the
+[`skill-sources`](skill-sources.md) sub-action now as a content
+pass: fetch + verify each trusted source into
+`.apache-magpie-sources/<id>/`, write both source locks, and
+create the canonical + relay `magpie-<name>` symlinks for the
+skills each source `provides` — the same wiring Step 8 does for
+framework skills, just targeting the source snapshots. Nothing is
+fetched if the trust list is absent or empty (the common case);
+this step is then a no-op.
+
+Source skills are `magpie-`-prefixed and gitignored exactly like
+framework skills, so the `.gitignore` block from
+[Step 7](#step-7--gitignore-entries-fresh-only) already covers
+their symlinks; the `.apache-magpie-sources/` snapshot dir and
+`.apache-magpie.sources.local.lock` were added there too.
+
 ## Step 9 — Scaffold `.apache-magpie-overrides/` (FRESH only)
 
 Create `<repo-root>/.apache-magpie-overrides/` (directory)
diff --git a/.agents/skills/magpie-setup/skill-sources.md 
b/.agents/skills/magpie-setup/skill-sources.md
new file mode 100644
index 00000000000..bf9fd6e071f
--- /dev/null
+++ b/.agents/skills/magpie-setup/skill-sources.md
@@ -0,0 +1,278 @@
+<!-- SPDX-License-Identifier: Apache-2.0
+     https://www.apache.org/legal/release-policy.html -->
+
+<!-- Placeholder convention (see 
../../AGENTS.md#placeholder-convention-used-in-skill-files):
+     <project-config>            → adopter's `.apache-magpie-overrides/` 
directory
+     <source-snapshot>           → `.apache-magpie-sources/<source-id>/` 
(gitignored fetch of one source)
+     <sources-lock>              → `.apache-magpie.sources.lock` (committed — 
the project's per-source pins)
+     <sources-local-lock>        → `.apache-magpie.sources.local.lock` 
(gitignored — per-machine fetch record)
+     <trust-list>                → `<project-config>/skill-sources.md` (the 
adopter opt-in / install gate)
+     <upstream>                  → adopter's public source repo (the repo this 
skill is being run in) -->
+
+# setup — `skill-sources` (pull skills from trusted external sources)
+
+Wire a skill or a whole skill-family from a **trusted external
+source** — a repo other than `apache/magpie` that ships
+Magpie-shaped skills — into the adopter repo so it behaves
+**exactly like an in-tree framework skill**: same
+`magpie-`-prefixed canonical-plus-relay symlink, same override
+layer, same eval binding.
+
+This is the runnable half of the [trusted external skill
+sources](../../docs/skill-sources/README.md) feature. The
+formats (source descriptor, `skills/<name>/source.md` pointer),
+the trust model, and the §13 carve-out are defined there and in
+[`RFC-AI-0006`](../../docs/rfcs/RFC-AI-0006.md); this sub-action
+does the fetch, the pin, and the symlink.
+
+**The rule that governs everything here:** per
+[`PRINCIPLES.md` 
§13](../../PRINCIPLES.md#13-snapshot-plus-override-never-vendored-copies),
+a source is fetched **only if the adopter has listed it in
+`<trust-list>` and committed its pin.** An org curating a source,
+or the [registry](../../docs/skill-sources/registry.md) listing
+one, never triggers an install. This sub-action reads the trust
+list and does nothing for a source that is not on it.
+
+Invocations (registered in [`SKILL.md`](SKILL.md#sub-actions)):
+
+- `/magpie-setup skill-sources` — reconcile every trusted source:
+  fetch/verify, pin, symlink the provided skills.
+- `/magpie-setup skill-sources add <source-id>` — the same flow
+  scoped to one source id (the id must already be present in
+  `<trust-list>` — this sub-action never edits the trust list;
+  vouching for a source is the adopter's committed act).
+
+**Main-checkout only**, like `adopt`/`upgrade` — a worktree picks
+up the source snapshots through the same `<snapshot-dir>` symlink
+that `worktree-init` seeds (the source snapshots live beside the
+framework snapshot and are shared the same way). Refuse to run in
+a worktree; direct the user to run it in the main checkout.
+
+## The two source locks
+
+Sources reuse the framework's [two-lock drift
+model](SKILL.md#the-two-lock-files) verbatim, in a **separate pair
+of files** so a source re-pin is never entangled with a framework
+upgrade:
+
+### `<sources-lock>` — `.apache-magpie.sources.lock` (committed)
+
+The project's **per-source pins** — one block per trusted source,
+keyed by `id`, carrying the same pin keys as the framework lock
+(`method` / `url` / `ref` + the per-method verification anchor).
+Edited only by this sub-action and `upgrade`; do not modify by
+hand.
+
+```text
+# .apache-magpie.sources.lock — committed; the project's per-source pins.
+
+- id:     acme-security-skills
+  method: git-tag
+  url:    https://github.com/acme/magpie-skills
+  ref:    v2.1.0
+  commit: <SHA the tag resolved to when pinned>
+
+- id:     example-svn-source
+  method: svn-zip
+  url:    https://downloads.example.org/skills/skills-1.4.0.zip
+  ref:    1.4.0
+  sha512: <released archive SHA-512>
+```
+
+`git-branch` sources carry `method`/`url`/`ref` and **no**
+cryptographic anchor (tip-tracking, WIP-only) — exactly as for a
+`git-branch` framework snapshot.
+
+### `<sources-local-lock>` — `.apache-magpie.sources.local.lock` (gitignored)
+
+The **per-machine fetch fingerprint** — what this checkout
+actually pulled for each source, and when. One block per source,
+keyed by `id`.
+
+```text
+# .apache-magpie.sources.local.lock — gitignored; per-machine.
+
+- id:             acme-security-skills
+  source_method:  git-tag
+  source_url:     https://github.com/acme/magpie-skills
+  source_ref:     v2.1.0
+  fetched_commit: <commit SHA on disk now>
+  fetched_at:     <ISO-8601 timestamp>
+```
+
+**Drift** for a source is a committed-vs-local mismatch on its
+block, read identically to the framework drift check: every
+framework skill (and `verify`) compares the two and, on a gap,
+proposes `/magpie-setup upgrade`. The committed lock is the pin
+that travels with the repo; the local lock is per-machine truth.
+
+## Step 0 — Pre-flight
+
+1. **Main-checkout guard.** As `adopt`/`upgrade`
+   ([`SKILL.md` Sub-actions](SKILL.md#sub-actions)): if
+   `git rev-parse --git-dir` ≠ `git rev-parse --git-common-dir`,
+   this is a linked worktree — refuse and tell the user to run
+   the reconcile in the main checkout (the worktree already sees
+   the source snapshots via its shared `<snapshot-dir>`).
+2. **Framework adopted?** Require `<committed-lock>`
+   (`.apache-magpie.lock`) and a live `<snapshot-dir>`. If the
+   framework itself is not adopted yet, stop and point the user
+   at `/magpie-setup` first — trusted sources ride on the same
+   symlink relay the framework install establishes.
+3. **Trust list present?** Read `<trust-list>`
+   (`<project-config>/skill-sources.md`). If it is absent or
+   lists no sources, there is nothing to do — say so and exit
+   (this is the common, expected case: an adopter running only
+   in-tree framework skills).
+
+## Step 1 — Resolve the trusted sources
+
+For every entry in `<trust-list>`
+([format](../../docs/skill-sources/README.md#source-descriptor)):
+
+1. **Resolve the descriptor.** An entry that is a bare
+   `id` (+ `ref` + anchor) **references** an org-curated
+   descriptor — look it up in
+   `organizations/<org>/skill-sources.md` for the org resolved by
+   the standard `project → organization → framework` precedence
+   (see [`AGENTS.md`](../../AGENTS.md#configuration-resolution-order)).
+   An entry that carries a full descriptor is used as-is. Merge:
+   the org descriptor supplies `method`/`url`/`layout`/`provides`;
+   the adopter entry supplies (and may override) `ref` + anchor —
+   the adopter's committed pin always wins.
+2. **Validate before any fetch.** `organization:` must name a
+   directory under `organizations/`; `method` must be one of
+   `git-tag`/`git-branch`/`svn-zip`; a non-`git-branch` source
+   must carry its anchor (`commit` for git-tag, `sha512` for
+   svn-zip). A source that fails validation is reported and
+   **skipped** — never fetched on a partial pin. (The
+   [skill-and-tool-validator](../../tools/skill-and-tool-validator/)
+   enforces the same shape statically on the descriptor files.)
+3. Present the resolved, validated source list (id, org, method,
+   ref, what it `provides`) and the exact fetch each will run.
+   This is the point of consent before any network egress.
+
+## Step 2 — Fetch + verify each source
+
+Into **`.apache-magpie-sources/<source-id>/`** (gitignored,
+sibling to `<snapshot-dir>` — kept separate on purpose so a
+framework `upgrade`, which deletes `<snapshot-dir>` outright, does
+**not** wipe the source snapshots). Reuse the framework [install
+recipes](../../docs/setup/install-recipes.md) **verbatim**,
+parameterized by the source `url`/`ref`:
+
+- **`git-tag` / `git-branch`** — `git clone --depth=1 --branch <ref>
+  <url> .apache-magpie-sources/<id>`. For `git-tag`, resolve
+  `HEAD` after clone and confirm it equals the committed `commit`
+  anchor; a mismatch aborts that source (the tag moved — a
+  supply-chain signal).
+- **`svn-zip`** — download the archive, `sha512sum -c` against the
+  committed `sha512`, optional `gpg --verify` against the source's
+  published `KEYS`, then unzip into
+  `.apache-magpie-sources/<id>/`. A checksum failure aborts that
+  source.
+
+A source that fails verification is left un-installed and
+reported; the others proceed. Never fall back to an unverified
+fetch.
+
+## Step 3 — Write both source locks
+
+1. **`<sources-lock>`** (committed) — for a first pin of a source,
+   write its block: `method`/`url`/`ref` + the resolved anchor
+   (`commit` from the clone for git-tag; `sha512` for svn-zip).
+   Bumping an existing pin is a deliberate project action and
+   shows up in the PR diff, exactly like a framework-lock bump.
+2. **`<sources-local-lock>`** (gitignored) — write/refresh this
+   machine's fetch fingerprint for each source
+   (`source_*` + `fetched_commit` + `fetched_at`).
+
+The two source locks + the `.apache-magpie-sources/` snapshot dir
+must be gitignored — see
+[`adopt.md` Step 7](adopt.md#step-7--gitignore-entries-fresh-only),
+which writes the block. If any line is missing (e.g. this is the
+first source on an older adoption), add it here idempotently.
+
+## Step 4 — Select the provided skills
+
+Expand each source's `provides` against its **fetched**
+`skills_root`:
+
+- `skill: <name>` → the single directory `skills/<name>/`.
+- `family: <prefix>-*` → every `skills/<prefix>-*` directory in
+  the fetched snapshot — the **same prefix-glob** as framework
+  family selection ([`adopt.md` Step 
8](adopt.md#step-8--wire-up-the-framework-skill-symlinks)),
+  computed fresh from disk, never a hard-coded list.
+
+Show the resolved skill set per source and confirm. A
+**pointer file** (`skills/<name>/source.md`) may already sit in
+the adopter's committed tree marking where a specific skill is
+expected; a `provides` entry and a pointer are two views of the
+same intent — reconcile them (a pointer with no matching
+`provides` is surfaced as an unfulfilled redirect).
+
+## Step 5 — Wire the symlinks
+
+Identical to the framework's canonical-plus-relay model
+([`adopt.md` Step 8](adopt.md#step-8--wire-up-the-framework-skill-symlinks),
+[`agents.md`](agents.md)) — the target is the source snapshot
+instead of the framework snapshot:
+
+- **Canonical (`.agents/skills/`)** — one gitignored symlink per
+  provided skill: `.agents/skills/magpie-<name>` →
+  `../../.apache-magpie-sources/<source-id>/skills/<name>/`.
+- **Relays (`.claude/skills/`, `.github/skills/`, any present
+  holdout)** — one gitignored symlink per skill:
+  `<target>/skills/magpie-<name>` →
+  `../../.agents/skills/magpie-<name>` (back through the canonical
+  entry, never at the source snapshot).
+
+Every source skill is `magpie-`-prefixed, so the same
+`magpie-*` gitignore glob and the same `symlink-lint`
+relay-through-canonical rule that cover framework skills cover
+source skills unchanged. **Never overwrite an existing committed
+skill or a framework symlink of the same name** — a source that
+`provides` a `magpie-<name>` already claimed by the framework or
+another source is a collision: surface it and stop, do not
+silently shadow.
+
+The pulled skill's eval suite rides along in the source snapshot
+at `.apache-magpie-sources/<id>/tools/skill-evals/evals/<name>/`;
+because the source keeps the framework's two-tree layout (declared
+in its descriptor `layout:` and required by the
+[layout 
contract](../../docs/skill-sources/README.md#layout-contract--skills-evals-tests)),
+the eval binding resolves after fetch with no extra wiring.
+
+## Step 6 — Chain worktree propagation
+
+As with `adopt`/`upgrade`, finish by running
+[`worktree-init`](worktree-init.md) on every linked worktree so
+each one's shared `<snapshot-dir>` and agent-dir symlinks reflect
+the new source skills. Unconditional and idempotent — a no-op when
+there are no worktrees.
+
+## Relationship to `adopt`, `upgrade`, `verify`
+
+- **`adopt`** chains into this sub-action as its final content
+  pass when `<trust-list>` lists any source, so a fresh adoption
+  that already trusts a source wires it in the same run (see
+  [`adopt.md` Step 
8b](adopt.md#step-8b--wire-up-trusted-external-source-skills)).
+- **`upgrade`** re-fetches every source per its committed
+  `<sources-lock>` pin, refreshes the symlinks, and extends drift
+  detection to the two source locks (see
+  [`upgrade.md` Step 
6f](upgrade.md#step-6f--re-fetch-trusted-external-sources)).
+- **`verify`** reports source-snapshot presence, source-symlink
+  health, and source drift (committed vs local) alongside the
+  framework checks (see
+  [`verify.md` check 
10](verify.md#10-trusted-external-source-snapshots--symlinks)).
+
+## Failure modes
+
+| Symptom | Likely cause | Remediation |
+|---|---|---|
+| "nothing to do — no trusted sources" | `<trust-list>` absent or empty | 
Expected when running only in-tree skills. Add a source to `<trust-list>` (and 
commit its pin) to install one. |
+| A source is skipped with a validation error | Unknown `organization:`, bad 
`method`, or a missing anchor on a non-`git-branch` source | Fix the descriptor 
/ pin in `<trust-list>` (or the org's `skill-sources.md`) and re-run. |
+| `git-tag` fetch aborts on a `commit` mismatch | The upstream tag was moved 
after it was pinned — a supply-chain signal | Re-review the source; only re-pin 
(bump `commit` in `<sources-lock>`) once the new tag is trusted. |
+| `svn-zip` fetch aborts on a checksum failure | The archive changed, or the 
pinned `sha512` is wrong | Re-verify the archive out-of-band before re-pinning. 
|
+| A provided `magpie-<name>` collides with a framework or another source skill 
| Two sources (or a source and the framework) claim the same prefixed name | 
Rename is the source's call; drop one `provides`/pointer to resolve locally. |
+| Worktree can't see a source skill | Source snapshots are shared via the 
worktree's `<snapshot-dir>` symlink, seeded by `worktree-init` | `/magpie-setup 
verify` in the worktree; `worktree-init` if the symlink is missing. |
diff --git a/.agents/skills/magpie-setup/upgrade.md 
b/.agents/skills/magpie-setup/upgrade.md
index fbb7586c936..25353041d14 100644
--- a/.agents/skills/magpie-setup/upgrade.md
+++ b/.agents/skills/magpie-setup/upgrade.md
@@ -657,6 +657,41 @@ missing entirely, point the operator at
 [`adopt.md` Step 9c](adopt.md#step-9c--comdev-mcp-prerequisites-asf-projects)
 to (re-)install it.
 
+## Step 6f — Re-fetch trusted external sources
+
+If `<project-config>/skill-sources.md` lists any source, reconcile
+the source snapshots the same way this upgrade reconciled the
+framework one — but from the **committed
+`.apache-magpie.sources.lock`** pins, not the framework lock, and
+**without** deleting them alongside `<snapshot-dir>` (source
+snapshots are a separate, sibling tree — see
+[Step 3](#step-3--delete-the-old-snapshot), which deletes only
+`.apache-magpie/`):
+
+1. **Source drift.** For each source, compare its
+   `.apache-magpie.sources.lock` block (committed pin) against its
+   `.apache-magpie.sources.local.lock` block (what this machine
+   fetched). Report any gap in the upgrade summary, exactly like
+   the framework drift row.
+2. **Re-fetch per the committed pin.** Run the
+   [`skill-sources`](skill-sources.md) fetch + verify for every
+   trusted source (git-tag `commit` / svn-zip `sha512` re-checked),
+   refresh `.apache-magpie-sources/<id>/`, and refresh the
+   canonical + relay `magpie-<name>` symlinks — adding skills a
+   source newly `provides`, removing ones it dropped, repairing
+   broken links. This is the source counterpart of
+   [Step 6](#step-6--refresh-framework-skill-symlinks).
+3. **Update the source local lock** to the new fetch fingerprint.
+
+Nothing happens when the trust list is absent or empty. Because
+each worktree shares main's `.apache-magpie-sources/` through the
+snapshot symlink [`worktree-init`](worktree-init.md) seeds
+(alongside `<snapshot-dir>`), the refreshed source **content** is
+visible to every worktree immediately; a worktree that predates a
+newly-`provides`-d source skill picks up its per-worktree symlink
+on its next `worktree-init` or
+`/magpie-setup verify --auto-fix-symlinks`.
+
 ## Step 7 — Update `<local-lock>`
 
 Write the new local lock with the values captured in Step
diff --git a/.agents/skills/magpie-setup/verify.md 
b/.agents/skills/magpie-setup/verify.md
index 111d9a76147..1d086200b5e 100644
--- a/.agents/skills/magpie-setup/verify.md
+++ b/.agents/skills/magpie-setup/verify.md
@@ -700,6 +700,35 @@ as ⚠ overall only, never ✗. `CONTRIBUTING.md` counts as a
 fallback for `README.md` if the adopter declared it so during
 adoption.
 
+### 10. Trusted external source snapshots + symlinks
+
+Only when `<project-config>/skill-sources.md` (the trust list)
+lists at least one source — otherwise skip this check silently
+(the adopter runs in-tree skills only). For each trusted source
+([`skill-sources.md`](skill-sources.md)):
+
+- **Committed pin present.** The source has a block in
+  `.apache-magpie.sources.lock` (`method`/`url`/`ref` + anchor).
+  Missing ⇒ ✗: the trust list vouches for a source that was never
+  pinned — run `/magpie-setup skill-sources`.
+- **Snapshot present.** `.apache-magpie-sources/<id>/` exists on
+  disk with the source's `skills_root`. Missing ⇒ ✗ with the
+  remediation `/magpie-setup skill-sources` (the fetch is
+  gitignored, so a fresh clone has none — expected, same as the
+  framework snapshot).
+- **Source drift.** The source's committed block vs its
+  `.apache-magpie.sources.local.lock` block — a mismatch ⇒ ⚠ and
+  proposes `/magpie-setup upgrade`, exactly like framework drift
+  (check 3).
+- **Symlinks live.** Every `magpie-<name>` the source `provides`
+  resolves through the canonical
+  `.agents/skills/magpie-<name>` → 
`../../.apache-magpie-sources/<id>/skills/<name>/`
+  and its relays (same rule as check 5). Dangling / misdirected ⇒
+  ✗ with `/magpie-setup verify --auto-fix-symlinks`.
+- **No name collision.** No `magpie-<name>` provided by a source
+  shadows a framework skill or another source's skill. Collision
+  ⇒ ✗ (surface, do not auto-resolve).
+
 ## After the report
 
 If every check is ✓ (or ⚠ on items the adopter has
diff --git a/.agents/skills/magpie-setup/worktree-init.md 
b/.agents/skills/magpie-setup/worktree-init.md
index 2cee737af64..39729b9f7a9 100644
--- a/.agents/skills/magpie-setup/worktree-init.md
+++ b/.agents/skills/magpie-setup/worktree-init.md
@@ -63,12 +63,25 @@ has the right symlink is a no-op.
 ln -s <main>/.apache-magpie <worktree>/.apache-magpie
 ```
 
+**Trusted external skill sources.** If the main checkout has a
+`.apache-magpie-sources/` directory (the adopter trusts at least
+one [external source](../../docs/skill-sources/README.md)), share
+it the same way so this worktree's source-skill symlinks resolve
+against one snapshot on disk:
+
+```bash
+# only when <main>/.apache-magpie-sources exists:
+ln -s <main>/.apache-magpie-sources <worktree>/.apache-magpie-sources
+```
+
 Then verify the chain end-to-end:
 
 - `ls -la <worktree>/.apache-magpie` returns a symlink pointing
   at `<main>/.apache-magpie`.
 - `ls <worktree>/.apache-magpie/skills/` lists the
   same skills as `ls <main>/.apache-magpie/skills/`.
+- when sources are in use, `ls -la <worktree>/.apache-magpie-sources`
+  is likewise a symlink to `<main>/.apache-magpie-sources`.
 
 ## Step 1b — Wire up the worktree's per-target symlinks
 

Reply via email to