Repository navigation
ci: Turbo seeds vs the 10 GB Actions cache pool — measure the pool, then shrink or retire the per-sha seeds #25452
Description
Filing gate: ② ruling-directed sibling card — batch #5 item 1, letter C (#25373 comment 6366946328, maintainer 「同意」 2026-10-23T14:13:20Z). Reader: the domain:devx execution seat, dispatch step. Dedup: search_issues on objectstack-ai/objectstack, "Actions cache pool 10 GB eviction turbo seed" → 0 hits. Session: cse_01LKHDniRQSWjRJyDtacwpEd.
One-sentence problem
Every push to main writes about 12.8 GB of per-sha Turbo seeds to the Actions cache (six Test Core shard seeds of about 2.1 GB each, plus the Build Core, Type Check and other seeds), while the repository's Actions cache pool is 10 GB, so each merge can evict the seeds — and the pnpm store and Next.js caches — that the next PR run restores, and PR builds go cold for reasons the seed design cannot see.
Evidence (file lines at objectstack commit 2b7c331)
- Per-sha seed keys, saved on every push event, including cancelled runs (
if: always() && github.event_name == 'push'):ci.yml:1397-1402(Test Core, per shard),ci.yml:2242-2247,ci.yml:2749-2754(Build Core),lint.yml:5928-5930(typecheck). Keys end in${{ github.ref_name }}-${{ github.sha }}(ci.yml:606,:1786,:2087,:2320,:2529,:2974;lint.yml:5140,:5753), so no two merges share a key and nothing is overwritten — every merge adds a full set. - Cancelled push run 39923516471 saved all six Test Core shard seeds at about 2.1 GB each (the ci: the push-to-main CI run is cancelled by the next merge 9 times in 13, so the Turbo cache seed that only that run saves goes stale and every PR shard and lint lane rebuilds cold (Build Core 51 s → 4m30s, shard closures Σ 20–31 runner-min per run) #25373 card thread's falsification, comment 6364570166).
- Plain
actions/cache@v6steps (restore and post-save on every event, PRs included) sit in 12 workflow files;ci.yml:2785-2798saves the pnpm store andapps/docs/.next/cacheon PR runs too. PR-scoped entries count toward the same pool. - The Turbo remote cache is ON: on PR ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds #25419 (card ci: no job asserts the Turbo remote cache is actually on — TURBO_TOKEN is withheld whenever the signing secret is empty, turbo then prints "Remote caching disabled" and builds cold with nothing red; add the assertion to Build Core and the closure builds #25374) Build Core printed "Remote caching enabled" with 76/76 remote hits, and Type Check · workspace 71/71 (
TURBO_TOKEN/TURBO_TEAM,ci.yml:749-750). For the tasks the remote cache serves, the per-sha.turbo/cacheseed in the Actions pool may be redundant weight. - Pool usage is NOT measured yet.
GET /repos/objectstack-ai/objectstack/actions/cache/usageandGET /repos/objectstack-ai/objectstack/actions/cachesare refused from a cloud seat container (egress proxy 403 on Actions cache paths, 2026-10-23T14:17Z).
Governing text
ci.yml:597-610andlint.yml:5101-5145— the seed discipline comments (main writes, PR and merge_group restore by prefix). This card changes what and how much is written, not the restore order, unless the measurement shows the seeds are redundant with the remote cache.- AGENTS.md lines 371–372 are about the local worktree cache, not CI.
- Ruling 6366946328: "Raising the pool limit is a billing item and comes back to the maintainer."
Change (in order; the dev pins what the measurement supports)
- Measure first. Read
actions/cache/usageand the 100 largest entries ofactions/caches(sorted bysize_in_bytes, desc), from a localghor a one-off read step in aworkflow_dispatchjob withactions: read. Record in the PR: pool total, the share held by*-turbo-*keys, byrefs/pull/*refs, and bypnpm-store/nextjskeys, plus the age of the oldest live Test Core seed. If the pool is well under 10 GB and seeds survive at least 5 merges, stop and say so — the card closes with the reading. - Then shrink, cheapest first, choosing from: (a) drop the
.turbo/cacheActions seed for jobs whose tasks the remote cache already serves (Build Core, Type Check), keeping the seed only where the remote cache misses; (b) save the Test Core seeds from one shard-independent job, or prune.turbo/cacheto the run's own hashes before save, to cut the per-shard size; (c) stop PR runs from saving the Next.js cache (restore-only on PRs, as the Turbo seed already is). - Never raise the pool limit in this card. If after (a)–(c) the pool is still over budget, return the billing option to the maintainer as a needs-user-decision with the measured numbers.
Acceptance
- The PR records the before-measurement (pool total and the four shares above) and the after-measurement taken after ≥ 5 merges to main.
- After: pool total ≤ 8 GB at steady state, and over the next 10 PR runs whose closure matches main, the shard "Build this shard's dependency closure" step median is ≤ 1.7 min and Build Core's build step is ≤ 2.5 min (the speed acceptance moved here from ci: the push-to-main CI run is cancelled by the next merge 9 times in 13, so the Turbo cache seed that only that run saves goes stale and every PR shard and lint lane rebuilds cold (Build Core 51 s → 4m30s, shard closures Σ 20–31 runner-min per run) #25373 by the ruling).
- Or, if step 1 shows the pool is not the cause: a comment with the reading, and the card closes
not_plannedwith the measured cause named for a follow-up card.
Risks
- Dropping a seed the remote cache does not actually cover makes those jobs colder; the dev keeps the remote-cache hit counts from the
assert-turbo-remote-cachelines (ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds #25419, once landed) before and after. - Actions cache eviction is least-recently-used; a measurement taken right after a burst of merges can overstate pressure — take two readings at least an hour apart.
Work estimate
Lane domain:devx · 1 PR (.github/workflows/ci.yml, .github/workflows/lint.yml; possibly .github/workflows/*.yml for the Next.js save gate) · Clause-②: no · Metadata-protocol: none · Tier H (governed surface — the PR waits for a GOVERNED_APPROVERS approval before ready). Size M. Serial: lands after #25373's PR (same ci.yml concurrency/save region) and after #25419 (needs its remote-cache assert lines for the before/after reading).
Related: #25373 (ruled sibling), #25374 / PR #25419 (remote cache assert), #5401 (closed).
Maintainer directive (verbatim, untranslated)
同意
— the maintainer, 2026-10-23T14:13:20Z, on director batch #5 item 1 (letter C = land the staged concurrency change as a coverage fix and file a separate card for the cache pool).
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 23, 2026
Claim: PM loop round 3 · 2026-10-23T18:23Z
Session:
session_01SawdJgiuoz8deqVdM51jAE(card thread, dispatched by seat sessionsession_01LKHDniRQSWjRJyDtacwpEd)Account:
os-elon-muskBranch:
claude/project-thread-53z7nt(the harness-pinned branch for the card thread; it names no issue, so this claim is the identity record)Worktree:
objectstack-issue-25452Domain:
domain:devxSeat:
domain:devx#1(seat post #6023)File surface: .github/workflows/ci.yml, .github/workflows/lint.yml (possibly other workflow files for the Next.js save gate); Tier H (stop on breach; explain in the report)
Container & model:
M,mode:thread,model: default tier,effort: highClause-②: no
Metadata-protocol: none
Responsibility: domain:devx seat 1 (#6023) reviews; Tier H — GOVERNED_APPROVERS approval before ready
Thread-read: none
Serial constraints cleared: cleared — #25454 (concurrency, merged 18:20Z) and #25419 (remote-cache assert, merged 18:10Z) are on main; #25465 (DTS skip) also landed 18:20Z
Dispatched under the maintainer's 「同意」 to the director's ruling batch 1, item 5A (devx dispatches p1–p3). This card is also covered by the maintainer's 「同意,立卡」 for the CI performance audit cards, where the card says so. Dispatch order:
/mnt/project-files/pm-devx-seat/dispatch-25452.md.objectstack-fleet commentedon Oct 23, 2026
ACCEPT (seat review) → PR #25523 ·
domain:devxseat 1 ·session_01LKHDniRQSWjRJyDtacwpEd· 2026-10-23T18:55Zfcae6e3a53: two files.scripts/ci/prune-turbo-cache.mjsis new (+381) with a 25-case self-test, wired into Build Core..github/workflows/ci.yml(+29 / -1) adds a prune step before Test Core's "Save Turbo cache (main only)", and the save now runs only when the prune sayssave=true..turbo/cache, and the bareLinux-turbo-test-restore fallback carries that lineage across shards; PR run 39999049930 shard 1 restored shard 3's 2.50 GB seed. This is card change (b).--summarizerun summary (.turbo/runs/, whichci.ymlwrites on both the package and the slice legs), plus the closure build's summary that the ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds #25419 assertion moved to$RUNNER_TEMP/turbo-remote-cache. All three files of every other entry are deleted. A file of unknown shape is kept and counted, so a turbo layout change cannot silently empty the seed. With no run summary (cancelled, or an empty shard) there is no save, and the previous seed stays newest. Every run-time path exits 0, so the shard attestation is unaffected.--self-testat this head is OK (25 cases, 5 batteries). CI is all green: 34 success, 11 skipped.actions/cache/usageand the largest entries) is pending. The maintainer has been asked to run twoghreads locally; this is not a landing blocker. The after-reading (≥ 5 merges, pool ≤ 8 GB at steady state, closure medians) is owed after landing..github/workflows/ci.yml). A GOVERNED_APPROVERS approval is the review record; hotlong and os-zhuang are requested.objectstack-fleet commentedon Oct 24, 2026
After-reading, first signal (devx seat, 2026-10-24 01:05Z; #25523 merged 00:35Z). Two push runs so far; the acceptance asks for ≥ 5.
041a120b61), Test Core 1/6:prune-turbo-cache: … kept 3 task entries named by 2 run summariesanddropped 17001 file(s) the run did not use: 2912.4 MB -> 0.8 MB on disk. It then savedLinux-turbo-test-1-main-041a120b61…. Shard 2 also saved.NOT SAVED -- no readable run summary. Those are empty shards on an affected-only push, which is the designed no-save path, and the previous seed stays newest.Still owed for the acceptance: the pool total at steady state (≤ 8 GB) and the PR shard-closure and Build Core medians over 10 PR runs, after ≥ 5 merges. The seat reads them on the next check.
Generated by Claude Code