# Upstream Drift Check (refactor Step 0b)

Loaded on demand by `/multi-agent:refactor` Step 0b. The SKILL.md carries the step intro and its rules; this file is the full procedure.

## Source configuration

The upstream mapping is **configuration, never hardcoded** (it can reference private sources, so it stays out of the shipped skill). Read it from `~/.claude/multi-agent-preferences.json` at `global.derivedSkillSources` (an array). Each entry:

```jsonc
{
  "label": "<human name for this derivation>",
  "localPath": "<repo-relative dir where our derived copy lives>",
  "upstreamMarketplace": "<installed marketplace name>",   // resolved under ~/.claude/plugins/cache/<marketplace>/
  "upstreamPlugin": "<plugin name>",
  "upstreamSkills": ["<skill-a>", "<skill-b>"],            // the upstream skills we took
  "derivedFromVersion": "<x.y.z>",                         // the version we last synced from
  "upstreamVersionSource": "marketplace.json",             // which manifest is authoritative; default marketplace.json
  "upstreamLocalClone": "<optional path>",                 // working copy of the upstream repo, preferred over the cache
  "upstreamRepoUrl": "<optional https url>"                // used when neither a clone nor the marketplace is available
}
```

## Which source is authoritative

**The plugin cache is a mirror, not the authority.** `~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/` only holds whatever the last `claude plugin marketplace update` fetched, so it can sit several releases behind upstream. Resolve in the order below and never let the cache alone produce an "up to date" verdict.

**Which manifest carries the version** is `upstreamVersionSource`, default `marketplace.json`. That is what a marketplace consumer actually resolves, and some upstreams keep per-plugin `plugin.json` versions deliberately unused - reading those records a version nobody ships.

## Procedure

1. If `global.derivedSkillSources` is missing or empty -> **skip** this step and report "no derived-skill sources configured" (nothing to check). Never invent a source.
2. For each entry, resolve the current upstream version, in this order, stopping at the first that answers:
   - **`upstreamLocalClone`** if set: read `<clone>/.claude-plugin/<upstreamVersionSource>`. Also run `git -C <clone> fetch --dry-run` (or compare against `@{u}`) and say so when the clone is itself behind, so a stale working copy is not silently trusted either.
   - **`upstreamRepoUrl`**: read the same manifest over the API (`gh api` / `WebFetch`). A private upstream can 404 for the currently active account even when the repo exists - that is an unreachable result, not a "no drift" result.
   - **Plugin cache** under `~/.claude/plugins/cache/<upstreamMarketplace>/<upstreamPlugin>/*/`: last resort only. When the cache is the only source that answered, report the entry as **`unverified (cache only)`**, never as "up to date", and add a plan item to configure `upstreamLocalClone`.
   - If nothing is reachable, record the entry as "upstream unreachable" and move on (do not fail the whole run).
3. Compare the resolved upstream version to `derivedFromVersion`:
   - equal, from an authoritative source -> "up to date" (no drift)
   - equal, from the cache only -> "unverified (cache only)"
   - newer -> **drift**: read the CHANGELOG entries between the two versions, and diff each `upstreamSkills` SKILL.md (+ any templates) against our `localPath` copy. Summarize what changed upstream (bug fixes, new sections, new templates, renamed inputs). Ignore changelog entries that only touch skills outside `upstreamSkills` - they are not ours to port.
4. Emit the drift table (plan band D):

```
| Derivation | Our copy (localPath) | Derived-from | Upstream now | Drift | What changed upstream |
|------------|----------------------|--------------|--------------|-------|-----------------------|
| <label>    | <path>               | 0.2.1        | 0.3.0        | YES   | <changelog + diff summary> |
```

5. For each drifted entry, add a band-D plan item: "port upstream <plugin> <version> changes into <localPath>", with the specific skills to update. Do not auto-apply upstream changes  -  they go through Step 5 approval like everything else, and after porting, bump the entry's `derivedFromVersion`.
