29 KiB
Tool-calling cut map (Imagination, 2026-10-01)
A dated map. Self's rotation threshold is owned by the SKILL.md rotation
bullet (about 400k since 2026-10-12); the Self figures below are as of
2026-10-01. The Hands and Soul caps below still stand.
Target: fewer model calls, and less context re-read by each call, with the
Soul loop untouched. Pinned to skill HEAD 92bf6f7. Eyes' facts are in the
session scratchpad (eyes-tool-calling-facts.md). The classifier scripts are
tc_index.py, tc_classify.py and tc_comp.py in the same scratchpad, and
every number below can be rerun from them.
0. The cost model (measured)
Every model call re-reads the whole context. A subagent starts at ~70k tokens: about 34k shared system prompt and tools, plus about 36k written per agent (CLAUDE.md files, brief and listings). It then grows by a nearly constant ~1.7-1.9k tokens per call. In the two largest Hands there was no single jump over 15k: affba1c4 went 69k→742k over 386 calls, and a0a3154a went 70k→781k over 332. So for an agent of N calls:
reads ≈ N·70k + 0.9k·N²
For a 390-call Hands the N² term is ~85% of its 163M. Call count is the lever, and it acts quadratically. Halving a long agent's calls cuts its reads by about 3x. Splitting it in two at the midpoint cuts them by about 40%.
The 5-minute subagent cache TTL is real. Measured over all subagent calls since 09-29:
| gap since previous call | calls | cache write | avg write |
|---|---|---|---|
| < 60 s | 25,232 | 56M | 2k |
| 60-300 s | 2,336 | 5M | 2k |
| 300-3600 s | 1,241 | 292M | 235k |
| > 1 h | 10 | 2.5M | 249k |
79% of all subagent cache writes come from the 4% of calls that follow an idle gap of more than 5 minutes. Each of those rewrites the agent's whole context at 1.25x the base price, where a cache read costs 0.05-0.1x. The quota weighting of reads against writes on a subscription is unpublished, and Eyes flagged it as open. In API-price terms, these rewrites are roughly a third of subagent input cost.
1. Waste taxonomy (measured, 09-29 → 10-01)
Self (root), 09-29/30, deduplicated by message id
- 2,135 model calls, 984M context read, median context about 500k, peak 924k.
- 1,703 of the 2,135 calls (80%) emitted no tool call. 1,035 of them had no text at all: Self woke up, read about 500k, and ended the turn.
- 1,324 text-only calls followed a task notification. They cost 596M, 61% of root reads.
- Root received 602 "Agent … finished" notifications from 245 agents.
68 agents finished more than once, giving 357 interim notifications: one
Hands 29 times, two Souls 21 times each. Docs: a background subagent's
results reach Claude "as a completion notification", and a subagent's own
background command notifies the subagent when it ends. Measured: every
interim turn end of a subagent reached the root as a finished notification.
The pattern in
92bf6f7("end the turn with the waiter running and say nothing") is exactly this pattern. It moves the wait's cost from the subagent (~200k context) to Self (~500-900k). - Agent results pasted into root: median 203 chars, p90 7.7k chars, about 404k tokens over two days. The p90 is the "raw verification output, pasted" clause in the Hands report.
Hands: 167 agents, 16,863 calls, 3.79B read
| class | calls | share of reads | what it is |
|---|---|---|---|
| search (Bash grep/find/rg) | 21.2% | 19.0% | Mostly legitimate orientation. Avg result 700 tok. |
wait.poll (foreground until/for … sleep) |
11.5% | 14.9% | e.g. for i in 1..18; do grep …; sleep 20; done; tail -60, repeated per job |
| verify.read_log (tail/cat/grep a job log) | 9.0% | 10.2% | reading raw logs after or between polls |
| read.file | 12.3% | 9.9% | avg 1.9k tok per result, the largest growth source |
| edit (Edit/Write) | 9.4% | 10.2% | necessary |
| verify.launch | 8.6% | 8.6% | 8.6 jobs per agent, often one per probe or mutant |
| git.read | 9.3% | 7.9% | status, log, diff, show |
| edit.script (python heredoc editors) | 6.5% | 7.3% | each agent re-invents a CRLF/BOM-preserving def edit(p,f); its inputs were the largest context item in 3 of 5 heavy Hands (39-56k tok) |
| git.write | 2.4% | 2.5% | add/commit/push, plus Write for the message file and a git log -1 check |
| wait.monitor + wait.stop + ssh.inspect | 3.8% | 4.1% | Monitor arms, TaskStop, ssh docker/ls checks |
- Waiting and observing (poll, read_log, monitor, stop) took 3,852 calls against 1,443 launches: 2.7 observation calls per job.
- Exact duplicate calls: 1,564 (9.3%), mostly re-polls.
- Ad-hoc harnesses were reinvented per agent:
runmut.sh,runprobe.sh,harness.sh,fulljob.sh,mutjob.sh,mutrun.sh,strykrun.shandscriptrun.shappear across the sampled Hands and Souls. They are the same three jobs (verify, mutate, probe), written fresh each time.
Soul: 146 agents, 8,752 calls, 1.40B read
- search 23.4%, git.read 21.2% (avg result 1.1k: the range diff re-read piecemeal), read.file 12.4%.
- Waiting and observing: wait.poll 9.3%, read_log 9.3%, monitor and stop 1.9%. That is 1,800 observation calls against 813 launches (2.2 per job).
- Sampled Soul aba0348c: 163 calls, 6
mutrun.shand 5strykrun.shlaunches, each followed by its own poll and read cycle.
Imagination: 25 agents, 2,130 calls (85 each), 431M read
- search 28.5%, git.read 24.5%, read.file 18.6%. Orientation by single shell calls, where probe scripts would do the same work in fewer calls.
Baseline prefix
- The global
~/.claude/CLAUDE.mdis 56k chars andF:\Projects\CLAUDE.mdis 14k chars, about 17.5k tokens together. Both load into every subagent. - Over about 28.8k subagent calls since 09-29 that is about 500M re-read, about 9% of subagent cache reads.
2. Target call shape per faculty
These are the target numbers per faculty. "Script per phase" means one Bash call that runs a written script and prints a bounded result. It replaces chained single commands.
| faculty | calls | peak ctx | phases (one script or one parallel batch each) | lifetime |
|---|---|---|---|---|
| Self | ≤ 3 per dispatched agent (dispatch, read the final notification, triage) | ≤ 300k, rotate past it | rehydrate is one recipe batch; triage is parallel views |
rotates at phase boundaries (§4) |
| Imagination | 40-80 | ≤ 250k | (1) an orient script that dumps git log, file:line excerpts and grep hits to a scratch file and prints ≤ 150 lines; (2) probe scripts, one per question, each run in one verify job; (3) one admit batch |
one map pass per agent; a refresh is a new agent |
| Hands | 60-150 | ≤ 300k | (1) an orient script: status, base, spec view, and sed -n excerpts of the spec's anchors in one call; (2) edits through Edit, with independent edits in one parallel message; (3) one verify job (build, scoped tests, mutation) through ygg-verify summary mode, waited in the foreground (§3a); (4) one commit call per commit; (5) the report admit |
hand off at ~300k or ~150 calls: commit what is verified, admit the cut_report with undone, stop. Self dispatches a continuation |
| Soul | 50-120 | ≤ 300k | (1) dump the range once: git diff base..head > $S/range.diff plus --stat, then grep that file instead of re-running git show per file; (2) one probe job carrying all probes, the hand mutants as a list (§3b) and the scoped reruns; (3) one final job: full suite plus the mutation tool; (4) the verdict admit |
a second pass covers only the fix delta (already ruled) |
| Eyes | ≤ 40 | ≤ 200k | parallel WebFetch and search batches; transcript work as scripts, never whole reads | one question set per agent |
| Life | ≤ 25 | ≤ 150k | one inventory script over the surfaces, then the edits | per phase boundary |
Rules common to every faculty:
- Observation bounds. No command prints more than ~150 lines. Logs go to a
file. You read
tail -n 60, orgrep -nhits with-m. You nevercata whole log or source file over ~300 lines; read the anchor's range instead. Reading in 100-line windows matches the SWE-agent ablation (18.0% against 12.7% for full-file views). Reading a file twice is a smell. Write what you need to keep to a scratch notes file instead. - Parallel tool calls. Independent reads, views and greps go in one message. This saves wall time and turns, not reads.
- No turn ends before the report. A subagent's turn end is a paid wake of Self (§1).
3. Tooling ledger, and the shared script body
Code is a liability, so deletions come first:
- Delete the
git log -1 --format=%Bcheck (briefs.md 305). - Delete "poll the log" (briefs.md 309).
- Delete "Run long builds detached … and poll" for agents (SKILL.md 577-579).
- Delete the raw-output paste in the Hands report (briefs.md 334-336).
- Delete the per-agent harness reinvention, by replacing it with the shared scripts below.
| tool | owner | consumer | calls saved (from the taxonomy) | carrying cost |
|---|---|---|---|---|
(a) ygg-verify summary mode + foreground waiter. SUMMARY=1 keeps the full log in a file and prints a bounded summary: exit verdict, pass/fail/skip counts per test binary (and a ZERO TESTS RAN line when the count is 0), failing test names, and the last 30 lines of each failure, capped at ~80 lines. The companion wait mode blocks ≤ 270 s per call on a done-file and prints RUNNING <elapsed> or the summary. |
the stopgap's owner (the skill repo). It dies with the stopgap when Idunn's typed verify verdict lands, and must not outlive the deletion line in ygg-verify.sh |
Hands, Soul, Imagination probes | Observation calls fall from 2.7 to ~1-2 per job: about −2,400 Hands and −1,000 Soul calls per two days, ~13% of calls. Because of N², that is ~15-20% of reads | ~60 lines of bash plus a parser per ecosystem (cargo test, dotnet test, vitest, pytest). Verdict-bearing: a summarizer that drops a failure forges a green. It gets a Soul pass before merge, plus a fixture test per parser: a failing run, a zero-test run, a killed run and a no-verdict run |
(b) mutation runner. It takes the ecosystem tool's diff scope, or a list of hand mutants (file, before, after, tests), and returns a kill table (label, outcome, killing test) in one job. Hand mutants are applied in the container clone, so the tree is never touched |
same | Soul primarily, Hands for the scoped run | Replaces the reinvented mutrun/strykrun/runmut scripts. One job instead of one per mutant: in aba0348c, 11 launches with their wait/read pairs become ~2. Estimate (inferred): −20-40 calls per Soul pass |
~100 lines. Verdict-bearing: same Soul and fixture rule. It must report unviable and timeout separately from caught (the brief's totals already require this) |
(c) commit helper. Not built. In Git Bash, git add <paths> && git commit -F- <<'MSG' … MSG && git push is one call. The BOM and here-string scar is PowerShell-only (SKILL.md 568-571) |
— | Hands, Self | ~1.5 calls per commit, ~1.5% of Hands calls, at zero code | none. A brief and SKILL text change only |
(d) CRLF/BOM-preserving edit. Probe first: does Edit preserve CRLF and BOM on these repos? If yes, the brief says "use Edit; no python editors" and nothing is built. If no, one shared edit.py replaces 1,097 reinvented editors |
probe: Self, now | Hands | 6.5% of Hands calls, and the largest tool-input context item | zero if the probe passes, ~30 lines if not |
| (e) an orient script per faculty | — | — | not a shared tool: one line in each brief ("orient in one script") | none |
3x. The shared script body (operator: "Is that too ambitious?")
Direct answer: no, provided it stays a directory in a git repo with ordinary
review. It is small and it already exists: tools/stopgap/ in the skill
repo. What the data shows is the opposite problem. Every Hands and Soul writes
its own runmut.sh or python editor and throws it away, and that costs calls
and context in every pass. The ambitious part would be a bespoke admission
process, and per the operator's follow-up none is needed: collaborating on code
is a solved problem.
Facts (gamecult-ops):
- Forgejo 16.0.3 runs on Yggdrasil at
127.0.0.1:3300behind nginx asgit.erycina.org. - Its purpose is "public, anonymously readable source hosting for Erycina". The inventory says Erycina is "not a GameCult subdomain by intent … meant to read as creator-owned and separately stewarded".
- Actions are deliberately not enabled: "CI runners on the same host as the state store … Revisit when there is something to run".
- Registration is disabled, and accounts are created by an admin through the forgejo CLI.
- Git runs over SSH through the host
sshdas thegituser, with keys registered in Forgejo. Agents would authenticate with an SSH key registered to a dedicated bot account (for push) and a Forgejo API token held outside briefs (for PRs). No secret appears in any brief or in this map. - No mirroring is documented. Forgejo supports push mirrors natively.
- As of 09-05 TLS was staged pending DNS. Whether it is issued now is unverified.
- The skill repo's
origintoday isgithub.com/GameCult/Eureka.
Shape (recommended, pending Q4):
- Where it lives: in the skill repo itself, in
tools/, with the stopgap staying undertools/stopgap/. It does not go in a separate repo. Scripts and briefs change together, since a brief names a script's flags, so one revision pins both. Agents already have the checkout at~/.claude/skills/eureka, so there is no clone path to manage and nothing separate to pin. Self records the skill SHA in the campaign's first brief line, which pins it for the run. - Contribution: an agent that writes a reusable script pushes a branch
tools/<name>and opens a PR. It never pushes tomain. The PR carries the script, its fixture test, and one line of evidence: which calls it replaces (a transcript count fromtc_classify.pyor a named pass) and its live consumer, the brief line that will call it. A PR without a consumer line is not merged. - Admission = merge. Self merges convenience scripts. Scripts whose output
a verdict depends on (the summarizer, the mutation runner, the waiter) are
cuts: a Soul pass on the PR comes before the merge, by the same rule as "a
release is a cut". Without Actions, the fixture tests run through
ygg-verifyon the PR head, and the reviewer pastes the summary line into the PR. Forgejo PR review is the record. - Discovery: a
tools/INDEX.mdwith one line per script (name, purpose, consuming brief section). Briefs name the exact script they want. Agents do not browse. - Pruning: an
INDEXline whose consuming brief no longer names the script marks it dead, and the next Self pass deletes it. Stopgap scripts keep their DELETION LINE header. Life does not touch scripts (they are Body); at a phase boundary it may report an INDEX entry with no consumer. - What stays out: anything that knows a project's layout (CultLib crate paths, Aetheria test names, a cut's mutant list). That goes in the project, or in the job's argument.
4. Self's lifecycle
What Claude Code supports, per the docs fetched 10-01:
/clear"costs nothing" and starts fresh. It is an operator command. Self cannot run it on itself.- Auto-compaction triggers near the auto-compact window.
CLAUDE_AUTOCOMPACT_PCT_OVERRIDEsets the threshold and "applies to subagents as well". Compaction "is itself a large request". - The main-conversation cache lifetime is 1 h on a subscription and drops to 5 min once usage credits are drawn. The 5-minute subagent TTL is measured above, not documented on that page.
- The env var
CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTLcomes only from a third-party repo (Eyes). It is unverified. - API-only: the context-editing and memory tools, programmatic tool calling, and the tool-search tool. Claude Code applies its own tool-result clearing and compaction. Self cannot call these.
Shape:
- No interim wakes. Subagents never end a turn before their report (§2, §3a). This removes the 357 interim notifications, worth about 600 root calls at ~500k, which is ~30% of root reads.
- Rotate the root at about 300k, or at each phase boundary, whichever comes
first. All campaign state is in Huginn, so the handoff is short: the
campaign slug, the session label and the next action, written to the
scratchpad. A clear ends the session's background agents (observed
2026-10-03), so rotate when none is in flight; see SKILL.md. Self then asks the operator to
/clear(Q3). A fresh root rehydrates with the campaign recipes, at about 100k. At a median root context of ~200k instead of ~500k, every remaining root call costs about 60% less. - Reports stay id-only. Hands and Soul return an id, a receipt and one sentence. Long raw output goes to a scratch file, and the report gives its path.
- Self delegates reading. It never reads a log or a diff itself. It reads
the verdict and the report by
view. - Backstop: if the operator prefers it, a lower auto-compact threshold (Q3) stops a forgotten rotation from riding to 900k.
5. Text changes (anchors at skill HEAD 92bf6f7)
references/briefs.md
- 275-283 (Hands "Long jobs" paragraph): replace with:
Long jobs: wait for them and finish, and never end your turn before your report. Each turn end reaches Self as a notification and costs a read of its whole context. Start the job as one background shell whose command exits only when the job does. Then wait in the foreground with
ygg-verify.sh wait <done-file>(oruntil [ -e <done> ]; do sleep 60; donewith a 270 s cap), one call at a time, each ≤ 270 s so that your cache stays warm. A call longer than 5 minutes rewrites your whole context. Never run a second watcher on the same job, no timer shorter than 60 s, and no interim message. (Pending Q1. If the operator picks B, keep the current text and add only the 270 s cap.) - 309: delete "Long builds run detached, with a log in the scratchpad;
poll the log." Replace it with: "Verify through
ygg-verify.shwithSUMMARY=1; read the summary, and open the full log only at a named failing test, withgrep -n -A 40." - 255-257 ("Verify once, at the end"): append "One job carries build, scoped tests and the mutation run (briefs Soul, 390-399)."
- 248-273 (context budget block): add three bullets:
- Orient in one script. One Bash call prints git status, base and the
spec's anchor ranges (
sed -n) for every file the spec names. Independent reads go in one parallel message. - Bound every observation: ≤ 150 lines per command; logs go to files; read windows, not whole files.
- Hand off at ~300k context or ~150 calls. Commit what is verified,
admit the
cut_reportwithundone, and stop. Self dispatches a continuation with the report id. This replaces the "far past" judgment at 263-273 with a measurable line. Keep the clause's warning against stopping because the scope looks large.
- Orient in one script. One Bash call prints git status, base and the
spec's anchor ranges (
- 296-306 (Commits): replace the Write-tool and
git log -1bullets with: "In Git Bash, one call:git add <paths> && git commit -F- <<'MSG' … MSG && git push. Never commit from PowerShell (it writes a BOM and breaks here-strings)." - 334-336 (Hands report): replace "then any raw verification output too long for an evidence line, pasted, not summarised" with "and, for output too long for an evidence line, the scratch path that holds it".
- 350-353 (Soul long jobs): same replacement as 275-283.
- 390-399 (Soul reruns): append "Dump the range once (`git diff ..<head> > /range.diff` plus `--stat`) and grep that file. Hand mutants go in one list to the mutation runner, never one job each."
- 428-430: unchanged. It is already id-only.
- 117-163 (Imagination map) and 91-112 (0b): add "Orient and probe through scripts: one call per question, output ≤ 150 lines."
- 469-480 (Eyes): add "Budget ≤ 40 calls; transcripts by script; batch fetches in parallel."
- 439-465 (Life): add "Budget ≤ 25 calls; inventory the surfaces in one script."
SKILL.md
- 215-236 (sizing): add after 219: "Size by calls too. Each call re-reads the context, so an agent's reads grow with the square of its calls (measured ≈ 70k·N + 0.9k·N²). A cut that needs more than ~150 Hands calls is two cuts, or one cut and a continuation."
- 451-513 (Self's discipline): add two bullets:
- Self's own context is the most expensive in the pipeline. Every
notification re-reads all of it. Rotate at ~300k or at a phase boundary:
write the handoff (slug, session label, next action; no agent in flight)
and ask the operator to
/clear(ruling: Q3). Never read logs or diffs in the root;viewreports and verdicts. - A subagent that notifies before its report is a brief defect. Count finished notifications per agent. More than one means a turn ended mid-wait, and the brief template is what gets fixed.
- Self's own context is the most expensive in the pipeline. Every
notification re-reads all of it. Rotate at ~300k or at a phase boundary:
write the handoff (slug, session label, next action; no agent in flight)
and ask the operator to
- 537-552 (Yggdrasil): the line says "at most 3 jobs at a time" and "12
GiB". The script says
SLOTS=5andMEM=6g. This is stale again. Drop the numbers and point at the script, as the line itself demands. - 568-571 (commit messages): replace with "Commit from Git Bash with
git commit -F- <<'MSG'. PowerShell 5 here-strings break-m, and itsOut-File/Set-Contentwrite a BOM." - 577-579 ("Run long builds detached … and poll"): split. Operator-side builds (Unity batchmode) stay detached, with a log and a PID. Agents wait in the foreground in ≤ 270 s calls (briefs Hands).
- New short section after 513, "Shared tools": the
tools/body,INDEX.md, the PR-as-admission rule, Soul before merge for verdict-bearing scripts, and pruning by consumer (§3x).
references/changelog.md
- New top entry: "Waiting costs no wakes". Evidence: 602 finish notifications
from 245 agents, 1,324 root text-only calls, 596M, and the 5-minute TTL table.
It amends
92bf6f7.
6. Operator questions
Q1. How does a subagent wait? (It amends 92bf6f7, landed today.)
- A. Foreground calls of ≤ 270 s on a done-file, about one call per 4.5 minutes. The cache stays warm and Self is never woken. Recommended. Per 10 minutes of waiting it costs about 2.2 cache reads, ≈ 0.2 context units, against 1.25 for one rewrite. Timers inside the call are ≥ 60 s, per the operator's floor.
- B. Keep the background waiter and the turn end (current). Measured: 357 interim root wakes in two days at ~500k each, plus a 235k cache rewrite per resume after 5 minutes.
- C. Foreground calls of up to 10 minutes. Fewest calls, but each one is a full rewrite. Pick C only if Q2 lands the 1 h TTL.
Depends on it: the briefs' long-jobs text and the waiter mode of
ygg-verify.sh.
Q2. Probe the subagent 1 h cache TTL? CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=1h
is unverified, from a third party. It doubles each write's price, and in
exchange idle gaps up to 1 h stop forcing rewrites (292M of rewrites in two
days).
- A. Self runs one bounded probe: set the variable, run a subagent with a
7-minute gap, and check
cache_creationon the next call. Then decide. Recommended. Settings are yours, so this needs a go. - B. Leave it alone.
Q3. How does Self's context get reset?
- A. Self writes a handoff and asks you to
/clearat about 300k or at a phase boundary. - B. Set
CLAUDE_AUTOCOMPACT_PCT_OVERRIDEso that auto-compaction fires around 300k. - C. Both: A by default, B as the backstop. Recommended.
Depends on it: Self's discipline text. The root stayed at a median of ~500k for two days.
Q4. Where does the shared script body live?
- A. In the skill repo's
tools/, on GitHubGameCult/Eureka, with PRs there. This costs zero setup. - B. The skill repo moves to Forgejo, primary, with a push mirror to GitHub. Review happens on Forgejo, beside where the scripts run. This means a GameCult org on a forge documented as Erycina's, "separately stewarded" and with a landing page fixed to Erycina, plus a bot account and key.
- C. A separate scripts repo on Forgejo, pinned by the skill. That adds a second checkout and a pin, for nothing the skill repo cannot carry.
Recommended: B if you are content to put GameCult tooling on the Erycina
forge, otherwise A. The workflow is identical either way: branch, PR, merge
as admission. Forgejo Actions stays off (the runbook's choice), and tests run
through ygg-verify.
Q5. Slim the always-loaded doctrine? The two CLAUDE.md files are about 17.5k tokens in every subagent, about 9% of subagent cache reads. Claude Code's docs advise keeping CLAUDE.md "under 200 lines" and moving workflow-specific text into skills.
- A. Move the long-form Cult, Praxis and Infrastructure sections into a referenced file. The Prime Directive, Code Is A Liability, the rebuild contract and the faculty lines stay inline. Recommended.
- B. Leave it.
It is your text; this is a question, not a cut.
7. Measured versus inferred
Measured (scripts in the scratchpad, rerunnable):
- the per-faculty class distributions;
- the 2.7 and 2.2 observation calls per job;
- the duplicate counts;
- the reinvented-harness names;
- the root call profile, its text-only share and the notification counts per agent;
- the context growth per call;
- the 70k baseline;
- the cache-write-by-gap table;
- the CLAUDE.md sizes;
- the Forgejo facts (gamecult-ops);
- the stale slot and memory numbers in SKILL.md.
From docs (fetched 10-01):
/clear, compaction andCLAUDE_AUTOCOMPACT_PCT_OVERRIDEreaching subagents;- the main-cache TTL;
- the background-command notification;
- the PreToolUse filter;
- the CLAUDE.md advice.
Inferred:
- That each interim subagent turn end produces a root notification. This is consistent with the counts and the docs, but no single event was traced.
- The per-tool savings estimates, and the calls saved by the mutation runner.
- The 300k and 150-call handoff lines. They are chosen from the N² model and the 400k "loopy" scar, not tuned.
- The quota weight of cache reads against writes. It is unpublished, so the savings are stated in reads and writes, not in quota.
Classifier limits: Bash commands are classified by regex on mixed command lines, so a compound call counts once, under its first matching class. Before reordering, the "verify.launch" class absorbed poll loops that grep for "ygg-verify:" in logs. The tables above are from the corrected ordering. Parallelism was not measured.
8. Rulings (operator, 2026-10-01)
Verbatim: "Q1 A, Q2 yes, Q3 agreed, Q4 B, Q5 yes, but see Epiphany's approach where each subagent gets its own targeted philosophy centered on its role".
- Q1 = A: subagents wait in the foreground, in calls of at most 270 s, and never end a turn before their report. This supersedes
92bf6f7. - Q2 = A: Self runs one bounded probe of
CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=1h. - Q3 = C: rotate at about 300k or at a phase boundary, with a handoff and the operator's
/clear. A lowerCLAUDE_AUTOCOMPACT_PCT_OVERRIDEis the backstop. - Q4 = B: the shared scripts stay in the skill repo on GitHub (
tools/,tools/INDEX.md), contributed by branch and pull request. - Q5 = yes: slim the global CLAUDE.md along Epiphany's per-role philosophy. A separate Imagination pass maps it.
9. Probe results (2026-10-01, Haiku 4.5, claude -p, a 7-minute idle gap)
CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=1h: CONFIRMED, though undocumented.- With it, the post-gap call read 112,158 cached tokens and created 401, all
ephemeral_1h. - Without it, the call read 29,331 and created 83,366, all
ephemeral_5m; the context had expired and was rewritten. - The official docs list only
CLAUDE_CODE_PROMPT_CACHE_TTL, for the main conversation.
- With it, the post-gap call read 112,158 cached tokens and created 401, all
CLAUDE_AUTOCOMPACT_PCT_OVERRIDEis documented as a percentage of the auto-compact window. It can only lower the threshold and it applies to subagents too. A value sized for the root would compact subagents early, so the Q3 backstop is not set; rotation carries Q3.
10. Q4 superseded (operator, 2026-10-01)
Q4 is now A: the Eureka repo, prose and tools/, moves to Yggdrasil's Forgejo and is shipped open source with contributions welcome. See faculty-philosophy-cut.md "Rulings" Q3 for the verbatim reason. Contributions use Forgejo PRs. Whether the GitHub copy is archived, mirrored or deleted is still open; ask the operator.
11. Follow-ups from the tools' Soul passes (2026-10-01)
The tools/ work merged after four Soul passes (last at 838b859). Recorded, not blocking:
- Jest
infailscope.infailresets only onPASSorTest Suites:, so a crash after an earlier failing file is named as a failing test. The verdict stays right; the name is wrong. Reset at a blank line or the next non-indented non-●line. - No automated guard for the RUN_ON_HOST watchdog (exit 124). It is proven only by the probe recipe in
tools/fixtures/mutation-probe/README.txt;tools/test-tools.shnever starts the stopgap, so reverting the fix stays green. - Shared volumes are outside the isolation. The cargo registry, nuget and
eureka-sccachevolumes carry state across the control and mutant containers. A test that counts into one could pass the control and read CAUGHT later. The runner header names the limit; no probe was built.