research: attention budget measured + Agent Loop Engineering rubric (25/28, gate FAIL) - #48
Merged
Merged
Conversation
…inciple Studies arXiv:2608.12610 "@skills: Attention is all you have" (Yin et al., 12 Aug 2026) + SylphAI-Inc/atskills, applies it to this operator's real skill library, and extends it to two other agentic resources. APPLIED — residency_audit.py (offline, deterministic, measures and PROPOSES only). On the live library: 221 SKILL.md entries, 176 distinct names against the paper's argued bound of 100 = 1.76x over. Resident index 34,120 chars (~8.5k tokens) vs 2,954,435 chars (~739k tokens) of bodies = a content-to-index ratio of 86.6x, which is the paper's thesis as a single number. Four predicted failure classes, all present: 17 PHANTOM entries (dangling symlinks into a dead gstack/ path — they hold a name and load nothing, and fail SILENTLY, which is the inverse of wasted attention); 25 DUPLICATE names; 72 of 176 descriptions OVERLONG past the ~120-char guidance (worst 11.6x); 0 UNTRIGGERED. The tool never mutates a library: which capabilities deserve residency is operator judgement. R&D 1 — trigger_reliability.py measures the quantity the paper explicitly does NOT measure ("bounded by argument and by the literature rather than measured by us") and names as future work. Subject gpt-oss-120b/Groq, probe generator from a DIFFERENT family (Gemini, Claude fallback) so request wording is not authored by the router. Declared bias: probes derive from each target's own description, so results are an OPTIMISTIC UPPER BOUND. Failed calls are excluded from the denominator, never scored as misses; responses are disk-cached; an N with <8 usable trials reports "insufficient data" rather than a number. Two measured transport traps worth the comment they carry: Groq's Cloudflare 403s (1010) on urllib's default User-Agent while accepting the same payload from curl; and gpt-oss bills reasoning to max_tokens, so a small cap returns EMPTY content — a false "model said nothing" that is really a budget bug. R&D 2 — tool schemas: the harness already ships this principle, listing ~190 MCP tool names with schemas withheld until ToolSearch. Sampled cost n=2 => ~30x ratio, same order as skills. Marked an estimate, not a census. R&D 3 — instructions: 19,314 chars (~4.8k tokens) resident every session, plus 63 per-project CLAUDE.md totalling ~127k tokens. The Projects-root CLAUDE.md is 3.3x the global one and is mostly a venture directory — tier-1 reference wearing tier-3 clothes. And the pattern predates the paper here: backbone.md (always) + playbooks.md (172 chars, index-only) is the same split, hand-rolled. Prior art across four windows, with the graveyard: 300y — Cutter's Objects (1876) still cited by IFLA's ICP (2016), Dewey's computed address, against fixed-location shelving and Otlet's Mundaneum. 30y — HTTP caching re-specified as RFC 9111/STD 98 (2022), git content-addressing, and AppCache's death BY declarative manifest, which is why "no manifest" is a lesson rather than a taste. Also names a real gap: virtual memory (1962) and Denning's working set (1968) fall between the 30-year and 300-year windows and are not generationally proven. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…s were wrong
The frontmatter reader used `^description:\s*(.*)$`, which captures the INDICATOR
of a YAML block scalar. Every skill written as
description: |
real text here
was therefore measured as having a ONE-CHARACTER description ("|"). The parser
never failed; it returned a plausible wrong value — the precise failure class the
audit exists to report, committed inside the audit itself.
Two deliverables were corrupted:
1. The audit understated residency. Corrected numbers:
resident index 34,120 chars -> 62,010 chars (~15.5k tokens)
content:index ratio 86.6x -> 47.6x
overlong descriptions 72 of 176 -> 130 of 176 (74%)
untriggered 0 -> 1
Unchanged: 221 entries, 176 distinct, 1.76x over the argued bound, 17 phantom,
25 duplicates.
2. The experiment's ground truth was meaningless. Probes are generated from each
target's description, so a "|" description produced generic, TRUNCATED, and in
several cases IDENTICAL requests: three unrelated targets (unfreeze, benchmark,
review) all received "Hey, can you pull", and moomoo-comment-sentiment was
probed with "Can you check my calendar". The 20-33% accuracies from that run
measured nothing but this bug and are discarded, not published.
A second, independent cause of the same corruption: the generator ran at
max_tokens=200 and Gemini 3.6 bills reasoning against that budget, so responses
came back as 15-28 char fragments. Raised to 1200. This is the same trap already
documented for the subject model on a different provider — two providers, one
lesson: if an answer looks truncated, suspect the token budget before the model.
Ships skillmeta.py (one shared reader, handles plain/quoted/|/>/ chomping and
indent indicators) + test_skillmeta.py (10 tests, including a regression guard
that fails if any indicator-only description reappears in a real library), and
rewires both tools to it, removing the duplicated parser.
The README records the correction rather than quietly restating the new numbers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ate; count the deferred tool surface instead of estimating it The repo's own design-fitness budget (max-complexity 10) failed on main() at 12. Extracted _one_trial / _build_probes / _sweep. ruff clean. Also retracts an eyeballed number in my own README: the deferred MCP tool surface was stated as '~190'. Counted from the harness's own notices it is 132 at peak (25 built-in + 62 claude.ai connectors + 5 moomoo + 40 notebooklm), of which 67 were withdrawn mid-session. A 1.44x overestimate, corrected in place with the retraction left visible. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… past ~40-80 skills The @skills paper states its central quantity is "bounded by argument and by the literature rather than measured by us" and names the experiment as future work. Here it is, run against a real 175-skill corpus: N=10 100.0% (24 trials, CI 86-100%) N=40 100.0% (24 trials, CI 86-100%) N=80 83.3% (24 trials, CI 64-93%) N=176 44.4% ( 9 trials, CI 19-73%) Routing is perfect to 40, degrades at 80, collapses at the full library. The break falls BETWEEN 40 and 80 — below the paper's argued bound of 100, so the bound is directionally supported and, on this corpus, generous. This operator's library is 176 skills: the collapse cell. Stated limits, in the README and not only here: one subject model, one corpus, 12 probes x 2 seeds; the N=176 cell rests on 9 usable trials after 15 calls were lost to free-tier limits, so it shows a collapse without locating one; and the probes are still the declared optimistic bound, since they are generated from each target's own description while real user phrasing never quotes it. The failure SHAPE matters as much as the rate: at both degraded cells the model mostly picks the WRONG skill rather than abstaining (80: 3 wrong / 1 none; 176: 4 wrong / 1 none). A silent misroute is harder to catch than a refusal. results.json is now tracked, so the per-trial record is reviewable rather than a number I assert. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ture — 25/28, gate FAIL A webinar summary (DataApplab/AI聘, 2026-08-20) lists sixteen sections of what a mature agent loop must have and verifies none of it against a running system. It is a rubric wearing an essay's clothes, so it is encoded as one: docs/rubrics/agent-loop-engineering.yml the claims, as data (single source) scripts/audit_loop_rubric.py probes them against shipped code + real tests Evidence is OBSERVED — a symbol at file:line, or a pytest node that is actually executed. No evidence means no. A probe that cannot run is `unmeasured`: excluded from the rate AND blocking, because "I could not look" is not "it works". THE FIRST RUN SCORED 23/23 AND THAT WAS THE BUG. A rubric authored by someone who already knows the codebase, which then passes everything, has measured nothing. So I went back to the lecture for the claims I had NOT encoded, chose them because I expected them to fail, and the honest score is now: 25/28 (89%) implemented · 3 declared gaps · 0 unmeasured · gate FAIL Made true this commit (was a miss): cross-run task success rate. Section 14 asks for tokens, time, iterations AND success rate; the first three were per-run and the fourth did not exist. MemoryStore.success_rate() adds it with two choices that decide whether the number is honest — a still-running run is excluded from the denominator rather than counted either way, and blocked_safety counts as a FAILURE, since a rate that forgave safety blocks would reward the outcome the gate exists to prevent. It returns None, never 0.0, when nothing has finished: "not measured" must not read as "tried and failed". 6 tests. Still missing, recorded as misses with a reason rather than reclassified as passes: ReAct-style interleaving (divergence — ReAct lets the actor judge its own next step, and here the maker never grades), human takeover of a running loop (a real gap; the gate is end-of-run only), and manager-worker hierarchy (divergence — coordination is an inspectable dependency DAG, not a runtime manager). Three declared gaps whose probes FAIL if the gap ever silently closes: typed failure taxonomy, branching search, span-level trace schema. 606 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two external sources, both of which assert without verifying. Neither is taken at its word.
A —
@skills(arXiv:2608.12610, Yin et al., 12 Aug 2026)The paper argues skills compete for "fewer than a hundred reliable auto-trigger slots per agent" and is explicit that this is not measured: "bounded by argument and by the literature rather than measured by us", naming the experiment as future work.
research/attention-budget/residency_audit.py— offline, deterministic, measures and proposes, never mutates. On a real 176-skill library: 1.76x over the argued bound; resident index 62,010 chars (~15.5k tokens) against 2.95M chars of bodies = 47.6x; 17 phantom entries (dangling symlinks that hold a name and load nothing), 25 duplicate names, 130/176 descriptions past the ~120-char guidance.research/attention-budget/trigger_reliability.py— runs the paper's own named future work:The break falls between 40 and 80 — below the argued 100, so the bound is directionally supported and, on this corpus, generous. Subject and probe-generator are deliberately different model families. Failed calls are excluded from the denominator, never scored as misses. Declared bias: probes derive from each target's description, so this is an optimistic upper bound. The N=176 cell rests on 9 trials and shows a collapse without locating one.
Two self-corrections, shipped as commits rather than quietly fixed
^description:\s*(.*)$, which captures the indicator of a YAML block scalar. Everydescription: |skill measured as a one-character description. It never failed; it returned a plausible wrong value. That made the audit numbers wrong (86.6x → 47.6x, 72 → 130 overlong) and corrupted the experiment's ground truth — three unrelated targets received the identical probe "Hey, can you pull". Those results were discarded, not published. Fixed inskillmeta.py, pinned by 10 tests including a regression guard.B — Agent Loop Engineering (webinar summary, 2026-08-20)
Sixteen sections of what a mature agent loop must have, verified against nothing. Encoded as a rubric:
docs/rubrics/agent-loop-engineering.yml— the claims as data, single sourcescripts/audit_loop_rubric.py— probes them against shipped code and executed testsEvidence is observed (a symbol at file:line, or a pytest node that actually ran). No evidence means no. A probe that cannot run is
unmeasured: excluded from the rate and blocking.The first run scored 23/23, and that was the bug. A rubric authored by someone who already knows the codebase, which then passes everything, has measured nothing. Rereading the source for claims chosen because I expected them to fail gives the honest score:
Made true here:
MemoryStore.success_rate()— section 14 asks for tokens, time, iterations and success rate; the first three were per-run and the fourth did not exist. In-flight runs are excluded from the denominator;blocked_safetycounts as a failure, because a rate that forgave safety blocks would rise when the gate fires; returnsNone, never0.0, when nothing has finished. 6 tests.Still red, with a reason recorded beside the mark and no mechanism to convert a reason into a pass: ReAct interleaving and manager-worker (design divergences — ReAct lets the actor judge its own next step, which breaks maker≠checker), and human takeover of a running loop (a real gap, no plan).
Three declared gaps whose probes fail the moment the gap silently closes: typed failure taxonomy, branching search, span-level trace schema.
Evidence
606 tests pass, ruff clean.
python3 scripts/audit_loop_rubric.py --gateexits 1 today, by design.🤖 Generated with Claude Code