From 1f8a1f0383b5b9335fb6fef6bf20111c4cfcf7c3 Mon Sep 17 00:00:00 2001 From: Aaron Elijah Mars Date: Sat, 17 Oct 2026 12:58:54 -0400 Subject: [PATCH] docs: sync PRs #1198-#1241 to aeon docs --- .../skills/aeon/references/skill-anatomy.md | 4 +- CHANGELOG.md | 78 ++++++++++++++++++- docs/ADK.md | 2 +- docs/CONFIGURATION.md | 12 +++ docs/harnesses.md | 10 +++ .../skills/aeon/references/skill-anatomy.md | 4 +- 6 files changed, 106 insertions(+), 4 deletions(-) diff --git a/.claude/skills/aeon/references/skill-anatomy.md b/.claude/skills/aeon/references/skill-anatomy.md index afe6e0b64aa..9d509048640 100644 --- a/.claude/skills/aeon/references/skill-anatomy.md +++ b/.claude/skills/aeon/references/skill-anatomy.md @@ -107,6 +107,8 @@ Claude Code's Bash permission analyzer **blocks any command containing a secret Braces, not `$`. A skill that writes `-H "Authorization: Bearer $XAI_API_KEY"` will be blocked at run time, not at author time. +In a scheduled run `./secretcurl` only fills placeholders for secrets the skill lists in `requires:` (plus `GH_TOKEN` / `GITHUB_TOKEN`). A placeholder for any other set key is refused with a message that names it, never its value, so declare every key you put in braces. curl runs with a stripped environment, and `--variable`, `--expand-*`, `-K` / `--config` and option values that read a file under `/proc` are refused. (#1215, #1216) + There is **no network sandbox** - plain `curl` works for unauthenticated GETs. ## Memory @@ -130,7 +132,7 @@ This is also the **dedup substrate**. The standard rule, and the one to add to a ### `memory/MEMORY.md` - the durable index (138 references across 59 skills) -Long-lived facts, not run history. Skills read it for context; the `memory-flush` skill promotes important log lines into it and prunes stale ones. Don't append per-run noise here - that's what `logs/` is for. +Long-lived facts, not run history. Skills read it for context; the `memory-flush` skill promotes important log lines into it and prunes stale ones, holds it under 8 KB with no line over 300 chars (it loads into every run), and ends each fact it adds with `[source: logs/YYYY-MM-DD#]`. Don't append per-run noise here - that's what `logs/` is for. ### Domain state files diff --git a/CHANGELOG.md b/CHANGELOG.md index ae4fda63765..ed4b37e9106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,36 @@ from or pin to; the template keeps serving the latest `main` to new forks. ### Added +- **Langfuse: one root span per run, priced cost, scores and slicing.** Each claude call now + sends a root span (also on failed runs) with one priced `usage ` row per model, and + Claude Code's own spans nest under it again: a 1s SessionStart hold fixes the trace tree that + split into one trace per span on subscription tokens (`AEON_OTEL_STARTUP_DELAY=0` turns it off). + Cost rows carry the skill as trace name and user, plus environment (`production` on the default + branch, `branch` elsewhere), release, SKILL.md version and a `cron` / `chain` / `manual` + trigger (new optional `trigger` dispatch input). New scores: a NUMERIC quality score and a + BOOLEAN `run_ok` per run. Failed runs get an `error_class` (timeout, rate_limit, auth, + budget_cap, cancelled and the rest of the shared table) and a status message. 1-hour cache + writes are priced at the 1-hour rate (cost read about 35% low before). The feed render and the + scorer run traced and lean (`run-harness --no-tools`, empty scratch dir), and usage rows are + zero-length so latency charts show real requests only. See `docs/langfuse.md`. (#1221, #1222, + #1223, #1230, #1232, #1233) +- **`memory-flush` cites a source on every fact and skips idle runs.** Facts it adds or changes + end with `[source: logs/YYYY-MM-DD#]`, and `memory_prep.py source ` prints that log + section (archive too), so contradictions are settled from the log. A new `Idle gate + (memory-flush)` step skips the model call when no daily log changed since a flush under 7 days + old. It also holds `memory/MEMORY.md` to 8 KB with no line over 300 chars. (#1217, #1232) +- **OpenRouter app attribution on every harness.** Every OpenRouter request (claude via + `gateway: openrouter`, codex, kimi, vibe, pi, hermes) carries `HTTP-Referer: + https://www.aeon.fun`, `X-OpenRouter-Title: Aeon` and `X-OpenRouter-Categories`. Override with + `OPENROUTER_SITE_URL`, `OPENROUTER_APP_TITLE` and the new `OPENROUTER_APP_CATEGORIES`. + (#1235, #1239) +- **Feedback section in the aeon setup skill.** When a `./aeon` command, a Connect MCP tool or a + skill step fails, the agent may send one short report through Connect's `send_feedback` tool or + the keyless `https://www.aeon.fun/api/feedback`, never with secrets or private repo contents. + (#1226) +- **Sentinel Pack listed** in the community registry: `robinhood-chain-monitor` watches addresses + on Robinhood Chain (4663), keyless, alerts only on change. (#1227) +- **Ecosystem: bon travail and skopos** added to `docs/ECOSYSTEM.md`. (#1220) - **`anatomy`: interactive isometric SVG figures from a brief.** New `dev` skill (vendored from upstream at 689dcf9, MIT, provenance in `skills/anatomy/UPSTREAM.md`) that builds a crafted, interactive isometric figure explaining a technical idea as a physical object, with live readout, @@ -202,6 +232,19 @@ from or pin to; the template keeps serving the latest `main` to new forks. ### Changed +- **Claude Code pinned to 2.1.301.** Usage-limit waits are capped at 10 minutes + (`CLAUDE_CODE_RETRY_WATCHDOG`), and WebFetch is turned off when egress runs in `enforce` mode + with the proxy up, since it never passes through iron-proxy. (#1234) +- **Test branches stay quiet.** Notifications and health-regression Issues now come only from + runs on the default branch; repo variable `NOTIFY_ON_BRANCH=1` opts a test branch back in. + (#1230, #1232) +- **Runner label from `AEON_RUNNER`.** Workflow jobs read their runner from the `AEON_RUNNER` + repo variable (unset = `ubuntu-24.04`, e.g. `blacksmith-2vcpu-ubuntu-2404`); the CI gate and + small catalog checks stay on GitHub runners. (#1228, #1236) +- **CONTRIBUTING lists every CI gate** with the local command that matches it, plus the test + lanes. (#1211, #1213, #1238) +- **`SECURITY.md` has a contact email** (`aaron@aeon.fun`) for reporters who can't use GitHub's + private form. (#1219) - **Setup skill secrets guidance tightened.** A new "Handling secrets" rule in `SKILL.md` and `references/secrets.md`: never ask for a key in chat, never echo, log or commit one, never read credential files to fill one in; values go in through `./aeon secrets set NAME --stdin` or the @@ -338,9 +381,24 @@ from or pin to; the template keeps serving the latest `main` to new forks. ### Fixed +- **Scheduler:** `SAT-SUN` / `FRI-SUN` ranges run (SUN closes a range as 7) (#1200, #1212); an + invalid schedule now raises a `::warning::` naming the skill instead of a silent skip (#1206); + a cron-state push that fails every retry fails the tick, so owed skills are not dispatched + twice (#1207, #1213). +- **CLI:** `aeon skills schedule` refuses a schedule CI would reject and `skills set --harness` + checks the name (#1212); `aeon mcp add` and `saveFile` (and the dashboard MCP, strategy and soul + routes) treat only a missing file as missing, so an auth or network error no longer overwrites + `.mcp.json` with one server (#1210, #1213). +- **Frontmatter readers handle CRLF, comments and mixed case,** so a `mode: read-only` skill no + longer runs in the write tier and `requires:` / `depends_on:` / `attest:` lists stay intact. + (#1203, #1213) +- **Dropped notifications are visible:** a payload no channel accepted raises a `::warning::` + with the count; no warning when no channel is configured. (#1208, #1213) +- **MCP server:** a multi-line `var` is folded onto one prompt line (#1204), and a failed skill run + returns an MCP error result instead of looking like success (#1209). - **Post-run Git pushes retain trusted checkout authentication.** The config guard rebuilds host-scoped HTTP auth from workflow secrets after removing untrusted includes. Push failures - now show redacted diagnostics and retry only stale refs, with authenticated HTTP push coverage. + now show redacted diagnostics and retry only stale refs, with authenticated HTTP push coverage. (#1241) - **Stale Claude Code npm cache no longer blocks pin bumps.** `restore-keys` restored an old cache whose packument did not list the new version, so every run failed at "Install Claude Code"; an exact-key miss now downloads fresh. (#1169) @@ -1234,6 +1292,20 @@ from or pin to; the template keeps serving the latest `main` to new forks. ### Security +- **Run guards after a skill run.** On main, changes a run made under `scripts/`, `.github/` or + `harness-adapter/` are restored to a freshly fetched `main` with an `::error::`; feature-branch + PR flows are unaffected. Push helpers run from the starting commit with hooks off, and a new + `Lock git config` step drops `.git/config` keys that run programs, then restores checkout auth + from fresh secrets. (#1214, #1216, #1241) +- **`./secretcurl` fills only secrets the skill declared** in `requires:` (plus `GH_TOKEN` / + `GITHUB_TOKEN`); curl runs with a stripped environment, and `--variable`, `--expand-*`, `-K` / + `--config` and `/proc` file reads are refused with an audit record. (#1215, #1216) +- **`bin/add-skill` accepts only plain skill names,** so `..` or `/` can't write outside + `skills/`. (#1202) +- **Inbound message text stays out of Actions run names and logs** in `messages.yml` (source, + length and a short hash only). (#1201, #1213) +- **`vuln-poc-gate` hardening:** a PoC must sit inside the PoC dir (no `..` or links), and files + a PoC creates in the target count as mutation. (#1218) - **Security audit fixes (2026-10-01).** The dashboard binds to `127.0.0.1` only; the health step takes its values through `env:` (no shell injection); `secretcurl` escapes newlines, rejects malformed option tokens and no longer sends its config (with the substituted secret) as a @@ -1288,6 +1360,10 @@ from or pin to; the template keeps serving the latest `main` to new forks. ### Maintenance +- CI and housekeeping 2026-10-12 to 2026-10-17: catalog sha refresh (#1198), cached bubblewrap + `.deb` (#1205, #1231), one parallel shellcheck pass (#1224), CI on Blacksmith runners with small + checks on GitHub (#1225, #1228, #1236), test suites in 10 parallel lanes (#1238), aeon-agent refs + moved to aeonfun (#1229). - Dependency bumps 2026-10-07: `sharp`, `@modelcontextprotocol/sdk`, `proxy-addr`, `source-map-js` and an npm_and_yarn group (#1171, #1172, #1173, #1174, #1175). PR numbers for entries above that shipped without one: Aeon Connect onboarding docs (#1163), hosted MCP pointers diff --git a/docs/ADK.md b/docs/ADK.md index 52657cedd12..cbe8d995a63 100644 --- a/docs/ADK.md +++ b/docs/ADK.md @@ -276,7 +276,7 @@ Report only signal via ./notify - a clean run sends nothing. Conventions that matter: -- **`requires:`** - exact env-var names. This drives the dashboard's "which skill needs which key" UI and your own pre-flight in §4.1. Secrets reach the run environment; secret-bearing calls go through `./secretcurl` with `{PLACEHOLDER}` tokens (a raw `curl …$KEY` is blocked by the permission layer). +- **`requires:`** - exact env-var names. This drives the dashboard's "which skill needs which key" UI and your own pre-flight in §4.1. Secrets reach the run environment; secret-bearing calls go through `./secretcurl` with `{PLACEHOLDER}` tokens (a raw `curl …$KEY` is blocked by the permission layer). In a run, `./secretcurl` only fills placeholders for names listed in `requires:`, so a key you forget to declare is refused, not sent. - **`mode: read-only`** if the skill shouldn't touch the repo - write tools are stripped and stray writes reverted. Declare honest `capabilities` (§5.2) for everything else. - **If your product is an MCP server**, declare `mcp: [your-slug]` instead of raw API calls, and ship the server entry for `.mcp.json`. OAuth-connected MCPs get a Connect button in the dashboard. - **Notify on signal only.** The `./notify` tool fans out to whatever channels the operator configured (Telegram/Discord/Slack/email) - your skill's reports arrive where the operator already lives, for free. diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 46e94871391..08c8ca4ed5e 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -124,6 +124,16 @@ mode: write # full access (the default): adds Write / Edit / git / gh / py `read-only` strips the repo-mutation tools from Claude Code's `--allowedTools` (`Write`, `Edit`, `Bash(git:*)`, `Bash(gh:*)`, python) **and** the OS sandbox write-locks the workspace for the run (see [Capabilities → enforcement layers](CAPABILITIES.md)), so a research-and-notify skill **physically can't** commit, push, open a PR, or change code or config. The two state dirs are the exception: `memory/` and `output/` stay writable (via a shell redirection or `node`) so a read-only skill can keep its own state and artifacts (since #1042). Route the run's result through your **final message** (the run's captured output) and `./notify`. After the run the workflow persists your captured output to `output/.chains/`, **appends the `### ` entry to `memory/logs/` on your behalf** (so read-only skills should not self-log, or the entry appears twice), and reverts any stray write outside `memory/` and `output/`. Use it for pure read-and-notify skills; `write` (the default, a strict superset) for anything that writes code. It's the runtime half of the install-time [`capabilities:`](../docs/CAPABILITIES.md) hint. +## Run guards + +A skill run has push credentials, so the steps after it treat what it left behind as untrusted: + +- **Code that later runs stays off main.** On the default branch, any change a run made under `scripts/`, `.github/` or `harness-adapter/` (left in the tree or committed) is restored to a freshly fetched `main` and reported with an `::error::`; the rest of the run's state is committed as usual. Skills that change those paths on a feature branch and open a PR (`aeon-update`, `skill-repair`, `self-improve`, `create-skill` and others) are unaffected. (#1214, #1216) +- **Push helpers come from the run's starting commit.** The commit steps run `git-push-retry.sh` and `audit.sh` from `$GITHUB_SHA`, never the working tree, with git hooks off. A `Lock git config` step right after `Run` drops `.git/config` keys that make git run a program (fsmonitor, filters, merge drivers, credential helpers, signing, includes, url rewrites) and then rebuilds the checkout's HTTP auth from fresh workflow secrets, so pushes keep working. (#1216, #1241) +- **`./secretcurl` fills only declared secrets.** A placeholder is substituted only when the skill lists that name in `requires:` (`GH_TOKEN` and `GITHUB_TOKEN` are always allowed); curl runs with a stripped environment and options that make it read env vars or `/proc` are refused. A refused call leaves an audit record with names only. (#1215, #1216) + +These are backstops, not a hard boundary: a write-mode run still has `GH_GLOBAL` in its env. + ## Dry-run gate for self-authored skills `create-skill` and `self-improve` write skills that reach `main` through auto-merging PRs. Left alone, the only thing between a generated skill and production is a Haiku score computed *after* it has already run with real secrets against real repos. For the part of the system that writes its own code, that ordering is backwards. @@ -277,6 +287,8 @@ The template ships a few starter files under `memory/` (e.g. `MEMORY.md`, `watch Private repos: Free plan = 2,000 min/mo, Pro/Team = 3,000 + $0.008/min overage. To reduce usage: switch to `*/15` or hourly cron, disable unused skills, keep the repo public. Every run logs token usage to `memory/token-usage.csv` for a per-skill, per-model cost breakdown. +`memory-flush` skips itself before the model starts when no daily log changed since its last flush and that flush is under 7 days old (the `Idle gate (memory-flush)` step; cron state still records a success). Any doubt means it runs, so the worst case is one extra run. (#1217) + --- ## Authentication diff --git a/docs/harnesses.md b/docs/harnesses.md index 5c6135b9fcd..e2c74de7007 100644 --- a/docs/harnesses.md +++ b/docs/harnesses.md @@ -50,6 +50,16 @@ through OpenRouter: `moonshotai/kimi-k2.7-code` (default, code-tuned) and `kimi- routes through the same harness the skill ran on, so a repo with **no** Claude credentials still gets every run scored. +### OpenRouter app attribution + +Every OpenRouter request aeon makes carries app attribution headers, so usage is credited to Aeon's +OpenRouter app: `HTTP-Referer: https://www.aeon.fun`, `X-OpenRouter-Title: Aeon` (plus the legacy +`X-Title`) and `X-OpenRouter-Categories: personal-agent,cloud-agent`. One helper +(`harness-adapter/lib/openrouter-attribution.sh`) sets them for claude (via `gateway: openrouter`), +codex, kimi, vibe, pi and hermes; cursor, fx and grok have no OpenRouter path. A fork can set its own +with `OPENROUTER_SITE_URL`, `OPENROUTER_APP_TITLE` and `OPENROUTER_APP_CATEGORIES` in the run +environment. (#1235, #1239) + ### Native auth — run on your own provider account OpenRouter is the shared fallback; each harness can also run on its **own** diff --git a/plugin/skills/aeon/references/skill-anatomy.md b/plugin/skills/aeon/references/skill-anatomy.md index afe6e0b64aa..9d509048640 100644 --- a/plugin/skills/aeon/references/skill-anatomy.md +++ b/plugin/skills/aeon/references/skill-anatomy.md @@ -107,6 +107,8 @@ Claude Code's Bash permission analyzer **blocks any command containing a secret Braces, not `$`. A skill that writes `-H "Authorization: Bearer $XAI_API_KEY"` will be blocked at run time, not at author time. +In a scheduled run `./secretcurl` only fills placeholders for secrets the skill lists in `requires:` (plus `GH_TOKEN` / `GITHUB_TOKEN`). A placeholder for any other set key is refused with a message that names it, never its value, so declare every key you put in braces. curl runs with a stripped environment, and `--variable`, `--expand-*`, `-K` / `--config` and option values that read a file under `/proc` are refused. (#1215, #1216) + There is **no network sandbox** - plain `curl` works for unauthenticated GETs. ## Memory @@ -130,7 +132,7 @@ This is also the **dedup substrate**. The standard rule, and the one to add to a ### `memory/MEMORY.md` - the durable index (138 references across 59 skills) -Long-lived facts, not run history. Skills read it for context; the `memory-flush` skill promotes important log lines into it and prunes stale ones. Don't append per-run noise here - that's what `logs/` is for. +Long-lived facts, not run history. Skills read it for context; the `memory-flush` skill promotes important log lines into it and prunes stale ones, holds it under 8 KB with no line over 300 chars (it loads into every run), and ends each fact it adds with `[source: logs/YYYY-MM-DD#]`. Don't append per-run noise here - that's what `logs/` is for. ### Domain state files