fleet-state
Fleet-state synthesizes three independent weekly fork-intelligence reports, fork-cohort activity buckets, release announcements, and contributor spotlight picks, into a single composite "state of the fleet" digest with week-over-week comparisons. Use this skill on Monday mornings to deliver operators one integrated view of fleet health, releases shipped, and personnel highlights rather than requiring them to manually correlate three separate notifications and prior snapshots.
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/fleet-state && cp -r /tmp/fleet-state/skills/fleet-state ~/.claude/skills/fleet-stateSKILL.md
> **${var}** — Optional. Pass `dry-run` to skip notify (state still updates and the article still writes). Pass `owner/repo` to override the parent repo. Otherwise empty.
Today is ${today}. Three weekly skills already produce fork intelligence in isolation:
- `fork-cohort` (Sunday 19:00 UTC) answers **"is the fork alive?"** — POWER / ACTIVE / STALE / COLD buckets by workflow runs in the last 7d.
- `fork-release` (Sunday 19:30 UTC) answers **"did any fork ship a versioned artifact?"** — silent when no tagged releases.
- `contributor-spotlight` (Sunday 20:00 UTC) answers **"who's the named operator we celebrate this week?"** — one POWER-fork callout.
Each fires its own Telegram blip. The operator reads three separate notifications and has to do the synthesis in their head. **Fleet-State Digest** closes that gap: one Monday read that answers the composite question — how many POWER forks, who leveled up, who shipped a release, who's the spotlight pick — with week-over-week deltas computed against the prior fleet snapshot.
## Why this exists
The fork fleet has grown to 48 (and growing). With three independent weekly skills, the operator's mental model of "how is the fleet" requires opening three notifications, three articles, three state files — and remembering last week's numbers to compute deltas. The synthesis layer is the next natural step now that all three constituent skills are shipped. This skill produces nothing the constituent skills don't already produce in pieces — its value is the *single weekly view* that lets the operator land on Monday morning with the fleet picture already assembled.
## Config
No new secrets. No new env vars. Reads:
- `memory/topics/fork-cohort-state.json` — authoritative current bucket assignments + totals.
- `memory/topics/fork-release-state.json` — `announced` array of `{fork_full_name, tag, published_at, announced_at}`.
- `memory/topics/contributor-spotlight-history.json` — `history` array; most recent entry is "this week's pick".
- `articles/fork-cohort-*.md`, `articles/fork-release-*.md`, `articles/contributor-spotlight-*.md` — read most recent of each for narrative material.
- `memory/topics/fleet-state.json` — this skill's own prior snapshot, for week-over-week deltas.
Writes:
- `articles/fleet-state-${today}.md` — the synthesis digest.
- `memory/topics/fleet-state.json` — current snapshot for next week's delta.
- `memory/logs/${today}.md` — log block.
## Steps
### 0. Bootstrap
```bash
mkdir -p memory/topics articles
[ -f memory/topics/fleet-state.json ] || cat > memory/topics/fleet-state.json <<'EOF'
{"parent":null,"snapshot":null,"last_run":null,"history":[]}
EOF
```
`history` is an LRU array (capped at 12 entries ≈ 3 months) of `{run_date, totals, release_count, spotlight_fork}` — the longitudinal record this skill itself maintains so the digest can show 3-month trend lines, not just a single week-over-week delta.
### 1. Parse var
- If `${var}` matches `^dry-run` → `MODE=dry-run`. Strip the prefix; remainder (if non-empty) is treated as a parent override.
- Otherwise `MODE=execute`.
- If the remainder is a non-empty token matching `^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$` → `PARENT_OVERRIDE=${remainder}`.
- Else if the remainder is non-empty but malformed → log `FLEET_STATE_BAD_VAR: ${var}` and exit (no notify).
- Else leave `PARENT_OVERRIDE=""`.
### 2. Resolve parent repo
```bash
if [ -n "$PARENT_OVERRIDE" ]; then
PARENT_REPO="$PARENT_OVERRIDE"
else
PARENT_REPO=$(gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner) --jq '.parent.full_name // .full_name')
fi
PARENT_OWNER="${PARENT_REPO%%/*}"
```
If the state file's `parent` is set and differs from the resolved `PARENT_REPO` → log `FLEET_STATE_PARENT_CHANGED` and clear `snapshot` + `history` (cross-parent deltas are meaningless). Update the stored `parent`.
### 3. Read constituent state files
```bash
COHORT_STATE=memory/topics/fork-cohort-state.json
RELEASE_STATE=memory/topics/fork-release-state.json
SPOTLIGHT_HISTORY=memory/topics/contributor-spotlight-history.json
```
For each: if missing, mark that source as `unavailable` and continue. The digest degrades gracefully — a missing source produces a partial section, not a hard failure.
- **fork-cohort missing** → `cohort=unavailable`. The digest header cannot show POWER/ACTIVE/STALE/COLD counts. Status becomes `FLEET_STATE_PARTIAL` if at least one source still loaded; `FLEET_STATE_NO_SOURCES` if all three are missing.
- **fork-release missing** → `releases=unavailable`. The "Shipped this week" section is omitted (not "0 releases" — we don't know).
- **contributor-spotlight missing** → `spotlight=unavailable`. The "Spotlight" section is omitted.
If `cohort=unavailable` AND `releases=unavailable` AND `spotlight=unavailable` → log `FLEET_STATE_NO_SOURCES`, exit (no notify, no article — there's nothing to digest).
### 4. Pull current fleet snapshot
From `fork-cohort-state.json`:
```bash
N_TOTAL=$(jq '.totals.total' "$COHORT_STATE")
N_POWER=$(jq '.totals.power' "$COHORT_STATE")
N_ACTIVE=$(jq '.totals.active' "$COHORT_STATE")
N_STALE=$(jq '.totals.stale' "$COHORT_STATE")
N_COLD=$(jq '.totals.cold' "$COHORT_STATE")
N_UNREADABLE=$(jq '.totals.unreadable' "$COHORT_STATE")
N_RUNNING=$((N_POWER + N_ACTIVE))
COHORT_LAST_RUN=$(jq -r '.last_run' "$COHORT_STATE")
```
From `fork-release-state.json` — count `announced` entries with `published_at` within the last 7 days (the field is ISO-8601 in UTC):
```bash
SEVEN_DAYS_AGO=$(date -u -d '7 days ago' +%FT%TZ)
RELEASES_THIS_WEEK=$(jq --arg cutoff "$SEVEN_DAYS_AGO" \
'[.announced[] | select(.published_at >= $cutoff)]' "$RELEASE_STATE")
RELEASE_COUNT=$(echo "$RELEASES_THIS_WEEK" | jq 'length')
```
From `contributor-spotlight-history.json` — pick the newest entry. When
`.history` is empty (fresh install, no spotlight has ever run) the first
jq emits nothing, which makes `SPOTLIGHT_PICK` an empty string. Piping
that into a second `jq` produces a parse error and aborts the digestMention/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.