Repository navigation
[Decision] CI and Lint run a full battery every hour (48 runs/day, about 2,800 job-minutes/day before any PR traffic): keep hourly, every 3 h, every 6 h, or run only when main moved since the last full run #22083
Description
Filing gate: ② a decision only the maintainer can make — the hourly full CI and Lint runs are a maintainer ruling (#16467, 2026-09-07), so changing their cadence is the maintainer's call. Filed by domain:skills seat 2 (seat post #19287, session_0181E4ZeZmWyknawnauxD2CE) on the maintainer's instruction after this seat's CI assessment, verbatim: 「CI 优化按照你的建议创建任务」. ⛔ Not a claim, ⛔ not a dispatch.
Reader: the maintainer (the needs-user-decision inbox); after the ruling, the domain:devx seat executes per 「裁后执行」 below.
Dedupe: page-looped REST listings, closed included (union 1,266) grepped for hourly|schedule|cron|full run|scheduled → 34 hits; the governing ones: #16467 (closed: push runs use the affected set; an hourly scheduled run keeps the full list and files a card on red — maintainer-directed), #16453 (the affected-set work it belongs to), #16464 / #22022 (the shard-timings refresh that reads the scheduled runs), and the 16 "hourly full run: red on main" cards since 2026-09-09 (#17059, #17687, #18161, #18594 …), every one closed. None re-measures the cadence's cost against its value, which is this card.
维护者速读
问题:CI 与 Lint 每小时各跑一次全量(0 * * * *),一天 48 次,约 2,800 job-分钟(≈47 个 runner-小时),与 PR 流量无关;它换来「main 红了一小时内有卡」(四周 16 张红卡,全部已关)和分片时长数据集每小时一个样本。本席在评估里把它列为可裁项,立卡前又量了两件事:过去 7 天 main 有提交的小时占 90%(152/168,662 次提交),所以「没改动就跳过」只能省约 10%;而且仓库是公开仓,ubuntu-latest 分钟不计费;实测代价只是 runner 池负载,而所有采样 job 的排队等待 ≤0.2 分钟。
推荐:A(保持每小时)。降频省下的是不计费的分钟,付出的是红 main 晚几小时被发现;真正该省的是每次全量跑的成本——那在 #22075(分片失衡)和 #22077(重复构建)里。等那两张落地后再量一次,届时若 runner 池出现排队再回到这张卡。
你要做的:回一个字母 A / B / C / D。选 A 本卡即关、cron 不动。
Governing text
- ci: push runs on main use the affected set; an hourly scheduled run keeps the full list and files a card on red (maintainer-directed) #16467, the ruling (maintainer verbatim, 2026-09-07): 「同意你的建议,你负责执行派发所有可行的优化」; items 2–3: 「
schedule: '0 * * * *'andworkflow_dispatchtrigger the same workflow with the full list … On a red scheduled run, one card (fixed title prefix, deduplicated)」. .github/workflows/ci.yml:50-58: the schedule's rationale — "scripts/ci/select-shard-timings-run.mjswants one complete run per hour far more than it wants a short queue wait, and a run that starts a few minutes late is still the hour's run" — the hourly run also feeds the shard-timings dataset refresh (ci: a scheduled workflow regenerates scripts/test-shard-timings.json from the newest fully green main run and opens the PR (maintainer-directed, measurement loop) #16464, fix(ci): accumulate shard-timings runs until every package has three executions, provisional below that #22022: collect until every package has three measurements)..github/workflows/lint.yml:40-47: the same trigger; "the selector already treats every event that is neithermerge_groupnorpull_requestas run every family".scripts/ci/select-gate-families.sh:27-28: "pushon main and the scheduled full run keep the whole battery, by design".- Protocol statement: B, C and D change the ruling's cadence or its trigger condition; A changes nothing.
前提(每条带 re-check 命令)
- Both workflows run the full battery hourly. —
grep -n "cron: '0 \* \* \* \*'" .github/workflows/ci.yml .github/workflows/lint.yml→ 2 lines. - Cost: scheduled CI runs used 36–147 job-minutes (4 samples), scheduled Lint runs 33–46; 24 × (77 + 41) ≈ 2,800 job-minutes a day; the repository is public, so
ubuntu-latestminutes are not billed; the measured cost is runner-pool load, and runner wait was ≤0.2 min in every sampled job. — jobs API over the 100 most recent completed runs of each workflow (the seat's CI research, raw files kept);gh api repos/objectstack-ai/objectstack --jq .private→ false. - Activity: over the last 7 days
mainreceived commits in 152 of 168 hours (90%), 662 commits; only the other 16 hours' full runs re-tested an unchanged tree. —git log origin/main --since=7.days --format=%cd --date=format:%Y-%m-%dT%H | sort -u | wc -l - Value: 16 "hourly full run: red on main" cards since 2026-09-09, all closed; detection latency of a red
mainis at most one hour. — REST listing grephourly full run: red on main. - The shard-timings refresh (fix(ci): accumulate shard-timings runs until every package has three executions, provisional below that #22022) accumulates scheduled runs until every package has three measurements; fewer scheduled runs mean a slower refresh. —
grep -n -i "three\|3 measurements\|accumulate" .github/workflows/shard-timings-refresh.yml
一句话问题
每小时把整棵树测一遍的固定开销,值不值得用「红 main 晚几小时被发现」去换。
选项 × 真实代价
| 选项 | 做什么 | 车队可感知后果 |
|---|---|---|
| A | 保持每小时 | 现状:≈2,800 job-分钟/天(不计费);红 main 一小时内有卡;数据集每小时一个样本 |
| B | 每 3 小时 | 跑次降约 67%;红 main 最多 3 小时才有卡;数据集样本慢 3 倍 |
| C | 每 6 小时 | 跑次降约 83%;红 main 最多 6 小时才有卡;数据集样本慢 6 倍 |
| D | cron 不变;首步读上次全量跑的 main sha,main 没动就提前退出 |
过去 7 天只有 16/168 小时能省(≈10%);多一个早退步骤和一个 sha 读数源 |
业务含义直译
A = 「不管有没有改动,每小时体检一次」;B / C = 「体检改成每 3 / 6 小时,出事晚知道几小时」;D = 「没改动不体检——但这里几乎每小时都有改动」。
四轴论证(从业务立场)
- 实际业务需求:实测开销 ≈47 runner-小时/天,但仓库是公开仓,
ubuntu-latest分钟不计费;实测代价只是 runner 池负载,而所有采样 job 的排队等待 ≤0.2 分钟;实测价值 = 16 张红卡的一小时内早发现 + 数据集的每小时样本。零拉动的一侧是「省钱」,有拉动的一侧是「早发现」。零拉动 ⇒ 默认不动。 - 项目长远合理性:全量跑的单次成本才是结构性问题(一个分片 36 分钟、三处重复构建),ci(test-shards): the shard balance is derived on full-run sums while PR and merge_group runs use the affected set — the CLI shard (1/6) measures 34–36 min against 10–20 for the others and sets CI and queue wall time #22075 与 ci: Lint's three Type Check jobs, the Test Core shards, dogfood and Temporal each rebuild the workspace (3.5–5.8 min per job, ~25–30 job-min per CI+Lint pair) — extend #21186's turbo remote cache to them #22077 正在修;修完后每次全量跑便宜一半以上,降频的意义进一步缩小。先修单价再谈频率。
- 防 AI 犯错:红 main 发现得越晚,叠在坏基线上的 PR 越多;B / C 把一小时拉成三到六小时,正好在最活跃的时段(90% 的小时有提交)损失最大。
- 创业阶段不扩散:A 零改动;D 加一个早退机制换 10%;B / C 改两行 cron 但改的是一条上月刚立的裁决。
推荐 + 回退 + 置信缺口
推荐 A(保持每小时;在 #22075 / #22077 落地后再量一次)。回退 B(若 runner 池开始出现排队等待,每 3 小时是最小的有效降幅)。置信缺口:活动样本只有 7 天;runner 池负载只看了采样 job 的等待时间;数据集刷新对样本频率的真实需求未测(#22022 的 3 次/包是下限)。
自检行:只看①选 A;②③④ 是否翻转:否。
终态句:两年后每次全量跑的成本由分片与缓存决定,频率跟着「红 main 可容忍的发现时延」走,而不是跟着分钟数走。
os-decision-facets
① 项目长远合理性:单次成本是结构问题(#22075 / #22077),频率不是;A 不动裁决。
② 实际业务拉动:公开仓分钟不计费、runner 不排队;早发现有 16 张卡的实测价值。
③ 防 AI 犯错:降频在最活跃时段最先损失红 main 的发现时延。
④ 创业阶段不扩散:A 零改动;D 新机制换 10%;B / C 改上月的裁决。
Prior rulings read: schedule,hourly,cron,full,scheduled,ci,runner → 60 ADR / 27 AGENTS.md / 484 spec term hits, 10 ADR candidates, none on CI cadence; ADR none; thread: #16467, #16453, #22022
推荐 A;选项 A / B / C / D;自检「只看①选 A;②③④ 是否翻转:否」。置信缺口:7 天活动样本;runner 池负载只看了等待时间;数据集节奏需求未测。
裁后执行
- A:本卡以
completed关闭;cron 不动;ci(test-shards): the shard balance is derived on full-run sums while PR and merge_group runs use the affected set — the CLI shard (1/6) measures 34–36 min against 10–20 for the others and sets CI and queue wall time #22075 / ci: Lint's three Type Check jobs, the Test Core shards, dogfood and Temporal each rebuild the workspace (3.5–5.8 min per job, ~25–30 job-min per CI+Lint pair) — extend #21186's turbo remote cache to them #22077 落地后本席或 devx 席重量一次并在本卡留一行读数。 - B / C:一张
domain:devx卡改ci.yml与lint.yml的两行 cron,并在 ci: push runs on main use the affected set; an hourly scheduled run keeps the full list and files a card on red (maintainer-directed) #16467 的规则文本与select-shard-timings-run.mjs的注释里改节奏说明;红卡的「自上次绿色全量跑以来的合并」窗口随之变长。 - D:一张
domain:devx卡在两个 workflow 的schedule路径上加首步:读上次成功全量跑的mainsha(jobs API 或缓存键),等于当前HEAD则输出「unchanged since the last full run」并让后续 job 以if:跳过;workflow_dispatch不受影响。
Related: #16467 · #16453 · #16464 · #22022 · #22075 · #22077 · ci.yml:50-58 · lint.yml:40-47.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 7, 2026
Box intake (triage):
domain:devx·priority:p3added. The card's shape is complete: 维护者速读, the option table, the four axes,Prior rulings read:and 裁后执行 are all present. It changes the cadence of a maintainer-ruled schedule (#16467), so it is the maintainer's. p3: today's hourly cadence works, and the card itself recommends A (keep it). Nothing else changes; the card waits in the box for the director.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T16:16Z. ⛔ Not a claim.objectstack-fleet commentedon Oct 8, 2026
Ruling: batch #287 item 1 · letter A · maintainer 「批 #287 同意」 2026-10-08T02:19Z
Director seat, summon #35,
session_01VYToj6PQehTEKNrjGM9akg(GitHubos-zhuang; written asobjectstack-fleet[bot]via the relay). Batch #287 was presented in chat twice, the second time in the detailed form the maintainer asked for, with this card's options A / B / C / D; the maintainer answered 「批 #287 同意」, which takes A. Freshness gate: the body and the one comment (6041983946, triage's intake) were re-read before this record; nothing newer exists. Thread-read: 6041983946.The ruling
A. The hourly full CI and Lint runs stay as #16467 ruled them (
cron: '0 * * * *'inci.yml:58andlint.yml:47). The cost side measured zero where it is paid: the repository is public, soubuntu-latestminutes are not billed, and runner wait was at or under 0.2 minutes in every sampled job; the value side measured sixteen "hourly full run: red on main" cards in four weeks (all closed) and the shard-timings dataset thatselect-shard-timings-run.mjswants fed once an hour (#22022 now accumulates until every package has three measurements). ⛔ Not taken: B and C (a 3- or 6-hour cadence trades unbilled minutes for a 3- to 6-hour red-main detection delay in the hours when 90% of them carry commits, and slows the dataset refresh by the same factor) and D (an early-exit step that saves about 10% of runs for a new sha-reading mechanism).What would reopen this: the repository turning private (minutes billed) or a move to self-hosted runners (a smaller pool). The per-run cost is the structural lever and is being worked elsewhere (#22077 landed; #22075 open): after #22075 lands, the
domain:devxseat re-measures once and leaves one line of readings here.State
completedin this act; the crons are not touched;tooling·domain:devx·priority:p3unchanged.Generated by Claude Code