Fork Digest
Fork Digest is a weekly divergence analyzer that compares how a fleet of configured forks customize skills, variables, models, and schedules relative to an upstream repository's defaults. It identifies systematic disagreements across the fork fleet to surface peer-learning signals, helping operators recognize when upstream defaults misalign with how the majority of forks have reconfigured them. Use this when you need to discover which default settings are being overridden most consistently across your fork ecosystem.
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/fork-digest && cp -r /tmp/fork-digest/skills/fork-digest ~/.claude/skills/fork-digestSKILL.md
> **${var}** — Target repo to scan forks of (e.g. "owner/aeon"). If empty, reads `memory/watched-repos.md` and uses the first entry.
Today is ${today}. Generate the weekly **divergence digest** — where the configured fork fleet systematically disagrees with upstream defaults on `enabled`, `var`, `model`, or `schedule`, and a per-fork customization fingerprint for the heaviest customizers.
## Why this exists
`skill-leaderboard` ranks **what's popular** (top 15 by enabled count). `fork-fleet` surfaces **per-fork unique work** (commits, new skills). Neither answers: **where do operators consistently disagree with upstream defaults?** That's the peer-learning signal — if 6 out of 8 configured forks enable a skill upstream defaults off, upstream is shipping the wrong default. If 5 out of 8 disable a skill upstream defaults on, that skill is noise. This skill surfaces those signals weekly so the operator can flip defaults that the fleet has already voted on.
## Steps
### 1. Determine the target repo
If `${var}` is set, use that as `TARGET_REPO`. Otherwise read `memory/watched-repos.md` and use the first non-comment, non-empty line. If neither yields a value, log `FORK_SKILL_DIGEST_NO_TARGET` to `memory/logs/${today}.md` and stop (no notification).
### 2. Snapshot upstream defaults
Read this running instance's local `aeon.yml` once. Build:
- `UPSTREAM_DEFAULTS`: dict `{skill_name -> {enabled: bool, model: str|null, var: str, schedule: str|null}}` for every skill entry under `skills:`.
- `UPSTREAM_SKILLS`: set of skill directory names from `skills/` (use `ls skills/`).
- `UPSTREAM_TAGS`: dict `{skill_name -> [tags]}` parsed from each `skills/<name>/SKILL.md` frontmatter (best-effort; missing frontmatter → `[]`).
These are the comparison baselines — never mutated.
### 3. Fetch active forks
```bash
CUTOFF=$(date -u -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
gh api "repos/${TARGET_REPO}/forks?per_page=100" --paginate \
--jq "[.[] | select(.pushed_at > \"$CUTOFF\") | select(.archived == false) | select(.disabled == false) | {owner: .owner.login, full_name: .full_name, pushed_at, stargazers_count, default_branch}]"
```
If zero active forks: log `FORK_SKILL_DIGEST_NO_FORKS` and stop (no notification).
### 4. Per-fork enumeration (one tree call + one yml fetch each)
For each active fork, run **one** recursive git-tree call to enumerate files (cheaper than per-path contents):
```bash
gh api "repos/${FORK_FULL}/git/trees/HEAD?recursive=1" --jq '[.tree[] | select(.type == "blob") | .path]'
```
Then fetch the fork's `aeon.yml` only if the tree contains it:
```bash
gh api "repos/${FORK_FULL}/contents/aeon.yml?ref=${FORK_DEFAULT_BRANCH}" --jq '.content' | base64 -d
```
Error handling:
- 404 / 409 (empty repo): mark `status: "no_tree"`, skip aeon.yml extraction, continue.
- 403 with `X-RateLimit-Remaining: 0`: sleep 60s, retry once. If still failing, mark `status: "rate_limited"` and continue.
- Tree contains aeon.yml but contents call 404s: mark `status: "yml_unreadable"`, continue.
- aeon.yml present but YAML parse fails: mark `status: "yml_invalid"`, continue.
For each readable `aeon.yml`, extract per-skill `{enabled, model, var, schedule}`. Treat missing keys as inheriting the upstream default (do NOT count those as overrides).
Detect **fork-only skills**: directory names matching `skills/<name>/SKILL.md` in the fork's tree where `<name>` is NOT in `UPSTREAM_SKILLS`. Record `{fork_full_name, skill_name, path}` for each.
### 5. Tier each fork
For each fork compute a divergence signal vector vs `UPSTREAM_DEFAULTS`:
- `enabled_diff`: count of skills where the fork's `enabled` differs from upstream
- `var_overrides`: count of skills with non-empty `var:` where upstream's was empty (or different non-empty value)
- `model_overrides`: count of skills with `model:` differing from upstream
- `schedule_overrides`: count of skills with `schedule:` differing from upstream
- `fork_only_skill_count`: count from step 4
Tier the fork:
- **CONFIGURED**: any signal ≥1 (the fork actively diverged)
- **TEMPLATE**: aeon.yml readable but every signal is 0 — exclude from divergence math
- **UNREADABLE**: no_tree / no aeon.yml / yml_unreadable / yml_invalid / rate_limited — tracked in source-status footer
### 6. Aggregate divergence (the core analysis)
Let `N_CONFIGURED` = count of forks tiered CONFIGURED. If `N_CONFIGURED < 2`: log `FORK_SKILL_DIGEST_TEMPLATE_FLEET` with active/template/unreadable counts, write a stub article noting the conversion rate, and **skip notification**. Stop.
For each skill name in `UPSTREAM_SKILLS`, compute four divergence dimensions:
**Enable divergence:**
- `forks_enabled_count`: number of CONFIGURED forks with `enabled: true` for this skill
- `forks_disabled_count`: number of CONFIGURED forks with `enabled: false` for this skill (explicitly set, not inherited)
- `upstream_enabled`: bool from UPSTREAM_DEFAULTS
- `divergence_pct`:
- If upstream `enabled: false`: `forks_enabled_count / N_CONFIGURED` (how many forks disagree by enabling)
- If upstream `enabled: true`: `forks_disabled_count / N_CONFIGURED` (how many forks disagree by disabling)
- `direction`: `"ENABLE_UPWARD"` (upstream off, forks turn on) or `"DISABLE_DOWNWARD"` (upstream on, forks turn off)
**Var divergence:**
- `var_override_count`: number of CONFIGURED forks where `var:` differs from upstream
- `top_var_value`: most common non-empty fork value (with count) — only if ≥2 forks share it
**Model divergence:**
- `model_override_count`: number of forks with non-null model differing from upstream
- `top_model_value`: most common fork model (with count) — only if ≥2 forks share it (signals fleet consensus on a cheaper/different model)
**Schedule divergence:**
- `schedule_override_count`: number of forks with schedule differing from upstream
- `top_schedule_value`: most common fork schedule (with count) — only if ≥2 forks share it
### 7. Categorize divergentMention/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.