ワンクリックで
contributor-spotlight
// Weekly recognition post for one fork operator — converts fork-cohort cohort data into a named human moment (POWER fork callout with their work, stars, and skills enabled)
// Weekly recognition post for one fork operator — converts fork-cohort cohort data into a named human moment (POWER fork callout with their work, stars, and skills enabled)
Allocate $10/day worth of $MIROSHARK to top tweeters about the project — rewards organic engagement
Daily report on new stars, forks, and traffic for watched repos
Audit every enabled skill's upstream file dependencies for staleness — flags chained skills about to consume yesterday's article or a long-dead topic file
Write an article about the project through a surprising lens — connecting it to current events, trends, philosophy, or comparable projects
Build a feature for the watched repo — picks from yesterday's repo-actions ideas first
Promote important recent log entries into MEMORY.md
| name | contributor-spotlight |
| description | Weekly recognition post for one fork operator — converts fork-cohort cohort data into a named human moment (POWER fork callout with their work, stars, and skills enabled) |
| var | |
| tags | ["meta","community"] |
${var} — Optional. Pass
dry-runto skip the notification (article still writes, state still updates). Pass anowner/repoto 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.
fork-cohort (PR #152) identifies POWER and ACTIVE forks weekly but produces a data table — not a recognition. fork-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.
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.mkdir -p memory/topics articles
[ -f memory/topics/contributor-spotlight-history.json ] || echo '{"history":[]}' > memory/topics/contributor-spotlight-history.json
${var} matches ^dry-run → MODE=dry-run. Strip the prefix; remainder is treated as an owner/repo override.MODE=execute.^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$ → OVERRIDE_FORK=$var. Otherwise OVERRIDE_FORK=auto.SPOTLIGHT_BAD_VAR: ${var} and exit (no article, no notify).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.)
If OVERRIDE_FORK is set:
COHORT_STATE.forks with bucket POWER or ACTIVE. If not, log SPOTLIGHT_BAD_OVERRIDE: $OVERRIDE_FORK not in cohort and exit (no notify).FEATURED_FORK=$OVERRIDE_FORK.Otherwise auto-pick:
COHORT_STATE.forks:
POWER (preferred) or ACTIVE (fallback if no POWER forks exist).dependabot[bot], github-actions[bot], aeonframework[bot], anything ending in [bot].contributor-spotlight-history.json.enabled_count desc (more skills = more sustained adoption)stargazers descdays_since_run asc (most-recently active first)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.
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
# 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.
# Read the fork's aeon.yml to count enabled skills, and diff against parent's
gh api "repos/${FEATURED_FORK}/contents/aeon.yml?ref=${FORK_DEFAULT_BRANCH}" \
--jq '.content' 2>/dev/null | base64 -d > /tmp/fork-aeon.yml || true
Extract the list of enabled skills (lines matching enabled:\s*true with the skill key on the same logical line). Pattern (loose, comment-skipping):
ENABLED_SKILLS=$(grep -E '^[[:space:]]+[a-zA-Z0-9_-]+:[[:space:]]*\{[^}]*enabled:[[:space:]]*true' /tmp/fork-aeon.yml \
| sed -E 's/^[[:space:]]+([a-zA-Z0-9_-]+):.*/\1/' | sort -u)
Compute the cohort signal:
ENABLED_COUNT = wc -l of $ENABLED_SKILLSOPERATOR_AUTHORED = enabled skills NOT present in the parent's skills/ directory (gh api repos/${PARENT_REPO}/contents/skills to list — fall back to empty list if the call fails). These are the operator-authored or operator-imported novel skills.The OPERATOR_AUTHORED list is the most newsworthy data point: a skill the operator built or pulled from somewhere other than upstream is a genuine contribution moment. If the list is empty, fall back to the highest-weight enabled skills (the ones most representative of an operator who chose their stack).
The article is one paragraph (≈140-180 words) and one bullet list (the enabled skills). The paragraph names:
@${FORK_OWNER}).${FEATURED_FORK}) and what it does (use the GitHub repo description if non-empty; otherwise "an Aeon fork").${COMMITS_30D} commits in the last 30 days, OR last run ${days_since_run} days ago.${ENABLED_COUNT} enabled skills. If OPERATOR_AUTHORED is non-empty, name 2-3 of those skills explicitly ("running their own ${skill_a} alongside upstream ${skill_b}").The paragraph must avoid:
Path: articles/contributor-spotlight-${today}.md. Overwrite if exists.
# Contributor Spotlight — ${today}
**This week:** @${FORK_OWNER} — \`${FEATURED_FORK}\` (${stars}⭐)
---
${recognition paragraph from step 6}
## Stack
- ${ENABLED_COUNT} skills enabled
- Last run: ${days_since_run} days ago
- 30-day commit activity: ${COMMITS_30D} commits
- Cohort: ${POWER | ACTIVE}
## Skills running
(One bullet per enabled skill. Mark operator-authored skills with `★` so the diverged work is legible at a glance.)
- ★ ${operator_authored_skill_1}
- ${enabled_skill_1}
- ${enabled_skill_2}
- ...
## Top contributors
| Login | Commits |
|-------|---------|
| @${login_1} | N |
(Up to 3 rows. Skip section entirely if the API call returned empty.)
## Why this fork is worth looking at
${one-sentence answer — derives from operator-authored skills if present, otherwise from enabled-stack composition. Examples: "First fork to wire ${X} alongside the upstream daily content stack." / "Running the largest enabled-skill set in the cohort (${N} skills active)." / "Three weeks of unbroken daily runs and counting."}
---
*Recognition rotates weekly. Same fork is not featured twice within 4 weeks. Picked from `articles/fork-cohort-*.md` POWER (then ACTIVE) cohort.*
[Visit the fork →](${html_url})
Cap the article at ~250 lines. If ENABLED_SKILLS exceeds 30 entries, render the top 30 by name (alphabetical) and append ... and N more.
The notification is the same paragraph as the article body (step 6), trimmed to fit Telegram's render budget. Format:
*Contributor Spotlight — ${today}*
@${FORK_OWNER} — ${FEATURED_FORK} (${stars}⭐)
${recognition paragraph}
Stack: ${ENABLED_COUNT} skills enabled · last run ${days_since_run}d ago · ${COMMITS_30D} commits in 30d
${If OPERATOR_AUTHORED non-empty:}
Diverged work:
- ${operator_authored_skill_1}
- ${operator_authored_skill_2}
Article: articles/contributor-spotlight-${today}.md
[Fork →](${html_url})
Cap at ~2200 chars total. The paragraph and bullet list together should never exceed ~1600 chars; if they do, trim the diverged-work bullets first, then the trailing close sentence.
If MODE == dry-run: skip notify, log SPOTLIGHT_DRY_RUN, write article and history anyway.
Otherwise call ./notify with the message from step 8.
Update memory/topics/contributor-spotlight-history.json:
{
"history": [
{
"fork": "${FEATURED_FORK}",
"owner": "${FORK_OWNER}",
"featured_at": "${today}",
"cohort": "POWER|ACTIVE",
"enabled_count": ${ENABLED_COUNT},
"stars_at_feature": ${stars},
"operator_authored_count": ${count of OPERATOR_AUTHORED},
"commits_30d": ${COMMITS_30D}
}
]
}
Cap to last 26 entries (≈6 months of weekly recognition). When trimming, drop oldest first.
memory/logs/${today}.md## Contributor Spotlight
- **Skill**: contributor-spotlight
- **Featured**: ${FEATURED_FORK} (${stars}⭐, cohort=${POWER|ACTIVE})
- **Operator**: @${FORK_OWNER}
- **Stack**: ${ENABLED_COUNT} enabled skills · ${COMMITS_30D} commits in 30d
- **Operator-authored skills**: ${count} (${comma-separated names})
- **Article**: articles/contributor-spotlight-${today}.md
- **Source**: ${COHORT_ARTICLE | COHORT_STATE}
- **Notification sent**: ${yes | no — dry-run | no — SPOTLIGHT_NO_CANDIDATES | no — SPOTLIGHT_NO_COHORT_DATA}
- **Status**: ${SPOTLIGHT_OK | SPOTLIGHT_DRY_RUN | SPOTLIGHT_NO_CANDIDATES | SPOTLIGHT_NO_COHORT_DATA | SPOTLIGHT_STALE_COHORT | SPOTLIGHT_BAD_VAR | SPOTLIGHT_BAD_OVERRIDE}
| Status | Meaning | Notify? |
|---|---|---|
SPOTLIGHT_OK | Featured one fork, article written, history updated | Yes |
SPOTLIGHT_DRY_RUN | var=dry-run mode | No (article + history still write) |
SPOTLIGHT_NO_CANDIDATES | All eligible forks featured in last 4 weeks, or only bots/parent in cohort | No |
SPOTLIGHT_NO_COHORT_DATA | No fork-cohort article in last 14 days AND no state file | No |
SPOTLIGHT_STALE_COHORT | Latest cohort article >14 days old; ran against state file as fallback | Yes (note staleness in article) |
SPOTLIGHT_BAD_VAR | ${var} was non-empty, non-dry-run, and not a valid owner/repo | No |
SPOTLIGHT_BAD_OVERRIDE | ${var} was a valid owner/repo but absent from cohort (or wrong bucket) | No |
fork-cohort already surfaces them in the WENT_STALE block.[bot]) is loose-but-sufficient at current scale.Uses gh api for all GitHub queries — handles auth internally, no env-var-in-headers, no curl. The fallback to COHORT_STATE (a local JSON file) keeps the skill functional even when gh api is rate-limited or sandbox-blocked, because the state file holds the same per-fork bucket assignment that the article would otherwise carry. The only outbound call beyond gh api is ./notify itself, which uses the standard postprocess-notify pattern.
fork-cohort (Sunday 19:00 UTC) — produces the source data this skill picks from. Run order matters: schedule contributor-spotlight one hour later (Sunday 20:00 UTC) so today's cohort is fresh.fork-contributor-leaderboard (Sunday 17:30 UTC) — adjacent recognition skill ranked by upstream-PR contribution. Spotlight focuses on fork-internal work; leaderboard focuses on upstream-PR work. Together they cover both directions of the contributor flywheel.thread-formatter (when run after this skill) — can pick up the spotlight as the day's top event and reformat into a 5-tweet thread, turning the recognition into a tweetable artifact.