Repository navigation
Commit 842a0ae
ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds (#25419)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DY934Zuxuxy6J1RxTkCS2QV)_
Fixes #25374
Clause-②: no
Metadata-protocol: none
Claim: comment 6364174741 on the card (session
`session_01QPa866zGYAuVVnv8kKLnKg`, branch
`claude/project-thread-hr4due`). Tier H: `.github/workflows/ci.yml` and
`.github/workflows/lint.yml` are on the governed register, so this PR
stays draft until a GOVERNED_APPROVERS approval.
## 维护者速读(草稿)
**改了什么**:CI 里五处走 Vercel Turbo 远程缓存的构建(Build Core、Test Core
每个分片的依赖闭包构建、lint 的三条 Type Check 车道)后面各加一步「远程缓存是否开着」的断言。它读 turbo 自己打印的那一句
`Remote caching enabled / disabled / unavailable
(…)`,并把本次构建的远程命中、本地命中、未命中个数写进该 job 的 Step
Summary。新脚本一个:`scripts/ci/assert-turbo-remote-cache.mjs`;另把门禁
`check-ci-filter-parity` 的识别放宽到「`pnpm build` 后只跟这两个报告类参数」,其余写法照旧拒绝。
**为什么改**:远程缓存的 token
只在签名密钥非空时才传,任何一个密钥或变量缺失、轮换,缓存就静默关掉,构建照样绿,只在日志里留一句没人读的话。每个 PR
十条并行构建可能长期在冷跑而无人察觉。
**风险与代价(含回滚)**:合并队列与 main 推送(会写远程缓存的运行)在缓存关闭时会变红,直到有人补好密钥;PR
与定时运行只出黄色警告(fork PR 拿不到密钥)。Vercel 连不上或服务端报错只警告,不红队列。新增步骤耗时为毫秒级;两个新增的
turbo 参数不改变任何任务哈希(83/83 相同)。回滚:还原本 PR 即可,无数据或产物迁移。
**席位意见**:
**你要做的**:批准本 PR(受管面)。
## What changed
- **`scripts/ci/assert-turbo-remote-cache.mjs`** (new, `--self-test`
with a battery floor and the handshake). It reads the build step's turbo
**structured log** for the prelude line, and the run summary
(`--summarize`) for each build task's `cache.source`. The summary does
not record whether the remote cache was on, which is why both are read.
Verdict table (header is the authority):
- `enabled`: green.
- `disabled` (any reason), or `unavailable` for an account state (auth
failed, disabled for the team, usage limit, spending paused, the mid-run
403): **red on a writing run, a warning otherwise**. A writing run is
`merge_group`, or `push` / `workflow_dispatch` on `refs/heads/main`: the
`remote:rw` branch of the TURBO_CACHE expression.
- `unavailable` for a transient reason (`Could not connect`, `Unexpected
server error`): a warning on every run, so a Vercel outage does not
block the merge queue.
- no prelude line, no log, or no summary: exit 3 PREREQUISITE NOT MET on
every run.
- Remote hits are reported, never judged.
- **The five carriers** pass `--summarize
--log-file=.turbo/remote-cache/SITE.json` to their existing `turbo run
build`. The assertion step runs straight after each:
- Build Core: `The Turbo remote cache was on for the build`. Build Core
also runs the script's `--self-test` once, beside `check-dts-emitted
self-test`.
- Test Core closure: `The Turbo remote cache was on for this shard's
closure build`, with `--if-ran` (an empty shard runs no turbo) and
`--move-summary-to "$RUNNER_TEMP/turbo-remote-cache"`, so `.turbo/runs/`
is still the test step's alone for the drift check and the timings
capture. The closure comment that said "No `--summarize`" now says why
it is there.
- lint.yml `Type Check · workspace`, `· debt ledger` and `· consumer
gates`: `The Turbo remote cache was on for the workspace build`, `id:
turbo-remote-cache-was-on` + `continue-on-error: true`, so it is a lane
gate and `lane-verdict.mjs` carries its red while the lane's other gates
still run.
- Build Core's "Turbo remote cache (#21186)" comment gains an ASSERTED
paragraph. The other carriers point back to it.
- **`scripts/check-ci-filter-parity.mjs`** (one file beyond the
dispatched surface; see Deviations). Its Build Core subject required a
step whose `run:` is exactly `pnpm build`, so Build Core's new `pnpm
build --summarize --log-file=…` was refused. The recognizer
(`isBuildCommand`) now accepts `pnpm build` followed ONLY by the closed
list `--summarize` and `--log-file=PATH`. These flags change what turbo
reports, never the task set. Anything else still refuses. 9 new
battery-(9) cases, floor 33 → 42:
- pass: both flags, and `--summarize` alone;
- refuse: `--filter=…` beside them, `--affected`, an unknown flag
(`--force`), an empty `--log-file=`, a `--` passthrough, the same flags
on `pnpm test`, and a second command after the build.
- The fixture now quotes `run:` so a multi-line value stays one YAML
scalar.
- Ablations: making the flag check always true reds 6 of the 7 refusal
cases (the `pnpm test` one is held by the prefix check). Dropping the
prefix check reds the `pnpm test` case.
- The new script gets its Build Core guard row in ci.yml's `core:`
filter (`check-ci-filter-parity` derives it: Build Core runs the
script's self-test and assertion).
## Measured
- **Flags do not move a hash.** `turbo run build
--filter=!@objectstack/docs --dry=json`, with and without `--summarize
--log-file=.turbo/remote-cache/x.json`: 83 of 83 tasks, 0 differing
hashes (turbo 2.11.5).
- **`--log-file` must be repo-relative.** An absolute path outside the
repo prints `Structured log path '…' escapes the repository root, using
default location` and writes `.turbo/logs/EPOCH.json` instead. A
repo-relative path creates its directory.
- **The structured log is not valid JSON as a whole.** turbo 2.11.5
leaves some separating commas out, so it is read line by line.
- **The three states, from a real run** (turbo 2.11.5,
`--filter=@objectstack/formula`):
- no token: `Remote caching disabled (remote cache requested — set
TURBO_TOKEN and TURBO_TEAM, or run "turbo login" and "turbo link"),
using shared worktree cache`;
- token without team: `Remote caching disabled (TURBO_TOKEN set without
TURBO_TEAM)`;
- token and team, no route to Vercel: `Remote caching unavailable (Could
not connect to "https://vercel.com/api")`, at level `warn`.
- `enabled` cannot be produced from a seat container, which has no route
to Vercel. The prelude wording is read from the turbo binary's strings,
and the full set of `disabled` / `unavailable` reasons comes from the
same place.
- **Token withheld, writing run: the simulation.** This is the
acceptance's PR-side simulation. A real `turbo run build
--filter=@objectstack/formula --summarize
--log-file=.turbo/remote-cache/sim.json` was run with `TURBO_TOKEN=`
(what the carriers' expression yields with the signing key empty). The
script was then run on its log:
- `GITHUB_EVENT_NAME=merge_group`: exit **1**, with `::error title=Turbo
remote cache disabled (…)::Remote caching disabled (remote cache
requested — set TURBO_TOKEN and TURBO_TEAM, …) -- this run writes the
remote cache, so it must be on. …`;
- `GITHUB_EVENT_NAME=pull_request`: exit 0, with the same sentence as a
`::warning`;
- the summary was moved out of `.turbo/runs/` (now empty);
- `--if-ran` with no log: exit 0, "the build step ran no turbo".
- **Before (the card's item 3).** Merge-queue run 39939612132
(`830a63a`): Build Core `Build packages (excluding docs)` 4m21s,
`Cached: 38 cached, 76 total`. The six closure builds took 2m14s to
3m28s. The prelude line itself is outside the 5,000 lines a seat
container can read from that log, so whether the remote cache was on
before this change is read from **this PR's first run**: the new step
summary on Build Core and on each closure shard. The seat records that
reading on the card.
## Not changed, on purpose
- No new job, workflow or check context: every new step sits inside a
job that is already required (`check:required-contexts`).
- The `test` / `test:repo` / `typecheck` steps stay off the remote, as
Build Core's PINS require. The assertion steps run no turbo.
- Only the first build of each lint lane asserts: the lane's second
build carries the same four TURBO_* lines, so it would print the same
state.
## Deviations
- **One file beyond the dispatched surface, approved by the seat on
2026-10-23.** That file is `scripts/check-ci-filter-parity.mjs`; the
seat's conditions were the closed allowlist, cases both ways, and the
83/83 measurement stated here. On its own it reads NOT governed; this PR
is Tier H because of the two workflows.
## Acceptance notes
- Two more remote-cache carriers exist and are **not** asserted here,
because the card names five places. They are Temporal Conformance (four
build steps, ci.yml `temporal-conformance`) and the dogfood closure
build (ci.yml `dogfood`). Each needs the same two flags and one step.
Leaving them is a scope choice for the seat; the script needs no change
for them.
## Gates
At head `ef582fff` (this branch merged with `origin/main` `f0fdd45b`),
after a full `pnpm build`:
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives 71 commands for the 4 paths. All 71
ran and all 71 exited 0. `--ran` over the record: 71 derived, 71 run, 0
NOT-MEASURED.
- Of those, `node scripts/check-ci-filter-parity.mjs` and its
`--self-test` (140 assertions) were red in the first round, before the
gate change, and are green now.
- `node scripts/ci/assert-turbo-remote-cache.mjs --self-test`: 32 cases
across 6 batteries, OK.
- `eslint --no-inline-config` over both scripts: exit 0.
- `node scripts/pm/check-governed-merges.mjs --branch HEAD`: governed
(Tier H) through `.github/workflows/ci.yml` and `lint.yml`; the two
scripts are not on the register; 526 changed lines (+514 / −12).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QPa866zGYAuVVnv8kKLnKg)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01QPa866zGYAuVVnv8kKLnKg
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent e207b97 commit 842a0ae
4 files changed
Lines changed: 514 additions & 12 deletions
File tree
- .github/workflows
- scripts
- ci
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
| 278 | + | |
278 | 279 | | |
279 | 280 | | |
280 | 281 | | |
| |||
736 | 737 | | |
737 | 738 | | |
738 | 739 | | |
739 | | - | |
740 | | - | |
741 | | - | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
742 | 745 | | |
743 | 746 | | |
744 | 747 | | |
| |||
764 | 767 | | |
765 | 768 | | |
766 | 769 | | |
767 | | - | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
768 | 780 | | |
769 | 781 | | |
770 | 782 | | |
| |||
2544 | 2556 | | |
2545 | 2557 | | |
2546 | 2558 | | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
2547 | 2565 | | |
2548 | 2566 | | |
2549 | 2567 | | |
| |||
2579 | 2597 | | |
2580 | 2598 | | |
2581 | 2599 | | |
| 2600 | + | |
| 2601 | + | |
| 2602 | + | |
| 2603 | + | |
| 2604 | + | |
| 2605 | + | |
| 2606 | + | |
| 2607 | + | |
| 2608 | + | |
| 2609 | + | |
2582 | 2610 | | |
2583 | 2611 | | |
2584 | 2612 | | |
| |||
2608 | 2636 | | |
2609 | 2637 | | |
2610 | 2638 | | |
2611 | | - | |
| 2639 | + | |
| 2640 | + | |
| 2641 | + | |
| 2642 | + | |
2612 | 2643 | | |
2613 | 2644 | | |
2614 | 2645 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5785 | 5785 | | |
5786 | 5786 | | |
5787 | 5787 | | |
5788 | | - | |
| 5788 | + | |
| 5789 | + | |
| 5790 | + | |
| 5791 | + | |
| 5792 | + | |
| 5793 | + | |
| 5794 | + | |
| 5795 | + | |
5789 | 5796 | | |
5790 | 5797 | | |
5791 | 5798 | | |
| |||
6041 | 6048 | | |
6042 | 6049 | | |
6043 | 6050 | | |
6044 | | - | |
| 6051 | + | |
| 6052 | + | |
| 6053 | + | |
| 6054 | + | |
| 6055 | + | |
| 6056 | + | |
| 6057 | + | |
| 6058 | + | |
6045 | 6059 | | |
6046 | 6060 | | |
6047 | 6061 | | |
| |||
6242 | 6256 | | |
6243 | 6257 | | |
6244 | 6258 | | |
6245 | | - | |
| 6259 | + | |
| 6260 | + | |
| 6261 | + | |
| 6262 | + | |
| 6263 | + | |
| 6264 | + | |
| 6265 | + | |
| 6266 | + | |
6246 | 6267 | | |
6247 | 6268 | | |
6248 | 6269 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
161 | 161 | | |
162 | 162 | | |
163 | 163 | | |
164 | | - | |
| 164 | + | |
| 165 | + | |
165 | 166 | | |
166 | 167 | | |
167 | 168 | | |
| |||
276 | 277 | | |
277 | 278 | | |
278 | 279 | | |
279 | | - | |
| 280 | + | |
280 | 281 | | |
281 | 282 | | |
282 | 283 | | |
| |||
644 | 645 | | |
645 | 646 | | |
646 | 647 | | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
647 | 665 | | |
648 | 666 | | |
649 | 667 | | |
| |||
794 | 812 | | |
795 | 813 | | |
796 | 814 | | |
797 | | - | |
| 815 | + | |
798 | 816 | | |
799 | 817 | | |
800 | 818 | | |
| |||
1574 | 1592 | | |
1575 | 1593 | | |
1576 | 1594 | | |
1577 | | - | |
| 1595 | + | |
| 1596 | + | |
1578 | 1597 | | |
1579 | 1598 | | |
1580 | 1599 | | |
| |||
1653 | 1672 | | |
1654 | 1673 | | |
1655 | 1674 | | |
| 1675 | + | |
| 1676 | + | |
| 1677 | + | |
| 1678 | + | |
| 1679 | + | |
| 1680 | + | |
| 1681 | + | |
| 1682 | + | |
| 1683 | + | |
| 1684 | + | |
| 1685 | + | |
| 1686 | + | |
| 1687 | + | |
| 1688 | + | |
| 1689 | + | |
1656 | 1690 | | |
1657 | 1691 | | |
1658 | 1692 | | |
| |||
0 commit comments