fork-cohort
fork-cohort classifies every fork of a parent repository into four activation states (POWER, ACTIVE, STALE, COLD) based on GitHub Actions run history from the past year, replacing code-divergence or contributor metrics with ground-truth execution data. Use this skill to track which forks are actually running workflows in production and generate reproducible adoption metrics for the Aeon instance.
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/fork-cohort && cp -r /tmp/fork-cohort/skills/fork-cohort ~/.claude/skills/fork-cohortSKILL.md
> **${var}** — Optional `owner/repo` to scope the parent repo. If empty, infers parent from the current repo's `parent.full_name` (or, on a non-fork, uses the current repo as parent).
Today is ${today}. Bucket every fork of the parent repo by *current activation stage* — not by code divergence (`fork-fleet` already does that), not by who's contributing (`contributor-leaderboard` already does that), but by **whether the fork is actually running right now**.
This closes the visibility gap. `fork-fleet` reads pushed_at and unique commits — both hide silent abandonment, because a fork can have great code yet zero scheduled runs (workflows disabled, secrets unset, fork created and forgotten). The ground truth for "is this Aeon instance alive?" is GitHub Actions run history on the fork itself.
## Why this exists
At ~38 forks (and growing), @aaronjmars and the operator community can't support every fork — but they can support the *running* ones. "X of N forks are currently running in production" is also a more compelling social-proof claim than "N forks" when the X is real, recent, and reproducible. This skill gives both numbers.
## Cohort definitions
| Bucket | Rule |
|--------|------|
| **POWER** | At least one workflow run in the last 7 days **AND** ≥5 distinct skills set `enabled: true` in the fork's `aeon.yml` |
| **ACTIVE** | At least one workflow run in the last 7 days (and not POWER) |
| **STALE** | Last run ≥7 days ago and ≤365 days ago, **OR** last run was ≥7 days ago even if no recent run record exists |
| **COLD** | No Actions runs ever recorded **OR** last run >365 days ago |
| **UNREADABLE** | API errors prevented classification (4xx / 5xx after retry budget exhausted) |
The 7-day boundary is daily-cadence-aware — most Aeon forks have at least one daily-cron skill, so a healthy running fork should always show a run within 7 days. The 365-day fallback in COLD prevents very old never-run-since-creation forks from showing up as STALE.
## Steps
### 0. Bootstrap
```bash
mkdir -p memory/topics articles
[ -f memory/topics/fork-cohort-state.json ] || echo '{"forks":{},"last_run":null}' > memory/topics/fork-cohort-state.json
```
### 1. Resolve parent repo
```bash
if [ -n "${var}" ]; then
PARENT_REPO="${var}"
else
PARENT_REPO=$(gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner) --jq '.parent.full_name // .full_name')
fi
PARENT_OWNER="${PARENT_REPO%%/*}"
```
### 2. List forks (paginated, single call)
```bash
gh api "repos/${PARENT_REPO}/forks" --paginate \
--jq '[.[] | select(.archived != true and .disabled != true) | {full_name, owner: .owner.login, default_branch, pushed_at, stargazers_count, created_at}]'
```
If the call fails after one retry (sleep 10s on 5xx, sleep 60s on 429), exit `FORK_COHORT_API_FAIL` with a single failure notify. Skip archived/disabled forks.
If the parent has zero forks: log `FORK_COHORT_NO_FORKS` and stop (no notify).
### 3. Per-fork: last workflow run
For each fork, query the most recent workflow run timestamp:
```bash
LAST_RUN=$(gh api "repos/${FORK_FULL_NAME}/actions/runs?per_page=1" \
--jq '.workflow_runs[0].updated_at // empty' 2>/dev/null)
```
Empty / null result + 200 status → fork has never run a workflow (`COLD` candidate).
Error handling — apply once per fork, then mark `UNREADABLE` and continue:
- **404** (Actions disabled by fork owner): treat as `COLD` (workflows never ran). Many fork owners disable Actions on fork creation; this is indistinguishable from "workflows enabled but never triggered" by the API and either way means the fork is not running.
- **403** (rate-limited or scope): retry once after 60s. Persistent → `UNREADABLE`.
- **5xx**: retry once after 10s. Persistent → `UNREADABLE`.
Cap total fork-processing at 80 forks per run. If more, sort by `pushed_at` desc and trim (log `truncated_at=80`). At 38-fork scale this is dead code; the cap exists so a viral fork day doesn't blow the run budget.
### 4. Per-fork: enabled skill count (only for ACTIVE candidates)
The POWER bucket requires reading the fork's `aeon.yml`. Skip this entire step for forks that are already classified COLD or STALE — saves a call per inactive fork.
```bash
gh api "repos/${FORK_FULL_NAME}/contents/aeon.yml?ref=${FORK_DEFAULT_BRANCH}" \
--jq '.content' 2>/dev/null | base64 -d > /tmp/fork-aeon.yml || true
```
Count distinct skills with `enabled: true` (matches both inline `{ enabled: true }` and multiline form):
```bash
ENABLED_COUNT=$(grep -E "enabled:\s*true" /tmp/fork-aeon.yml 2>/dev/null | wc -l | tr -d ' ')
```
If `aeon.yml` is missing (fork stripped it) or unreadable, treat as `ENABLED_COUNT=0` and the fork stays ACTIVE (not POWER).
### 5. Classify each fork
```
days_since_run = (now - last_run_iso8601) / 86400
(∞ if last_run is empty)
if 404_on_runs OR days_since_run > 365:
bucket = COLD
elif days_since_run < 7 and ENABLED_COUNT >= 5:
bucket = POWER
elif days_since_run < 7:
bucket = ACTIVE
elif days_since_run >= 7:
bucket = STALE
else:
bucket = UNREADABLE
```
### 6. Compute week-over-week delta
Read `memory/topics/fork-cohort-state.json` (prior run). For every fork present in both runs, compute the bucket transition:
| Transition | Tag |
|------------|-----|
| (any) → POWER | `LEVELED_UP` |
| ACTIVE → STALE | `WENT_STALE` |
| STALE → ACTIVE / POWER | `REVIVED` |
| (absent) → ACTIVE / POWER | `NEW_ACTIVE` |
| ACTIVE / POWER → COLD | `WENT_COLD` |
| (absent) → any | `NEW_FORK` |
| POWER → ACTIVE | `DROPPED_FROM_POWER` |
`WENT_STALE` is the highest-priority operator-action signal — those are the "fork owners who got busy elsewhere or hit a config wall" cohort that benefits most from a check-in. `LEVELED_UP` and `REVIVED` are the bright spots worth surfacing.
### 7. Pick the verdict (one-line lede)
Priority order:
1. `LEVELED_UP: {N} forks crossed POWER threshold` — if any LEVELED_UP transitions
2. `REVIVED: {N} stale forks running again` — if any REVIVED
3. `WENT_STALEMention/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.