contributor-spotlight
contributor-spotlight converts weekly fork-cohort data into a single named recognition post highlighting one active fork operator, their shipped work, star count, and enabled skills. Use this skill to create social acknowledgment artifacts that feed directly into thread-formatter for distribution, closing the loop between fork analytics and operator recognition while preventing duplicate features via deduplication history.
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/contributor-spotlight && cp -r /tmp/contributor-spotlight/skills/contributor-spotlight ~/.claude/skills/contributor-spotlightSKILL.md
> **${var}** — Optional. Pass `dry-run` to skip the notification (article still writes, state still updates). Pass an `owner/repo` to override the auto-pick for one run. Empty = auto-pick from the most recent fork-cohort run.
Today is ${today}. Convert the most recent `fork-cohort` output into one named recognition post per week. `fork-cohort` produces a cohort table; this skill turns one row of that table into a 150-word human moment that names the operator, what they shipped, and why it matters.
## Why this exists
`fork-cohort` (PR #152) identifies POWER and ACTIVE forks weekly but produces a data table — not a recognition. `contributor-leaderboard` ranks contributors by upstream PRs but doesn't see what's happening inside a fork. Neither closes the loop between *we have fork data* and *we do something social with it*.
contributor-spotlight is the social loop: one fork operator per week gets a named callout — their handle, their fork, the skills they enabled, their star count, a one-line "keep shipping" close. That's the flywheel — operators who feel seen attract other operators. This is also formatted to feed `thread-formatter` directly, so the post is a tweetable artifact, not just a Telegram blip.
## Config
No new secrets. No new env vars. Reads:
- `articles/fork-cohort-*.md` — most recent (look back up to 14 days). Picks the POWER cohort roster.
- `memory/topics/fork-cohort-state.json` — authoritative bucket assignments, fallback if no article exists.
- `memory/topics/contributor-spotlight-history.json` — dedup state. Same fork is not featured two weeks running.
Writes:
- `articles/contributor-spotlight-${today}.md` — the recognition post.
- `memory/topics/contributor-spotlight-history.json` — appends `{fork, featured_at, role}` for last 26 entries (≈6 months at weekly cadence).
- `memory/logs/${today}.md` — log block.
## Steps
### 0. Bootstrap
```bash
mkdir -p memory/topics articles
[ -f memory/topics/contributor-spotlight-history.json ] || echo '{"history":[]}' > memory/topics/contributor-spotlight-history.json
```
### 1. Parse var
- If `${var}` matches `^dry-run` → `MODE=dry-run`. Strip the prefix; remainder is treated as an owner/repo override.
- Otherwise `MODE=execute`.
- If the remaining var matches `^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$` → `OVERRIDE_FORK=$var`. Otherwise `OVERRIDE_FORK=auto`.
- If the remaining var is non-empty and doesn't match the owner/repo pattern → log `SPOTLIGHT_BAD_VAR: ${var}` and exit (no article, no notify).
### 2. Locate the source cohort data
```bash
COHORT_ARTICLE=$(ls -t articles/fork-cohort-*.md 2>/dev/null | head -1)
COHORT_STATE=memory/topics/fork-cohort-state.json
```
If `COHORT_ARTICLE` is empty AND `COHORT_STATE` is missing → log `SPOTLIGHT_NO_COHORT_DATA` and exit (no notify). The skill cannot fabricate cohort assignments.
If `COHORT_ARTICLE` exists, check the date in the filename. If it's older than 14 days, log `SPOTLIGHT_STALE_COHORT: $COHORT_ARTICLE older than 14d` and continue with `COHORT_STATE` as the source instead. (The state file is updated every fork-cohort run, so it's the more reliable signal when articles are sparse.)
### 3. Pick the fork to feature
If `OVERRIDE_FORK` is set:
- Verify it appears in `COHORT_STATE.forks` with bucket `POWER` or `ACTIVE`. If not, log `SPOTLIGHT_BAD_OVERRIDE: $OVERRIDE_FORK not in cohort` and exit (no notify).
- Otherwise `FEATURED_FORK=$OVERRIDE_FORK`.
Otherwise auto-pick:
1. Build the candidate list from `COHORT_STATE.forks`:
- Keep entries with bucket `POWER` (preferred) or `ACTIVE` (fallback if no POWER forks exist).
- Drop bot owners: `dependabot[bot]`, `github-actions[bot]`, `aeonframework[bot]`, anything ending in `[bot]`.
- Drop the parent repo's owner — this skill is for *fork operators*, not the upstream maintainer.
2. Drop forks featured in the last 4 weeks per `contributor-spotlight-history.json`.
3. Rank remaining candidates by:
- Primary: `enabled_count` desc (more skills = more sustained adoption)
- Secondary: `stargazers` desc
- Tertiary: `days_since_run` asc (most-recently active first)
4. Pick the top entry. `FEATURED_FORK=<owner/repo>`.
If the candidate list is empty (e.g. only the parent + bots, or every fork was featured in the last 4 weeks): log `SPOTLIGHT_NO_CANDIDATES` and exit cleanly without notifying.
### 4. Pull richer context for the featured fork
```bash
FORK_OWNER="${FEATURED_FORK%%/*}"
FORK_NAME="${FEATURED_FORK##*/}"
# Repo-level stats
gh api "repos/${FEATURED_FORK}" \
--jq '{stars: .stargazers_count, forks: .forks_count, default_branch, created_at, pushed_at, description, html_url}' \
> /tmp/contrib-repo.json 2>/dev/null || echo '{}' > /tmp/contrib-repo.json
# Extract default_branch into a shell var — step 5 needs it to address the right ref.
# Falls back to "main" when the API call failed (contrib-repo.json is "{}") or
# when GitHub returned the field as null/missing.
FORK_DEFAULT_BRANCH=$(jq -r '.default_branch // "main"' /tmp/contrib-repo.json)
[ -z "$FORK_DEFAULT_BRANCH" ] || [ "$FORK_DEFAULT_BRANCH" = "null" ] && FORK_DEFAULT_BRANCH=main
# Recent commit activity (last 30 days, default branch)
SINCE=$(date -u -d "${today} - 30 days" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -j -v-30d -f %Y-%m-%dT%H:%M:%SZ "${today}T00:00:00Z" +%Y-%m-%dT%H:%M:%SZ)
COMMITS_30D=$(gh api "repos/${FEATURED_FORK}/commits?since=${SINCE}&per_page=100" \
--jq 'length' 2>/dev/null || echo 0)
# Top contributor on the fork (likely the operator themselves; could be co-op)
gh api "repos/${FEATURED_FORK}/stats/contributors" \
--jq '[.[] | select(.total > 0)] | sort_by(.total) | reverse | .[0:3] | [.[] | {login: .author.login, total}]' \
> /tmp/contrib-top.json 2>/dev/null || echo '[]' > /tmp/contrib-top.json
```
`gh api` retries are baked into `gh` itself; on persistent 4xx/5xx, treat the call as empty and continue. Missing data degrades the article (e.g. "30-day commits unavailable") but does not abort the run.
### 5. IdentifyMention/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.