Skip to main content
ClaudeWave
Skill510 repo starsupdated today

fork-fleet

Fork-fleet catalogs active forks of an Aeon repository, compares each fork's main branch against upstream to detect diverged work, and assigns tiers (PROMOTE/REVIEW/NOTE) based on contribution value and activity recency. Use this skill weekly to identify which community forks have meaningful improvements worth merging upstream, filter out noise from routine edits, and track per-fork progress across weeks without notification fatigue for dormant repositories.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/fork-fleet && cp -r /tmp/fork-fleet/skills/fork-fleet ~/.claude/skills/fork-fleet
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

<!-- autoresearch: variation B — sharper output: verdict + PROMOTE/REVIEW/NOTE tiers + week-over-week delta + notify gate -->
> **${var}** — Optional `owner/repo` to analyze a single fork. If empty, scans all active forks.

Today is ${today}. Track Aeon's fork fleet: discover active forks, surface the fork work that actually matters, and gate notifications on real change.

## Operating principles
- **Verdict first, catalog second.** Operator reads one line and knows if action is needed.
- **Silent when nothing changed.** Weekly cadence + dormant fleet = a read-once habit to kill.
- **Per-fork compare is one call, not three.** `/compare/{owner}:main...{fork_owner}:main` returns ahead/behind/unique commits/files in a single round-trip.
- **Substance ≠ noise.** A new `skills/*/SKILL.md` is worth 100 cron-time edits in `aeon.yml`. Score accordingly.

## Steps

### 0. Bootstrap + load state

```bash
mkdir -p memory/topics
[ -f memory/instances.json ] || echo '{}' > memory/instances.json
[ -f memory/topics/fork-fleet-state.json ] || echo '{"forks":{},"last_run":null}' > memory/topics/fork-fleet-state.json
```

Read `memory/instances.json` → set of repo `full_name`s that are managed instances (tagged separately from organic community forks in the report).
Read `memory/topics/fork-fleet-state.json` → prior run's per-fork `{pushed_at, ahead_by, default_branch, new_skill_count}` keyed by `full_name`. Used for the what-changed delta.

### 1. Resolve parent + list forks

```bash
PARENT_REPO=$(gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner) --jq '.parent.full_name // .full_name')
PARENT_NAME="${PARENT_REPO##*/}"
PARENT_OWNER="${PARENT_REPO%%/*}"
```

Single paginated listing — includes `default_branch`, `archived`, `disabled`, `pushed_at`:

```bash
gh api "repos/${PARENT_REPO}/forks" --paginate \
  --jq '[.[] | {full_name, owner: .owner.login, default_branch, pushed_at, pushed_at_epoch: (.pushed_at | fromdateiso8601), stargazers_count, open_issues_count, archived, disabled, description}]'
```

Skip `archived=true` or `disabled=true`. Retain the rest as the total fork population (`N_TOTAL`).

**If `${var}` is set** to `owner/repo`, filter to that single fork and skip step 2 (treat as "active").

### 2. Classify by activity window

- **Active** = `pushed_at` within last 30 days.
- **Stale** = 30–365 days.
- **Dormant** = >365 days or never pushed after creation.

If zero active forks AND no state change (no new forks, no forks that flipped active→stale or stale→active vs prior state):
- Write status=`FORK_FLEET_QUIET` to `memory/logs/${today}.md`.
- Update state file.
- **Do NOT send any notification.**
- Stop.

### 3. Per-fork compare (one call each)

For each active fork, call cross-repo compare using the fork's own `default_branch` and `full_name` (fixes any repo-rename drift):

```bash
gh api "repos/${PARENT_REPO}/compare/${PARENT_OWNER}:${PARENT_DEFAULT_BRANCH}...${FORK_OWNER}:${FORK_DEFAULT_BRANCH}" \
  --jq '{ahead_by, behind_by, status, files: [.files[]? | {filename, status, additions, deletions}], commits: [.commits[]? | {sha: .sha[0:7], msg: .commit.message | split("\n")[0], author: .commit.author.name, date: .commit.author.date}]}'
```

On `404` (branch missing / fork emptied): mark fork `UNREADABLE` and continue.
On `429`: sleep 60s, retry once. On `5xx`: sleep 10s, retry once. On persistent fail: mark `API_FAIL` for that fork.

Cross-repo compare returns unique fork commits (`commits`) and changed files (up to 300) in one shot. No separate `/commits` calls needed.

### 4. Classify divergence signals per fork

From the `files` array, tag each fork with signals:
- **New skills**: files with `status=added` under `skills/*/SKILL.md`
- **Modified skills**: `status=modified` under `skills/*/SKILL.md`
- **Custom schedule**: any change to `aeon.yml`
- **Modified dashboard**: any change under `apps/dashboard/`
- **Custom notify**: change to `notify` or `notify-jsonrender`
- **New content**: additions under `articles/` or `memory/topics/`
- **Config changes**: changes to `CLAUDE.md`, `.github/`, or root `scripts/`
- **Workflow changes**: changes under `.github/workflows/`

### 5. Score each fork (substance-weighted)

```
score =  10 × (new skill files)
       +  4 × (modified skill files)
       +  2 × min(unique_commits, 15)
       +  3 × (new content files, capped at 5)
       +  2 × (workflow/config files, capped at 3)
       +  1 × (custom-schedule flag)
       +  1 × stargazers
```

Sort active forks by score descending. Flag any fork with ≥1 new skill file as a **PROMOTE** candidate; ≥3 unique commits OR ≥1 modified skill as **REVIEW**; otherwise **NOTE**.

### 6. Deep-read top upstream candidates

For every PROMOTE fork (capped at 5), fetch each unique skill's SKILL.md from the fork's default branch:

```bash
gh api "repos/${FORK_FULL_NAME}/contents/${SKILL_PATH}?ref=${FORK_DEFAULT_BRANCH}" --jq '.content' | base64 -d
```

On failure fall back to the file tree listing and note "could not read content". Synthesize each unique skill into a 1-2 sentence description of what it does. Do NOT deep-read REVIEW or NOTE forks (output stays actionable).

### 7. Compute week-over-week delta

Compare current active-fork set to prior state file:
- **NEW_FORK**: full_name absent from prior state
- **NEW_ACTIVE**: was stale/dormant, now active
- **WENT_STALE**: was active, now stale/dormant
- **NEW_SKILLS**: active in both snapshots, `new_skill_count` increased
- **GONE**: archived / deleted since prior run

### 8. Pick the verdict

One line at the top. Priority order:
1. `NEW UPSTREAM CANDIDATE: {fork}` — if ≥1 PROMOTE fork has ≥1 new skill not present in prior state
2. `ACTIVE FLEET: {N} forks building` — if ≥3 PROMOTE+REVIEW combined
3. `FLEET STIRRING: {N} new active` — if ≥2 NEW_FORK or NEW_ACTIVE
4. `HOLDING PATTERN: {N} active, no new work` — active forks present but nothing crossed REVIEW
5. `DORMANT: no active forks` — shouldn't reach notify (step 2 would have gated), included fo