fork-fleet
Fork divergence monitor - tracks where the fleet's active forks diverge in CODE (unique commits, new/modified skills) and CONFIG (enable/var/model/schedule vs upstream), gated on real change.
git clone --depth 1 https://github.com/aeonfun/aeon /tmp/fork-fleet && cp -r /tmp/fork-fleet/skills/fork-fleet ~/.claude/skills/fork-fleetSKILL.md
> **${var}** — Divergence scope selector; space-separated tokens, order-independent, all optional:
> - **scope** (`code` | `config` | `both`, default `both`) — which divergence dimension to run.
> - **`repo=owner/name`** — override the parent repo whose forks are scanned (else auto-resolved).
> - **`fork=owner/name`** — drill into a single fork (forces `code` scope; config math needs a fleet).
>
> Empty ⇒ **both** dimensions over the auto-resolved parent. Examples: `` (both, all forks) · `code` · `config` · `config repo=octo/aeon` · `fork=alice/aeon`.
Today is ${today}. This is the fleet's **divergence monitor**. It answers two questions the popularity/liveness skills don't:
1. **Code divergence** — which active forks are building real work (unique commits, new/modified skills) that's worth pulling back upstream?
2. **Config divergence** — where does the configured fleet systematically disagree with upstream's `enabled` / `var` / `model` / `schedule` defaults, so the operator can flip a default the fleet has already voted on?
`skill-gap` ranks **what's popular** (top 15 by enabled count). This skill's **code** branch surfaces **per-fork unique work**; its **config** branch surfaces **where operators disagree with defaults**. If 6 of 8 configured forks enable a skill upstream defaults off, upstream is shipping the wrong default; if 5 of 8 disable a skill upstream defaults on, that skill is noise. Both are peer-learning signals.
## Operating principles
- **Verdict first, catalog second.** The operator reads one line and knows if action is needed.
- **Silent when nothing changed.** Weekly cadence + a dormant/undivergent fleet = a read-once habit to kill. A clean run notifies nothing.
- **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; the recursive git-tree returns the fork's whole file list in one call.
- **Substance ≠ noise.** A new `skills/*/SKILL.md` is worth 100 cron-time edits in `aeon.yml`. Score accordingly. On the config side, an untouched template fork is not a "vote" — exclude it from divergence math.
---
## Shared setup (all scopes)
### S0. 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
[ -f memory/topics/fork-digest-state.json ] || echo '{"last_run":null}' > memory/topics/fork-digest-state.json
```
Read `memory/MEMORY.md` for high-level context and scan the last ~3 days of `memory/logs/` — drop anything already reported so a weekly signal isn't re-sent.
- Read `memory/instances.json` → the 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 **code** what-changed delta.
- Read `memory/topics/fork-digest-state.json` → prior config-divergence snapshot (schema in step B8). Used for the **config** week-over-week delta.
### S1. Parse the scope selector
Parse `${var}` into tokens:
- `SCOPE` = `code`, `config`, or `both` (default `both` if no scope keyword present).
- `REPO_OVERRIDE` = value of a `repo=owner/name` token, if any.
- `SINGLE_FORK` = value of a `fork=owner/name` token, if any. **If `SINGLE_FORK` is set, force `SCOPE=code`** (single-fork config divergence is meaningless — the config math needs a fleet of ≥2 configured forks).
### S2. Resolve the parent/target repo
Resolve `PARENT_REPO` in priority order:
1. `REPO_OVERRIDE` if the `repo=` token was given.
2. Else auto-resolve from this running instance:
```bash
PARENT_REPO=$(gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner) --jq '.parent.full_name // .full_name')
```
3. Else fall back to the first non-comment, non-empty line of `memory/watched-repos.md`.
If none resolves, write status `FORK_DIVERGENCE_NO_TARGET` to `memory/logs/${today}.md` and stop (no notification).
```bash
PARENT_NAME="${PARENT_REPO##*/}"
PARENT_OWNER="${PARENT_REPO%%/*}"
PARENT_DEFAULT_BRANCH=$(gh api "repos/${PARENT_REPO}" --jq '.default_branch')
```
### S3. List + classify forks (single call, shared by both branches)
One paginated listing — includes `default_branch`, `archived`, `disabled`, `pushed_at`, stars, description:
```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`). Classify by activity window:
- **Active** = `pushed_at` within last 30 days.
- **Stale** = 30–365 days.
- **Dormant** = >365 days or never pushed after creation.
The **Active** set (pushed in the last 30 days) is the shared working set for both branches — this matches the config branch's original 30-day cutoff exactly.
- **If `SINGLE_FORK` is set:** filter to that one fork, treat it as active, and skip the classification math.
- **If zero active forks** (and `SINGLE_FORK` unset): both branches short-circuit. If there is also no code-side state change (no new forks, none flipped active↔stale vs prior `fork-fleet-state.json`), write status `FORK_DIVERGENCE_QUIET` to the log, update the state files' `last_run`, send **no notification**, and stop.
Cap active-fork deep processing at **50 per run** — if more, rank by `pushed_at_epoch` desc and trim (log `truncated_at=50`).
Now dispatch: run **Branch A** if `SCOPE ∈ {code, both}`, **Branch B** if `SCOPE ∈ {config, both}`.
---
## Branch A — Code divergence (runs when `SCOPE ∈ {code, both}`)
### A1. Per-fork compare (one call each)
For each active fork, call cross-repo comSet up and run an Aeon agent instance — get started from scratch, pick which skills to turn on or install more from packs, reschedule or change what runs, edit what an existing skill does, fix a skill that isn't firing, set the STRATEGY.md north star and soul/ voice, turn a coding-agent chat into a scheduled Aeon skill, and mine past coding-agent conversations for recurring work worth automating as a skill. Use when the user mentions Aeon, aeon.yml, an Aeon skill / instance / routine / pack, asks to schedule, enable, edit, or debug an agent that runs on a cron, or asks what of their repeated/manual work Aeon could take over.
Mention/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
Static config-correctness linter for this instance - catches the silent-failure class (unquoted schedules, duplicate keys, unconfigured skills, mode typos, broken requires/MCP refs) that no run-based health skill can see. Notifies only on problems.
Pull framework updates from the upstream Aeon repo into this instance - 3-way merges canon's new commits into a PR, never clobbering operator config.
Write a publication-ready article in one of three angles - a trending long-form piece, a watched-repo thesis, or a project-through-a-lens essay. Optional Replicate hero image with --visual.
Automatically merge open PRs that have passing CI, no blocking reviews, and no conflicts
Two-mode aeon.yml workflow builder - analyze inspects URLs and emits a tiered, signal-verified skill-enablement plan plus an aeon.yml diff; enable flips slugs to enabled:true and opens a PR.