Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/aeonfun-aeon-update/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 349% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 133% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 188% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 197% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 77% | 0% |
> ${var} — mode selector; space-separated tokens, order-independent, all optional: > - mode (sync | report, default sync) — sync opens a PR with the framework changes; report computes the delta and notifies, mutating nothing (dry run). > - repo=owner/name — override the upstream source repo (else auto-resolved from this instance's parent, falling back to aeonfun/aeon). > - reset=<sha|fork-point> — force the stored baseline to <sha> (or the merge-base with upstream) before running. Recovery / backfill lever. > > Empty ⇒ sync from the auto-resolved upstream. Examples: · report · repo=aeonfun/aeon · reset=fork-point.
Today is ${today}. This is the fleet's downstream updater - the counterpart to fork-fleet. fork-fleet looks outward from the parent to find work in the forks worth pulling up; this skill runs inside an instance and pulls the parent's shipped framework changes down - new skills, script/harness fixes, workflow and doc updates - and lands them as a reviewable PR. It is how an instance stays current with aeonfun/aeon without a hand-run rsync-overlay rebase.
main. Every framework change ships as one reviewable PR. The operator merges.aeon.yml, STRATEGY.md, soul/, memory/, output/, .mcp.json and the git-derived catalogs are instance-owned. Upstream changes to them are surfaced for manual review in the PR body, never written into the tree.bashmkdir -p memory/topics [ -f memory/topics/aeon-update-state.json ] || echo '{"baseline_sha":null,"upstream":null,"last_run":null,"last_pr":null,"pending_conflicts":[]}' > memory/topics/aeon-update-state.json
Read memory/MEMORY.md for context and scan the last ~3 days of memory/logs/ - drop anything already reported so a repeat run isn't re-sent. Read the state file:
BASELINE = .baseline_sha (the upstream commit this instance was last synced to).PENDING = .pending_conflicts (files surfaced as conflicts in a prior run, not yet resolved).${var}MODE = report if the token report (or dry) is present, else sync.REPO_OVERRIDE = value of a repo=owner/name token, if any.RESET = value of a reset= token, if any (fork-point or a 7-40 char SHA).bashSELF=$(gh repo view --json nameWithOwner -q .nameWithOwner) UPSTREAM="${REPO_OVERRIDE:-$(gh api "repos/${SELF}" --jq '.parent.full_name // empty')}" [ -z "$UPSTREAM" ] && UPSTREAM="aeonfun/aeon"
If UPSTREAM == SELF, this instance is canon - there is nothing upstream to pull. Write status AEON_UPDATE_IS_UPSTREAM to memory/logs/${today}.md, send no notification, and stop.
bashUP_DEFAULT=$(gh api "repos/${UPSTREAM}" --jq '.default_branch') HEAD_SHA=$(gh api "repos/${UPSTREAM}/commits/${UP_DEFAULT}" --jq '.sha')
reset=fork-point → BASELINE=$(gh api "repos/${UPSTREAM}/compare/${HEAD_SHA}...$(git rev-parse HEAD)" --jq '.merge_base_commit.sha'). reset=<sha> → BASELINE=<sha>. Persist immediately to state, then continue.BASELINE null and no reset): a fresh instance already carries all of canon from fork time, so there is no delta to apply - just anchor the watermark. Set baseline_sha = HEAD_SHA, write state, log AEON_UPDATE_BASELINE_SET, send a one-line notify (baseline initialized at <head7>; future runs sync from here), and stop. (To backfill everything since the fork point instead, re-run with reset=fork-point.)BASELINE == HEAD_SHA: in sync. Re-verify PENDING (S8) in case a prior conflict is now resolved, update state, log AEON_UPDATE_IN_SYNC, notify nothing, stop.bashgh api "repos/${UPSTREAM}/compare/${BASELINE}...${HEAD_SHA}" --jq '{ ahead: .ahead_by, behind: .behind_by, status, commits: [.commits[]? | {sha: .sha[0:7], msg: (.commit.message | split("\n")[0]), date: .commit.author.date}], files: [.files[]? | {filename, status, previous_filename, additions, deletions}] }' > /tmp/aeon-update-compare.json
Error handling:
status: "diverged" with no merge base (baseline not an ancestor of HEAD - history rewrite or unrelated repo): stop with AEON_UPDATE_BASELINE_UNREACHABLE; notify the operator to re-run with reset=fork-point or reset=<sha>..files looks truncated, note files_truncated=true in the report - the operator can run again after merging to pick up the remainder.Classify every entry in .files by path. A file is OPERATOR-owned (surfaced, never auto-written) if its path matches any of:
aeon.yml STRATEGY.md soul/** memory/**
output/** .mcp.json .env* aeon.db
skills.lock eyebrowlock.json catalog/*.json .claude/** (except .claude/skills/aeon/**)
apps/dashboard/outputs/**Everything else is OWNED (a candidate for auto-apply): skills/**, scripts/**, bin/**, harness-adapter/**, .github/**, apps/** (except apps/dashboard/outputs/**), CLAUDE.md, AGENTS.md, docs/**, .github/README.md, LICENSE, CHANGELOG.md, .gitignore, eyebrow.policy.json, and tracked root helpers (aeon, ...).
catalog/*.json and eyebrowlock.json are OPERATOR-owned here only so they are never blindly copied - they are regenerated from the synced sources in S7, which is the correct way to reconcile them.
Set up a workspace and, for each OWNED file f, fetch upstream's HEAD and BASELINE blobs:
bashWORK=$(mktemp -d) fetch() { gh api "repos/${UPSTREAM}/contents/$1?ref=$2" --jq '.content' 2>/dev/null | base64 -d; } # $1=path $2=ref h() { sha256sum 2>/dev/null | cut -d' ' -f1; }
Decide f's disposition from its status and a content 3-way (local-current vs upstream@BASELINE vs upstream@HEAD):
| status | Test | Disposition | |----------|------|-------------| | added | path absent locally | CLEAN-ADD (write HEAD blob) | | added | path present locally (collision, e.g. a fork-only skill) | CONFLICT | | modified | sha256(local) == sha256(HEAD blob) | already synced → SKIP | | modified | sha256(local) == sha256(BASELINE blob) (operator never touched it) | CLEAN-UPDATE (write HEAD blob) | | modified | otherwise (operator customized it) | CONFLICT | | removed | sha256(local) == sha256(BASELINE blob) | CLEAN-DELETE (git rm) | | removed | local differs or absent | CONFLICT (or already gone → SKIP if absent) | | renamed | treat as removed previous_filename + added filename under the rules above | per-part |
Never CLEAN-DELETE a skills/<name>/ directory whose <name> is not present in upstream's tree - fork-only skills are operator work and are structurally untouched (upstream's compare can only reference paths that exist upstream).
If MODE == report, skip to S9. Otherwise:
bashBR="aeon-update/sync-$(echo "$HEAD_SHA" | cut -c1-7)" git checkout -b "$BR"
Write every CLEAN-ADD / CLEAN-UPDATE (mkdir -p "$(dirname f)" then write the HEAD blob to f) and git rm every CLEAN-DELETE. CONFLICT and OPERATOR files are not touched - they go in the PR body only.
If any skills/** path was applied, regenerate the derived catalogs from the synced sources (never copy them from upstream):
bashbin/generate-skills-json && bin/generate-packs-json && bin/generate-skill-icons node scripts/gen-agents-md.js || true
Refresh the integrity lock so ci-skill-integrity stays green for any added/edited skill, then validate config:
bashnode scripts/validate-config.js aeon.yml || echo "validate-config flagged (may be pre-existing drift; note, do not abort on it)"
If nothing CLEAN applied (every upstream change was CONFLICT or OPERATOR): open no PR. Fold all changes into the report, log AEON_UPDATE_MANUAL_ONLY, and go to S10 (notify the operator that the sync needs a manual merge). If a file we wrote breaks YAML/JSON parsing, abort: git checkout . && git checkout ${UP_DEFAULT} && git branch -D "$BR", exit AEON_UPDATE_VALIDATION_FAILED, notify with the failing file.
Recompute PENDING: for every CONFLICT file this run plus every prior PENDING entry, keep it only if sha256(local) != sha256(HEAD blob) (still genuinely divergent). Drop the rest (resolved).
Write memory/topics/aeon-update-state.json and commit it with the sync so merging advances the watermark:
json{ "baseline_sha": "${HEAD_SHA}", "upstream": "${UPSTREAM}", "last_run": "${today}", "last_pr": null, "applied": { "added": N, "updated": N, "deleted": N }, "pending_conflicts": [ { "path": "scripts/foo.sh", "reason": "operator-customized", "upstream_commits": ["abc1234"] } ] }
Advancing baseline_sha to HEAD means clean files never re-notify, while pending_conflicts carries unresolved merges forward independently - so they resurface each run until the operator actually reconciles them, and are also written to the PR body. (In report mode, do not write state - a dry run mutates nothing.)
bashgit add -A git commit -F /tmp/aeon-update-commit.txt # never inline the message with -m (backticks/`$()` in commit text get shell-substituted) git push -u origin "$BR" gh pr create --repo "$SELF" --base "$UP_DEFAULT" \ --title "aeon-update: sync ${N_COMMITS} upstream commits (${BASE7}..${HEAD7})" \ --body-file /tmp/aeon-update-pr-body.md
/tmp/aeon-update-commit.txt:
aeon-update: sync upstream ${BASE7}..${HEAD7}
${N_COMMITS} upstream commits from ${UPSTREAM}. ${N_APPLIED} files applied cleanly, ${N_CONFLICT} need manual review. Baseline advanced to ${HEAD7}.PR body (/tmp/aeon-update-pr-body.md) - only include sections that have content:
markdown## Upstream sync: `${UPSTREAM}` `${BASE7}..${HEAD7}` **${N_COMMITS} commits** ({earliest date} → {latest date}) · **${N_APPLIED} applied** · **${N_CONFLICT} manual** · baseline → `${HEAD7}`. ### Applied cleanly - **New skills:** `foo`, `bar` _(regenerated catalogs + agents.md + skill-icons)_ - **Modified skills:** `baz` - **Scripts / harness:** `scripts/notify.sh`, ... - **Workflows:** `.github/workflows/...` - **Docs / other:** `docs/...`, `CLAUDE.md`, ... ### Needs manual review (conflicts - your local copy diverges from upstream) For each: what upstream changed and why it wasn't auto-applied. - `scripts/foo.sh` — you customized this locally; upstream changed it in {commits}. Upstream diff: ```diff {short upstream base..head diff for the file} ``` ### Operator config changed upstream (not auto-applied - reconcile by hand) - `aeon.yml` — upstream added skills / changed defaults: {summary}. Merge the new entries you want (keep your enable/schedule/model choices). - `soul/…`, `STRATEGY.md` — {summary, if changed} ### Upstream commits | SHA | Summary | |-----|---------| | abc1234 | ... |
Capture the PR URL; write it back into last_pr in the branch's state file (amend the state commit) so the merged watermark records its own PR.
Append to memory/logs/${today}.md under ### aeon-update: status, UPSTREAM, ${BASE7}..${HEAD7}, applied/conflict counts, PR URL (or report/manual-only), and pending_conflicts count.
Notify only on signal - match soul/ voice if present. Send when there is a PR, a report with changes, or a manual-only situation; stay silent for IN_SYNC / BASELINE_SET-with-nothing. Keep it ≤4000 chars:
*aeon-update — ${today}*
{verdict: "synced N commits → PR" | "N changes need manual merge" | "report: N commits behind"}
Upstream `${UPSTREAM}` is ${AHEAD} commits ahead. Applied ${N_APPLIED} cleanly, ${N_CONFLICT} need review.
{Top applied highlight: e.g. "new skill: `token-radar`; harness fix in run-harness"}
{If conflicts: "Manual: `aeon.yml` (new skills), `scripts/foo.sh` (local edit)"}
PR: {url} (or "dry run — nothing changed")Pass --mute-key "aeon-update:${HEAD7}" so a muted sync doesn't re-ping for the same upstream HEAD.
| Code | When | Notify | |------|------|--------| | AEON_UPDATE_OK | PR opened with ≥1 clean file (conflicts, if any, listed in it) | Yes - PR link | | AEON_UPDATE_MANUAL_ONLY | Upstream changed only operator-owned / conflicting files - no clean apply, no PR | Yes - manual call-out | | AEON_UPDATE_REPORT | report mode - delta computed, nothing mutated | Yes - dry-run summary | | AEON_UPDATE_IN_SYNC | Baseline already == upstream HEAD | No (log only) | | AEON_UPDATE_BASELINE_SET | First run - watermark anchored, nothing applied | One-line notify | | AEON_UPDATE_IS_UPSTREAM | This instance is the upstream repo itself | No (log only) | | AEON_UPDATE_BASELINE_UNREACHABLE | Baseline is not an ancestor of HEAD (history rewrite) | Yes - asks for reset= | | AEON_UPDATE_VALIDATION_FAILED | An applied file broke YAML/JSON parsing → branch reverted | Yes - failing file |
main or auto-write an OPERATOR-owned path (aeon.yml, soul/, memory/, STRATEGY.md, .mcp.json, output/).catalog/*.json / eyebrowlock.json from upstream - regenerate them.baseline_sha without carrying unresolved conflicts forward in pending_conflicts.files_truncated=true and let a follow-up run pick up the rest.Every network call is gh api, which authenticates via GITHUB_TOKEN automatically - no curl, no ./secretcurl, no $SECRET on the command line for the Bash permission layer to refuse, and no secret beyond the default GITHUB_TOKEN. There are no irreversible side-effects: the skill's only mutation is a PR against this instance's own repo, which the operator reviews and merges. Retry policy: on 403 with X-RateLimit-Remaining: 0, sleep 60s and retry once; on a persistent contents-API failure for one file, mark it UNREADABLE in the report and continue with a partial sync rather than aborting the whole run.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→pass | 14,196 | 7,301 | -49% | 1 | 1 | 0% | 1,286 | 5,771 | +349% | 0 | 0 | — |
case-01 | fail→fail | 17,466 | 12,421 | -29% | 1 | 1 | 0% | 299 | 4,772 | +1496% | 0 | 0 | — |
case-02 | fail→fail | 27,310 | 34,969 | +28% | 1 | 1 | 0% | 2,093 | 4,770 | +128% | 0 | 0 | — |
case-03 | fail→fail | 18,169 | 14,209 | -22% | 1 | 1 | 0% | 2,217 | 4,780 | +116% | 0 | 0 | — |
case-04 | fail→pass | 18,374 | 29,935 | +63% | 1 | 1 | 0% | 3,457 | 8,049 | +133% | 0 | 0 | — |
case-05 | fail→fail | 15,484 | 15,495 | +0% | 1 | 1 | 0% | 2,586 | 4,958 | +92% | 0 | 0 | — |
case-06 | fail→pass | 13,161 | 15,850 | +20% | 1 | 1 | 0% | 2,049 | 5,910 | +188% | 0 | 0 | — |
case-07 | fail→fail | 16,670 | 13,966 | -16% | 1 | 1 | 0% | 1,531 | 5,160 | +237% | 0 | 0 | — |
case-08 | fail→fail | 16,107 | 18,432 | +14% | 1 | 1 | 0% | 1,984 | 4,999 | +152% | 0 | 0 | — |
case-09 | fail→fail | 13,089 | 11,465 | -12% | 1 | 1 | 0% | 1,392 | 5,162 | +271% | 0 | 0 | — |
case-10 | fail→fail | 13,363 | 24,496 | +83% | 1 | 1 | 0% | 184 | 4,808 | +2513% | 0 | 0 | — |
case-11 | pass→fail | 15,969 | 14,525 | -9% | 1 | 1 | 0% | 2,355 | 5,096 | +116% | 0 | 0 | — |
case-13 | fail→pass | 14,975 | 18,874 | +26% | 1 | 1 | 0% | 2,729 | 8,102 | +197% | 0 | 0 | — |
case-14 | fail→pass | 22,936 | 11,709 | -49% | 1 | 1 | 0% | 3,025 | 5,345 | +77% | 0 | 0 | — |
case-15 | fail→pass | 9,517 | 10,629 | +12% | 1 | 1 | 0% | 750 | 5,424 | +623% | 0 | 0 | — |
case-16 | fail→fail | 7,565 | 16,851 | +123% | 1 | 1 | 0% | 1,509 | 5,173 | +243% | 0 | 0 | — |
case-17 | fail→fail | 18,167 | 15,783 | -13% | 1 | 1 | 0% | 2,971 | 4,809 | +62% | 0 | 0 | — |
case-18 | fail→pass | 13,155 | 18,344 | +39% | 1 | 1 | 0% | 1,080 | 6,247 | +478% | 0 | 0 | — |
case-19 | fail→pass | 16,283 | 12,188 | -25% | 1 | 1 | 0% | 1,861 | 5,492 | +195% | 0 | 0 | — |
case-20 | fail→pass | 8,450 | 14,789 | +75% | 1 | 1 | 0% | 546 | 6,655 | +1119% | 0 | 0 | — |
case-21 | pass→fail | 8,887 | 9,051 | +2% | 1 | 1 | 0% | 1,130 | 4,997 | +342% | 0 | 0 | — |
case-22 | pass→pass | 19,856 | 17,212 | -13% | 1 | 1 | 0% | 2,658 | 6,121 | +130% | 0 | 0 | — |
case-23 | fail→pass | 15,854 | 17,472 | +10% | 1 | 1 | 0% | 2,670 | 6,954 | +160% | 0 | 0 | — |
case-24 | fail→fail | 3,963 | 7,428 | +87% | 1 | 1 | 0% | 570 | 4,988 | +775% | 0 | 0 | — |
case-25 | fail→pass | 10,617 | 3,555 | -67% | 1 | 1 | 0% | 1,546 | 5,091 | +229% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted, and 12 counted toward the lift figure. The other 13 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 12 comparable cases. 7 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.