fleet-skill-adoption
fleet-skill-adoption reads each POWER+ACTIVE fork's aeon.yml configuration to count which upstream skills have enabled: true, then ranks the 157+ skill catalog by fleet adoption percentage. Use this skill to identify which skills operators have validated in production and which need upstream re-examination, answering the inverse question to fork-skill-gap by measuring actual enablement rather than installation or missing features.
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/fleet-skill-adoption && cp -r /tmp/fleet-skill-adoption/skills/fleet-skill-adoption ~/.claude/skills/fleet-skill-adoptionSKILL.md
> **${var}** — Optional. Pass `dry-run` to skip notify (state and article still write). Pass `owner/repo` to override the parent repo. Combine with a space (`dry-run owner/repo`) for both.
Today is ${today}. `fork-skill-gap` answers *"what's in upstream that this fork hasn't adopted?"* — a per-fork **gap** view keyed on skill *presence* in each fork's `skills.json`. It cannot answer the inverse, fleet-level question: **"which skills has the fleet actually validated by turning them on?"** With the upstream catalog at 157+ skills (34 landed in a single merge, #219), a fork operator staring at the menu has no signal for which skills are battle-tested in production across the cohort. This skill closes that layer: it reads each POWER+ACTIVE fork's `aeon.yml`, counts per-slug `enabled: true`, and ranks the catalog by fleet penetration.
## Why this exists
A 157-skill catalog is a menu no operator can evaluate cold. `fork-skill-gap` shows what a fork is *missing*; it says nothing about whether the missing skill is worth adopting. Adoption is the fleet's revealed preference: a skill enabled by 68% of active forks is one that survived contact with real operators; a skill enabled by nobody after eight weeks is one upstream should re-examine.
This skill turns enablement into a leaderboard. It is the demand-side complement to `fork-skill-gap`'s supply-side gap report — same cohort, same Sunday window, opposite question. Crucially it measures `enabled: true` in `aeon.yml` (the skill is *running*), not mere presence in `skills.json` (the skill is *installed*) — that distinction is exactly what separates this skill from `fork-skill-gap` and `fork-skill-digest`.
## Scope and inputs
Reads from two places, with graceful degradation:
1. **`memory/topics/fork-cohort-state.json`** (primary) — gives the POWER + ACTIVE fork list. When present and fresh (≤8 days), this skill targets only POWER + ACTIVE forks (the audience whose enablement choices carry signal — STALE/COLD forks aren't running anything, so their `aeon.yml` is noise).
2. **`gh api repos/{parent}/forks`** (fallback / first run) — when cohort state is absent, missing the forks list, or stale, build a POWER+ACTIVE list live using the same activation rule as `fork-cohort` (≥1 workflow run in the last 7 days).
3. **`gh api repos/{parent}/contents/skills.json`** — the upstream slug universe + per-slug `category` and `updated` date (used to flag freshly-shipped skills so they aren't shamed in the bottom-15 before the fleet has had time to adopt them).
4. **Per fork: `gh api repos/{fork}/contents/aeon.yml`** — the enablement source. Base64-decoded, parsed for `enabled: true` slugs.
The intent: when `fork-cohort` runs Sunday 19:00 and `fork-skill-gap` at 21:00, `fleet-skill-adoption` at 22:00 reuses the same cohort list. When cohort hasn't been enabled yet, it still works — just slower (live fork classification).
Writes:
- `memory/topics/fleet-skill-adoption-state.json` — per-slug rolling 8-week adoption history
- `articles/fleet-skill-adoption-${today}.md` — leaderboard article (every non-error run, including QUIET)
- `memory/logs/${today}.md` — one log block per run
- Notification via `./notify` — only when the top-10 moved or it's the first baseline run (see step 8)
## Steps
### 0. Bootstrap
```bash
mkdir -p memory/topics articles
[ -f memory/topics/fleet-skill-adoption-state.json ] || cat > memory/topics/fleet-skill-adoption-state.json <<'EOF'
{"parent":null,"last_run":null,"last_status":null,"readable_forks":null,"upstream_skill_count":null,"history":[],"slugs":{}}
EOF
```
If `jq empty` fails on the state file (corrupt JSON from an aborted write), back it up to `.bak`, reset to the empty template above, and tag the run `STATE_CORRUPT`. Continue — a fresh state file means no prior week to diff, which is the correct post-corruption behaviour (WoW deltas are simply omitted).
`slugs` is a map keyed by slug: `{enabled_count, adoption_pct, category, is_new, last_seen}`. `history` is a rolling list (cap 8 entries) of `{date, readable_forks, top10:[{slug,pct}]}` used for WoW comparison and trend.
### 1. Parse var
- Split `${var}` on whitespace. Tokens: `dry-run`, anything matching `^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$` (treated as `PARENT_OVERRIDE`), anything else.
- If any unknown token is present → log `FLEET_SKILL_ADOPTION_BAD_VAR: ${var}` and exit (no notify).
- `MODE=dry-run` if the `dry-run` token is present, else `execute`.
### 2. Resolve parent repo
```bash
if [ -n "$PARENT_OVERRIDE" ]; then
PARENT_REPO="$PARENT_OVERRIDE"
else
PARENT_REPO=$(gh api "repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)" --jq '.parent.full_name // .full_name')
fi
```
If `state.parent` is set and differs from the resolved `PARENT_REPO` → log `FLEET_SKILL_ADOPTION_PARENT_CHANGED`, reset `slugs` and `history` to empty, update `state.parent`. (A different parent means a different catalog; old adoption numbers are meaningless.)
### 3. Read upstream skills.json (the slug universe)
```bash
gh api "repos/${PARENT_REPO}/contents/skills.json" \
--jq '.content' 2>/dev/null | base64 -d > /tmp/fsa-upstream.json
UPSTREAM_COUNT=$(jq -r '.skills | length' /tmp/fsa-upstream.json)
jq -r '.skills[] | "\(.slug)\t\(.category // "other")\t\(.updated // "")"' /tmp/fsa-upstream.json > /tmp/fsa-universe.tsv
```
If `skills.json` is missing/empty/invalid → log `FLEET_SKILL_ADOPTION_NO_UPSTREAM_MANIFEST`, exit (no notify). The upstream manifest is the canonical slug universe; without it there is no leaderboard to build.
**Freshness flag.** A slug is `is_new` when its `updated` date is within the last 14 days. New skills are reported separately and **excluded from the bottom-15 least-adopted table** — a skill that shipped four days ago hasn't had a weekly cycle to be adopted, so ranking it "least adopted" is noise, not signal.
### 4. Build the POWER + ACTIVE fork list
Try the cached path first (identical freshness logic to `fork-skill-gap` so the two skills agreeMention/keyword sweep on social platforms for [REPLACE: KEYWORDS] — trends, sentiment, top posts
5 concrete real-life actions, leverage-scored against open loops with specificity and anti-fluff gates
Curated AI-agent tweets, clustered into narratives with insight summaries
Tracker of AI agent substitution signals — which roles, companies, and industries show real headcount displacement. Named roles + real deployments only.
Competitive-intelligence digest on the AI agent framework space — momentum, releases, breaking changes across a curated watchlist
Cross-domain market pulse from AIXBT's free grounding endpoint — crypto, macro, tradfi, geopolitics. Refreshes taxonomy references (clusters, chains) as a bonus.
Pre-batch API provider health check — detects credit exhaustion or auth failure for every configured provider key before the scheduled batch runs, giving the operator a window to act before skills degrade
List a wallet's live ERC-20 token approvals on Base and flag unlimited / risky spender grants. Keyless via Base RPC (eth_getLogs + eth_call) — no explorer key needed.