Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

ci(test): widen the test matrix from 12 to 16 legs, and move every pin of the width (objectui#12384) - #12399

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-12384-test-shard-cancellations
Oct 15, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-12384-test-shard-cancellations

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12384

What this does

It widens ci.yml's test matrix from 12 to 16 legs and moves every pin of the width in the same diff. This is route A of the reading 6181333653, which the seat accepted in claim 6181366176.

What stays: ⛔ timeout-minutes: 20 is not raised, ⛔ testTimeout is not raised, ⛔ no test is skipped or quarantined, ⛔ the relevance gate is not widened, ⛔ the coverage matrix (8 legs, 40-minute cap) is not touched, and ⛔ no runner is pinned.

It applies ruling 6121816480's own width rule: "the width derived from the total measured duration at a target of about 10 minutes per shard". Triage 6177117080 says: "A lighter shard plan, or a runner pin, changes no limit and needs no ruling."

Pins moved

Derived with git grep for /12, twelve, --shards 12, shard N/12, of 12 and 12-runner, then read hit by hit.

  • .github/workflows/ci.yml:
    • the shard: list (1 to 16);
    • the job name Test (shard N/16);
    • the step name Run tests (shard N/16) and its echo line;
    • both --shard=N/16 invocations;
    • test-aggregate's check-test-shard-results.mjs --shards 16;
    • shard-headroom.mjs --job 'Test (shard {n}/16)' --shards 16;
    • the full-battery echo line;
    • the comments: a new "12 -> 16" paragraph beside the "4 -> 8" and "8 -> 12" ones, and the stale "8 runners" in the job's first paragraph, now width-neutral.
  • .github/workflows/test-shard-timings-refresh.yml: test-file-timings.mjs select --shards 16, its NOT MEASURED warning text, and the header. The header also gains one paragraph on what a width move does to the selection (A3 below).
  • .github/workflows/lint.yml: the one comment that names the legs.
  • scripts/dependabot-merge-gate.mjs: the NOT_A_GATE rows, Test (shard 1/16) through Test (shard 16/16), and the comments and strings that name the PR lane.
  • Usage headers: check-test-shard-results.mjs, shard-headroom.mjs, test-file-timings.mjs and select-affected-tests.mjs.
  • Tests:
    • cases in dependabot-merge-gate.test.ts, select-affected-tests.test.ts and shard-headroom.test.ts;
    • comments in check-eager-closure-budget.test.ts, check-skill-examples.test.ts and check-test-path-roots.test.ts.
  • content/docs/guide/ci-cd-pipeline.md:
    • the job-table row, whose "Appears as" ci-cd-pipeline-doc.test.ts matches against ci.yml's name:;
    • a 12 -> 16 history sentence;
    • the sentences that state the shard count in the aggregator, refresh and Dependabot sections.
    • ⛔ The OBJECTUI_ALLOW_MAJOR sentences that objectui#12334 edits are not touched.
  • AGENTS.md: the --shard=1/16 example, and the sentence two lines below it that names the example's number. Nothing else in that paragraph changes.

One new pin, in the same family. test-file-timings.test.ts now holds the weekly refresh's select --shards to the test matrix width, the way check-test-shard-results.test.ts already holds test-aggregate's --shards.

  • Without it, a refresh left on an old width selects no run. It prints NOT MEASURED and stays green, and the timings dataset quietly stops refreshing.
  • No test held this width pin before. The ablation is under Verification.

Left on purpose:

  • history: "objectui#12208 to 12" and "Balanced, the twelve legs ...";
  • test-file-timings.test.ts's writer case, which turns shard: { index: 3, count: 12 } into '3/12': an arbitrary reporter input and output, not a pin of the matrix;
  • flowLaunch.translation-12075.test.tsx's "red in CI's shard 4/12": a dated measurement.

A2: the required-check set names the aggregate, not the legs

  • Command: node scripts/check-required-check-set.mjs --fixture FILE. FILE is a gh api repos/objectstack-ai/objectui/rules/branches/main response read on 2026-10-15. The script's own live fetch answered HTTP 401 in this container (exit 2, "could not take a reading").
  • Result: exit 0, "✅ INTACT — 1 pinned and 6 watched context(s) all present (7 required context(s) read)".
  • The 7 contexts: Lint, Type Check, Build & E2E, Build Docs, Changeset Declaration, Test, Governed Surface Queue Guard.

No Test (shard N/W) leg is required, so the width is a workflow edit, not a ruleset change.

A3: the timings refresh across the width change

scripts/test-shard-timings.json is keyed per file and records no width, and the sequencer reads it per file, so it needs no change. The refresh's selector judges a run by the leg names of one width: judgeRun looks up Test (shard n/M) for each n.

Measured on 2026-10-15 by running selectRuns() unchanged against main's live runs, with its reads routed through gh api:

  • --shards 16: it examined 30 push and schedule runs, its cap (limit × 5). It skipped every one ("Test (shard 1/16) is not in the run") and took 0. That is the CLI's NOT MEASURED, exit 3.
  • Control, --shards 12: it took 6 of the first 6 runs examined.

After landing:

  • The old 12-leg runs are skipped by name and are never mixed in.
  • The first green 16-leg full battery is the first run taken: the merge's own push run, then the hourly schedule.
  • The refresh runs on Mondays at 06:47 UTC. If it fires before such a run exists, it prints the NOT MEASURED warning, exits green and leaves test-shard-timings.json untouched. It does not fail, and the next week's run takes the 16-leg runs. Only a landing in the hour or so before that slot hits this.
  • This PR's own pull_request leg of the refresh workflow runs the same selection at 16 and should read NOT MEASURED.

A4: the per-leg estimate

These figures come from the reading's numbers. Actions history was not re-measured.

Each leg carries 12/16 = 0.75 of today's load. The reading's 12-leg figures, over 50 hours of finished PR and queue legs:

  • median 11.3 min and p99 12.6 min;
  • the full-battery maximum is 13.6 min;
  • normal setup takes about 35 s;
  • the reading's upper bound for a fixed per-leg vitest start cost is 1.2 min.
12 legs (measured) 16 legs, all cost scales 16 legs, 1.8 min fixed per leg
median leg 11.3 min 8.5 min 8.9 min
p99 leg 12.6 min 9.45 min 9.9 min
full-battery longest leg 13.6 min 10.2 min 10.65 min
break-even slow factor, p99 leg (20 min / p99) 1.59x 2.12x 2.02x

The last column is 1.8 + 0.75 × (leg − 1.8).

  • Headroom. Slow VMs measured 1.6x to 2.0x against normal controls. The p99 margin stays thin, at about 2.0x to 2.1x, as the reading said. The median leg gets about 2.25x to 2.35x.
  • The nine legs named on the card. Their projected Run tests of 1,168 to 1,383 s at 12 legs becomes 876 to 1,037 s at 16. With their own slow setup (47 to 68 s) that is 15.6 to 18.3 min, all under 20.
  • Cost. Four more legs at their fixed cost of 0.6 to 1.2 min each come to about +2.5 to +5 runner-min per run. That is +2% to 4% of about 136 runner-min, or about +330 to +650 runner-min a day at about 134 runs a day. Standard hosted runners on this public repository are not billed.
  • The ruling's acceptance. It reads "ten consecutive full-suite runs with the longest shard under 60 % of the cap", which is 12 min.
    • The projected longest leg on a normal VM is 10.2 to 10.65 min, under 12.
    • A VM slower than about 1.15x still crosses 12.
    • NOT MEASURED until it runs: test-aggregate's headroom step reads it on every run.

Verification (head 0f5a949e4)

Tests. I ran them from the repository root, under the shared verify lock.

  • Command: pnpm exec vitest run --maxWorkers=2 scripts/__tests__/.
  • Result: Test Files 187 passed | 2 skipped (189), Tests 5633 passed | 2 skipped (5635), lock VERDICT command-exit 0.
  • This covers every pin touched here: check-test-shard-results, shard-headroom, select-affected-tests, dependabot-merge-gate, test-file-timings and ci-cd-pipeline-doc. It also covers the other workflow-reading suites under scripts/__tests__.
  • None of the touched files carries a skip.

Ablation of the new refresh pin. I used ablation-replace in wrap mode, under the lock, against the commit above.

  • Mutation: select --shards 16 --limit 6 became select --shards 12 --limit 6 in the refresh workflow. The anchor count went 1 → 0, the replacement count 0 → 1, and the blob 7198fa4f893c became 9bdb34cea68c.
  • Result: 1 failed and 14 passed, and the failure was the new case: "the refresh's --shards and ci.yml's test matrix have drifted apart: expected 12 to be 16".
  • Restore: the blob after restore equals HEAD's (7198fa4f893c) and git diff HEAD is empty. The green leg is the full run above.

check-test-shard-results.mjs --fixture:

run exit reads
--shards 8 on the recorded 8-leg fixture run-36042402511-attempt-1.json 0 "all 8 shards reported success"
--shards 16 on that 8-leg fixture 3 every Test (shard n/16) ABSENT
--shards 16 on a 16-leg job list synthesized from that fixture (not committed) 0 "all 16 shards reported success"
--shards 12 on the synthesized list 3 every Test (shard n/12) ABSENT

Gates that read these paths, derived by hand from lint.yml, repo-gates.yml, line-citation-gate.yml and changeset-presence.yml. The objectstack dispatch-gates tool does not serve this repository. Each exit code was captured before any pipe.

gate exit
node scripts/check-control-bytes.mjs 0
node scripts/check-action-ref-convention.mjs 0
node scripts/check-doc-links.mjs 0
node scripts/check-shell-escape-residue.mjs 0
node scripts/check-doc-fence-languages.mjs --self-test 0
node scripts/check-doc-fence-languages.mjs 0
pnpm check:new-line-citations ("0 new citation(s)") 0
node scripts/check-changeset-presence.mjs ("no changeset is owed") 0
node scripts/check-test-path-roots.mjs 0
node scripts/check-lint-coverage.mjs 0
pnpm check:governed-queue-guard 0
pnpm check:required-check-set 0

The repository has no actionlint or other workflow linter, so the workflow-shape readings are the scripts/__tests__ suites above. Repo-wide pnpm lint and the full test farm are CI's; this PR's own CI is the first 16-leg run.

Governed surface. node scripts/check-governed-queue-guard.mjs --test on the 17 changed paths exits 3:

⛔ GOVERNED — 4 of 17 path(s) are on a governed surface:
   AGENTS.md x1 — the repo-root agent instruction file
   .github/workflows/** x3 — CI, deploy and release workflows: what runs on every push, what deploys, what gates the queue
     - .github/workflows/ci.yml
     - .github/workflows/lint.yml
     - .github/workflows/test-shard-timings-refresh.yml

So this PR stays draft until an APPROVED review from a GOVERNED_APPROVERS account. The claim also owes a CONTRACT_REVIEW_TIER review.

Acceptance notes

  • Changeset. None is owed. check-changeset-presence reads 0 published source and 0 published contract changed, and CI config and repository scripts publish nothing.
  • A stale comment, left alone. ci-cd-pipeline-doc.test.ts has a comment that still gives the matrix job's name with /4, stale since 4 -> 8. It is a comment that nothing reads, outside this card's surface. Carrier: none, so it is noted here only.
  • A stale phrase, made width-neutral in place. The header of select-affected-tests.mjs said "the four-shard coverage lane", stale since objectui#12256. It sat in the same sentence this diff edits, so it now reads "the sharded coverage lane". It is a comment only, and the coverage matrix itself is unchanged.
  • What holds each width pin now:
    • --shards in test-aggregate: check-test-shard-results.test.ts;
    • --shards in shard-headroom: shard-headroom.test.ts;
    • --shards in the refresh: test-file-timings.test.ts, new;
    • the NOT_A_GATE rows: the partition test in dependabot-merge-gate.test.ts;
    • the job and step names: select-affected-tests.test.ts and test-file-timings.test.ts;
    • the doc row: ci-cd-pipeline-doc.test.ts.
  • The reading's out-of-scope finding stays on this card, its family carrier. Two export-to-react-compiles tests ran 17.3 s and 17.6 s against testTimeout: 15000 on a slow VM. This PR does nothing about them, and testTimeout is unchanged.

维护者速读(草稿)

改了什么

  • CI 的测试分片从 12 条腿加到 16 条,每条腿的负载降到原来的四分之三。
  • 20 分钟超时上限不动,不跳过任何测试,不动覆盖率分片,也不锁定 runner。
  • 所有写死 12 的地方一并改成 16:工作流、Dependabot 合并门、每周计时刷新、文档,以及 AGENTS.md 里的示例。
  • 另加一条测试:以后再改宽度时,如果漏改了计时刷新,本地测试会直接变红。

为什么改

  • 2026-10-14 有 16 条测试腿在 20 分钟上限被取消,全都没有挂死。
  • 原因是部分虚拟机整体变慢,同样的文件要多花 1.6 到 2.0 倍的时间。
  • 后果:测试全过的 PR 显示红色,要手动重跑;合并队列里的 PR 被踢出,后面排队的都要多等一轮。
  • 12 条腿时,p99 腿只有约 1.59 倍余量,低于慢机器的系数;16 条腿约 2.0 到 2.1 倍。
  • 这是执行既有裁决的宽度规则(每条腿约 10 分钟),不是新决定。

风险与代价(含回滚)

  • 每次运行约多 2.5 到 5 个 runner 分钟(+2% 到 4%)。本仓是公开仓,标准 runner 不计费。
  • p99 余量仍然偏薄:约 2.0 到 2.1 倍,而实测最慢约 2.0 倍。
  • 测试套件继续增长会再吃掉余量。现有的只读 headroom 报告步骤每次运行都会显示,不新增门禁。
  • 落地后第一次每周计时刷新,如果早于第一次 16 腿全绿运行触发,会报 NOT MEASURED 并保留原文件,不会变红。
  • 回滚:revert 本 PR 即回到 12 条腿。没有数据迁移,也没有仓库设置改动,因为必需检查只认 Test 聚合。

席位意见

(留空)

你要做的

  • 审阅后,在本 PR 上留下一条 APPROVED review。本 PR 改动了 .github/workflows/** 与 AGENTS.md,属于受管面。
  • 之后由认领席翻 ready、挂入合并队列。

This change was implemented by the dispatched dev of the domain:ui seat 1 PM, session https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDB.


Generated by Claude Code

…n of the width (objectui#12384)

Slow-VM episodes (every file 1.6x to 2.0x slower, per VM, no hang) pushed
balanced 12-way legs past the 20-minute job cap. Sixteen legs carry 0.75 of
the load each, which moves the break-even slow factor for a p99 leg from
about 1.59x to about 2.1x. The cap, testTimeout and the coverage matrix are
unchanged.

Pins moved: ci.yml (matrix, job and step names, both --shard=N/W
invocations, test-aggregate's --shards, shard-headroom's --job and --shards,
comments), the weekly timings refresh's select --shards, lint.yml's comment,
dependabot-merge-gate.mjs's per-leg NOT_A_GATE rows, the script usage
headers, the scripts/__tests__ cases and comments, ci-cd-pipeline.md and the
AGENTS.md example. New pin: test-file-timings.test.ts holds the refresh's
--shards to ci.yml's test matrix, so a future widening cannot leave the
refresh silently selecting nothing.

Claude-Session: https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDB
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0f5a949e4a28bc2846109484958153673b994a48
Local-runs: none

The face is governed rules text: .github/workflows/ci.yml, .github/workflows/lint.yml, .github/workflows/test-shard-timings-refresh.yml and AGENTS.md sit on objectui's governed surface (the PR body's own check-governed-queue-guard --test reading, 4 of 17 paths). Read for this record: card objectui#12384 (body and all seven comments: the triage direction 6177117080, both claims 6181038298 and 6181366176, the reading 6181333653, the BUILD report 6181669972), ruling 6121816480 on objectui#12208, PR #12399's body, file list and net diff against main (17 files, +107/−62), the 35 check-runs on the head, the Test aggregate's and the timings refresh leg's job logs on that head, the live main ruleset, and the tree at the head for a leftover-pin sweep. Nothing was built, run or re-run.

① Derived judgments

Every accept-set and surface change the diff implies, each named.

  1. The test matrix 12 → 16 (the shard: list, the job name Test (shard N/16), the step name, both echo lines, both --shard=N/16 invocations) — right. The head's Test aggregate log reads "expecting 16 test shard(s)", lists Test (shard 1/16) through Test (shard 16/16) all success, and ends "all 16 shards reported success".
  2. The ceiling — unchanged, right. timeout-minutes: 20 still sits on the test job at the head and no hunk touches it. The three recorded refusals (ceiling, skip or quarantine, relevance widening) are restated in the new 12 → 16 comment paragraph and held by the diff: no skip, no only, no quarantine, fail-fast: false unchanged, no exclusion-list or paths line changed, select-affected-tests.mjs logic untouched (its header comment only).
  3. No runner pin — right. runs-on: ubuntu-latest on the test job is unchanged; the reading found no runner class to pin and the diff pins none.
  4. The coverage matrix — untouched, right. No test-coverage or coverage-report hunk; its 8 legs and 40-minute cap stand. The two comment edits that touch the word coverage ("four-shard coverage lane" → "the sharded coverage lane"; "8 runners" → "the runners of the shard: matrix below") are width-neutral prose, not a lane change.
  5. The required check set — unaffected, right. The live ruleset on main (id 11776024, strict) names Lint, Type Check, Build & E2E, Build Docs, Changeset Declaration, Test and Governed Surface Queue Guard: the aggregate, no leg. So the width is a workflow edit and no repository setting moves; this matches the PR body's A2 fixture reading. Test reported success on the head.
  6. The four pins the brief names, each moved in the diff and each proven on the head:
    • the aggregate's check-test-shard-results.mjs --shards 16 — right (the log above);
    • the headroom reading shard-headroom.mjs --job 'Test (shard {n}/16)' --shards 16 --cap-minutes 20 --target-minutes 10 — right; it ran report-only on the head and printed "longest Test (shard 2/16): 9m52s = 49% of the 20-minute cap, 10m08s of headroom; total 134m42s over 16 shard(s); at the 10-minute target per shard that is 14 shard(s) (the matrix has 16)";
    • the timings refresh selector test-file-timings.mjs select --shards 16 --limit 6 and its NOT MEASURED warning text — right; the refresh's own PR leg on the head examined 30 push and schedule runs, skipped each with "Test (shard 1/16) is not in the run", printed NOT MEASURED and exited green with the dataset untouched, which is the A3 prediction to the letter;
    • the Dependabot gate's NOT_A_GATE rows Test (shard 1/16) through Test (shard 16/16) — right; the partition test is two-sided (an unclassified produced name and an unproduced listed name both fail it) and it passed inside the 16 legs on the head. The unchanged PR_TEST_SHARD_NOT_A_GATE string names no width.
  7. The width itself, 16, against the ruling's rule ("the width derived from the total measured duration at a target of about 10 minutes per shard") — right, with one reading the approver should see. The card's measurement derives 13 (full-battery median), 15 (full-battery maximum) and 16 (PR and queue runs); the PR takes the top of that band. On this head's own full run the ruling's instrument reads 14 at the 10-minute target with the matrix at 16, about 8.4 min per leg: inside "about 10", on the side that buys slack against the measured 1.6x to 2.0x slow-VM factor, and the longest leg here (9m52s) sits under the ruling's acceptance line of 60 % of the cap (12 min). Triage 6177117080 admits "a lighter shard plan" with no ruling, so no ruling is owed for the number. Whether 16 still fits is the headroom reading on every run, as the new comment says.
  8. The new pin in scripts/__tests__/test-file-timings.test.ts — right. It reads width off ci.yml's test strategy.matrix.shard length (the derivation check-test-shard-results.test.ts and shard-headroom.test.ts already use), requires exactly one select --shards in the refresh and holds it to that width: one-sided to the matrix, no second constant to rot. It closes the silent failure the refresh leg's log demonstrates (a stale width selects nothing, warns and stays green). The PR body's ablation shows it red on the mutated refresh and green on restore.
  9. Rules text. AGENTS.md: the --shard=1/16 example and the one sentence that names the example's number; the paragraph still says the file does not re-verify that number (诫条 完善设计器的每一个细节 #9) — right, nothing else in it moves. lint.yml: the single comment that names the legs — right. content/docs/guide/ci-cd-pipeline.md: the job-table row (its "Appears as" is held to ci.yml's name: by ci-cd-pipeline-doc.test.ts, green on the head), one history sentence, and the aggregator, refresh and Dependabot sentences — right; the OBJECTUI_ALLOW_MAJOR sentences objectui#12334 edits are not touched.
  10. Left-behind pins — none found. A sweep of the tree at the head (all 29 workflow files; every shard, timing, affected-test, dependabot and required-check script and test under scripts/; the vitest configs and setup files; the pipeline guide) for N/12, --shards 12, 12-runner and "twelve shards/legs" finds only: history lines in ci.yml and the guide ("objectui#12208 to 12", "8 → 12 shards in [Decision] CI 的 Test (shard 1/8) 又逼近 20 分钟上限,并已超时取消一次:分片怎么改才不再复发 #12208", "the twelve legs were no longer heavy"); the refresh header's contrast example (Test (shard 1/12) is not Test (shard 1/16)), which is the point of that sentence; the reporter writer case shard: '3/12' in test-file-timings.test.ts, an arbitrary input and its output, not a pin; and unrelated counts (cron hours, "1/12 of the self-heal", "repaired twelve times"). Right to leave each.
  11. Cosmetic, no reader, noted only: the re-wrapped ci.yml paragraph leaves "a PR run reported 495s wall" on a line of its own before "clock of which"; the ci-cd-pipeline-doc.test.ts comment that still spells the matrix job with /4 (the dev's own out-of-scope note); the pre-existing "coverage lane, sharded 4 ways" comment above test-coverage in ci.yml, stale since objectui#12256 and outside this card's family. None is a pin and none changes an accept set.

Check-runs on the head: 35, none failed. The 16 Test (shard N/16) legs success (5m24s to 9m52s), Test success, and Test (dist pins), Lint, Type Check, Build & E2E, Build Docs, Repo Gates, Changeset Declaration, Changeset Claim Re-read, Changeset Fixed Group Check, Governed Surface Queue Guard, Line Citation Gate, Spec Main Shape Gate, Live E2E (informational), label and Regenerate the per-file test timings all success; Test (coverage), the coverage legs and dependabot skipped by design on a pull request. Those conclusions are the gate verdicts; this record re-ran none.

② Semver level

No published surface moves: the 17 files are workflows, AGENTS.md, the pipeline guide, repository scripts and their tests under scripts/; nothing under packages/**, no schema, no export, no contract. No changeset is owed and none is added: Changeset Declaration and Changeset Claim Re-read are green on the head, and check-changeset-presence read "no changeset is owed" in the PR body. Clause-②: no on both claims matches what the diff publishes, which is nothing. Right.

③ Boundary flags

From the BUILD report 6181669972, each answered.

  • Deviation 1 (comment edits beyond the A1 list: check-skill-examples.test.ts, ci.yml's "8 runners", select-affected-tests.mjs's "four-shard coverage lane") — accepted: inside the claim's file surface, comments only, the coverage matrix untouched.
  • Deviation 2 (scripts/__tests__/test-file-timings.test.ts gained one case, outside the claim's stated file surface) — accepted as a bounded in-place change: the same width-pin family, a mirror of the existing aggregate pin, one-sided to the matrix, no other claim on the file, ablation shown. Action for the seat, not a condition of this record: amend the claim's file surface on objectui#12384 to name the file, as the dev asked.
  • Deviation 3 (check-required-check-set.mjs live mode answered 401; A2 read via --fixture) — answered here from the live ruleset: the same seven contexts, no leg. Nothing further owed.
  • Deviation 4 (A3 measured by an uncommitted harness) — answered by the head itself: the refresh's PR leg reproduced the selection at 16 (0 of 30 runs taken, NOT MEASURED, green).
  • Deviation 5 (tests run over the whole scripts/__tests__/ directory) — a superset of the named files; fine.
  • Deviation 6 (commit trailers follow objectui AGENTS.md's model-free pair) — the head commit ends with the Claude-Session and Co-authored-by pair that AGENTS.md records for this repository under objectui#9441; consistent, no conflict left open.
  • open_questions: none declared, none found.
  • Out-of-scope finding 1 (two export-to-react-compiles tests at 17.3 s and 17.6 s against testTimeout: 15000 on a slow VM, and two check-object-metadata-write-doors tests near the budget) — correctly left out of this diff (testTimeout unchanged) and correctly carried on objectui#12384 as the family carrier. Escalated to the seat: when the card closes on this PR, that residual needs its own card or a named carrier, or it falls out of the ledger.
  • Out-of-scope finding 2 (the /4 comment in ci-cd-pipeline-doc.test.ts) — comment only, nothing reads it; noted, no carrier owed.
  • After landing, for the seat (not a review condition): the first weekly refresh takes the first green 16-leg full battery; a NOT MEASURED that persists past the second week is the finding the refresh header names. The ruling's acceptance (ten consecutive full-suite runs with the longest shard under 12 min) is read by the headroom step on every push and schedule run; the card should record it once met.

Implemented-by: claude/issue-12384-test-shard-cancellations
Reviewed-by: session_01JZnppgHRp4sREcouhkQYDB

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读 · objectui PR #12399(objectui#12384)· domain:ui 席 1 · 2026-10-15T01:08Z

改了什么:CI 的测试矩阵从 12 腿加到 16 腿,每腿 20 分钟上限不变。所有写死宽度的地方一起改,包括:

  • 聚合检查的腿数、余量读数、每周耗时数据刷新的选择条件;
  • Dependabot 合并门的逐腿名单;
  • 指南文档和 AGENTS.md 的示例。

另加一条钉子测试:耗时刷新的选择宽度一旦和矩阵脱节,测试就转红,不会再静默选不到任何运行。

为什么改:10-14 当天有 16 个测试腿在 20 分钟上限处被取消,其中 13 个集中在一个下午。实测这些腿都落在慢机器上,每个文件都慢 1.6–2.0 倍,没有挂起,也没有哪个文件特别重。

  • 后果:测试其实全过的 PR 被读成红,合并队列反复踢出 PR,每次都要人工重跑。
  • 12 腿时,p99 腿对上限只剩 1.59 倍余量,低于慢机器的倍率;16 腿后约为 2.1 倍。

风险与代价(含回滚):

  • 跑道分钟数约 +2–4%。上限不提高,真挂起照样在 20 分钟被截断。
  • 不跳过、不隔离任何测试,也不固定机器型号(实测没有可区分的机型)。
  • 首个 16 腿运行实测各腿 5m24s–9m52s,最长腿占上限的 49%。
  • 每周耗时数据刷新在第一个 16 腿全量绿跑出现前读作 NOT MEASURED,保留现有数据,不会出错。
  • 回滚:revert 本 PR。

席位意见:建议批准。

  • 这是执行既有裁决 6121816480(objectui#12208)的宽度规则(每腿约 10 分钟);分诊方向也明说「更轻的分片方案不需要裁决」。
  • 契约复审(CONTRACT_REVIEW_TIER)在当前提交上 PASS(6181973332)。CI 35 项:32 项通过,3 项按设计跳过。
  • 供参考:裁决自带的余量仪表按本次运行算出 14 腿就够。16 是卡上实测区间 13–16 的上沿,多花的两腿换的是对慢机器的余量。席位建议 16。

你要做的:用 os-zhuang 或 hotlong 批准本 PR(它改了 .github/workflows/** 和 AGENTS.md,属受管面)。

席位核对

Verdict: ACCEPT (Tier H: draft until an authorised approval). Reviewed on GitHub against the build claim 6181366176 on objectui#12384, the accepted reading 6181333653 and the dev's report 6181669972, not on the report's own account.

  • Shape.
    • Draft, base main, assignee sunhaolin, author objectstack-fleet[bot].
    • Line 1 is Fixes #12384 and is the body's only closing keyword.
    • 17 files, +107/−62.
    • check-governed-merges --pr: GOVERNED, Tier H: AGENTS.md and three .github/workflows/** files. 169 changed lines, under 3000.
  • Premises, measured. A1–A4 hold.
    • A2: the live main ruleset names the Test aggregate and no leg, so the width is a workflow edit.
    • A3: the dataset carries no width, and the refresh's own PR leg on this head skipped all 30 old-width runs, read NOT MEASURED and stayed green.
    • A4: about 8.4 min per leg.
  • Gates, read off check-runs whose head_sha is 0f5a949e4a28bc2846109484958153673b994a48. 35 check-runs, every one completed: 32 success and 3 expected skips (the coverage legs and dependabot).
    • All 16 Test (shard N/16) legs are success, in 5m24s to 9m52s.
    • Test 116185315577, Lint 116182295200, Type Check 116182294410, Repo Gates 116182294450 and Governed Surface Queue Guard 116182294314: all success.
  • Contract review of record: 6181973332 on this head, CONTRACT_REVIEW_TIER, PASS. It found:
    • every width pin moved, and none left behind (a tree-wide sweep of 29 workflows and the shard, timing and dependabot scripts);
    • the ceiling, the runner, the coverage lane and the relevance gate unchanged;
    • the required check set unaffected.
  • Deviations, accepted:
    • the width-neutral comment edits;
    • A2 read with --fixture (the live mode answered 401 here) and confirmed against the live ruleset by the review;
    • the whole scripts/__tests__/ run as a superset of the named files;
    • the model-free commit trailers, per objectui AGENTS.md;
    • one case added in scripts/__tests__/test-file-timings.test.ts, outside the claim's surface. It is bounded in place under all four conditions, and the claim's file surface is amended on the card in this act, together with the four script usage headers.
  • Out of scope, routed:
    • The slow-VM testTimeout exposure (two export-to-react-compiles tests at 17.3 s and 17.6 s against 15000 in job 116029528393) loses its carrier when this PR's Fixes closes objectui#12384. So it is filed now as its own card, linked on the card in this act.
    • The stale /4 comment in ci-cd-pipeline-doc.test.ts has no reader and stays in the PR's Acceptance notes.
  • After landing:
    • The first weekly timings refresh should take the first green 16-leg full battery. NOT MEASURED past its second week is a finding.
    • Ruling 6121816480's acceptance (ten consecutive full runs with the longest leg under 60 % of the cap) is read by the headroom step on every run.
  • Landing clause:
    • Draft until a latest-decisive APPROVED review from GOVERNED_APPROVERS (os-zhuang / hotlong).
    • Then this seat lands it: pr_ready, then automerge_enable through the merge queue.

Implemented-by: claude/issue-12384-test-shard-cancellations
Reviewed-by: session_01JZnppgHRp4sREcouhkQYDB


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review October 15, 2026 01:14
@os-zhuang
os-zhuang enabled auto-merge October 15, 2026 01:14
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit 140916c Oct 15, 2026
35 of 36 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-12384-test-shard-cancellations branch October 15, 2026 01:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ci/cd configuration documentation Improvements or additions to documentation tests

Projects

None yet

3 participants