Repository navigation
ci(test-ui): add the Test UI aggregate job and register it as a required context - #26569
Conversation
…uired context A `test-ui-gate` job named `Test UI` over the 16 `test-ui` shards, in test-gate's shape (`name:` literal, `if: always()`, roster declaration), red on any rollup other than success or a filter-explained skip. One REQUIRED_CONTEXTS row, the REQUIRED_AGGREGATORS floor row, self-test cases for both, and the two statesTheSet instruction surfaces follow the registry (eight to nine). Claude-Session: https://claude.ai/code/session_01ADHkmNhqdySz5JeM3ARKGW Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Card #26460 read in full: body, brief 6433960457, ruling 6435318516 (letter A, staged), ui claim 6436277065, flake reading 6436579765 (0/50), ui os-dev-report 6436597045, devx claim 6436627175, devx os-dev-report 6437393268. Net diff read as ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS |
席位核对 · ACCEPT · devx seat 2 · 2026-10-27T08:50ZSeat
Landing (Tier H: |
Conflicts in three skill files main also edited (#26536, #26569): kept main's root-run console:build wording and its ninth required context (Test UI), kept this branch's removal of the objectui-only lines and the retired SHA-stamp drift bullet (no .objectui-sha pin or build-console.sh exists any more). Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibvE77Ed7MKdzPxJTQQ
Requested by Steve · project thread
Fixes #26460
Clause-②: no
Metadata-protocol: none
Tier H (
.github/workflows/ci.yml,AGENTS.md;.claude/**rides along). Draft until an approval from GOVERNED_APPROVERS (os-zhuang, hotlong). The ruleset half — addingTest UIto themainruleset's required status checks — is the maintainer's, done in the same sitting as the merge (#9325's two halves; precedentLint UI/Build & E2E UIvia #25857 andType Check UIvia #25878).维护者速读
Test UI(job idtest-ui-gate),覆盖 16 个Test UI (k/16)分片,任一分片不是 success 就红;分片因 ui 过滤被跳过时为绿。注册表、汇总名册和两处写着必过名单的说明文字同步从 8 个变 9 个。doc-version-claimsanchors the docs' Node version on literalnode-version:lines in .github/workflows, so #26419 (Node read from.nvmrc) turns it red #26421)。ui 车道的第一阶段读数已完成:最近 50 次跑了 Test UI 的队列构建 flake 0/50(6436579765)。Test UI才生效;回滚就是从 ruleset 删掉这一项再 revert 本 PR。若 Test UI 出现 flake,会把队列条目弹出。.github/workflows/ci.yml新增的test-ui-gate任务(判定的 case 分支);scripts/check-required-contexts.mjs新增的注册行;AGENTS.md第 525–528 行的名单。node scripts/check-required-contexts.mjs && node scripts/check-aggregator-roster.mjs,应看到ci.yml:test-ui-gate → 'Test UI'和5 aggregator(s);本 PR 的 checks 里应有一个名为Test UI的绿色检查。main的必过检查里加上Test UI。What changes
.github/workflows/ci.yml: a new jobtest-ui-gate,name: Test UI,needs: [test-ui, filter],if: always(), placed right aftertest-ui. It copiestest-gate's shape: thename:literal andif: always()are both load-bearing, and it declares its roster (OS_AGGREGATOR_MEMBERS: test-ui,OS_AGGREGATOR_NON_MEMBERS: filter). Its one step reads the matrix rollupneeds['test-ui'].result:success→ green;skipped→ green only whenfilterconcludedsuccessand said the diff reaches no ui path (ui_treeoruiis'false', the shards' ownif:), thefilterjob 一旦失败,Test Core / Build Core / Dogfood 会全部 skipped 而分支保护判为通过 —— 隐式 success() 今天已第三次咬人 #4928 guard. That is how a PR or queue build that touches no ui path reads, the same wayLint UIandBuild & E2E UIreadskippedtoday;failure,cancelled, an unexplainedskipped, a lifecycle value such asabandoned) → red, with an::errornaming the rollup.No other job changes: no shard, timeout or filter edit, and no Test Core line (ci(test-shards): Test Core's two slowest shards set every core PR's wall clock at ~28 min (5.6 min dependency build + ~20 min tests) while the other six finish in 7–17 — re-derive the cli slicing and shard balance on post-merge readings #25870 edits that section in parallel; the hunks do not overlap).
scripts/check-required-contexts.mjs: oneREQUIRED_CONTEXTSrow (ci.yml,test-ui-gate,Test UI,authorizednaming ruling 6435318516 and the reading 6436579765). BothstatesTheSetsurfaces'mustNamegainTest UI. Self-test: battery (3) renames the bareTest UIname and expects red; battery (9) collides theTest UI (k/16)shard name with the bare gate name and expects red, plus the coexistence control.scripts/check-aggregator-roster.mjs:REQUIRED_AGGREGATORSgainsci.yml/test-ui-gate/Test UI, the floor that keeps the new aggregate from losing its roster declaration. Self-test batteries (2) and (3) gain the dropped-member and phantom-needs:controls for it.AGENTS.md(merge-queue rule) and.claude/skills/pm-dispatch/references/platform-readings.md: the required-set list grows from eight to nine.check:required-contextsreds until both name the registry exactly (statesTheSet); the count words are hand-followed.Why
Ruling A (staged) on #26460, comment 6435318516. The ui step it orders first is done: the flake reading on the newest 50 queue builds that ran Test UI is 0/50, and every Test UI red in the last 24 hours has a named cause that is fixed on
main(comment 6436579765).Acceptance notes
test-gatecounts shard attestations because one rollup word cannot carry several shards' verdicts. The Test UI shards publish no attestation, and adding one is a change totest-ui(pinned by the ui lane'sui/scripts/__tests__), so this job reads the rollup and fails closed on every value exceptsuccessand a filter-explainedskipped. The rollup's known blind spot, a matrix where some legs are skipped and the rest succeed, cannot occur here: all 16 legs share one job-levelif:and a static matrix, and the ui lane pins the width at 16 (select-affected-tests-wiring.test.ts).cancelledis red. That is also what a shard killed by its owntimeout-minutesreads, which must not pass. On a superseded push it paints the old sha red, which no required check reads.ui/scripts/check-test-shard-results.mjs(the portedTestaggregate, row 7 of tooling(ui-wiring): objectstack-side inert wiring for theui/workspace — workspace globs, root turbo tasks, path-filtered ui test/typecheck/lint/E2E jobs, spec change compiles the Console; pin gates retire at cutover (parent #25677, 3/6) #25697's roster, "dropped until cutover") hardcodes theTest (shard N/M)spelling, so it cannot readTest UI (k/16)without a ui-lane change. Not used here; noted for the ui lane.Verification
All on head
853ddedb4.The two touched gates and their self-tests
dispatch-gates derived family
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran→ exit 0: 80 derived, 80 run, 0 NOT-MEASURED (a derived zero). Five families first read exit 3 (PREREQUISITE NOT MET: no builtpackages/*dist) and were re-run green afterturbo run build --filter='./packages/**':check:doc-formula-expressions,check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content.check:pm-dispatch-gates: 1935 fast-tier cases pass.Also run, outside the derivation because the ui lane's pins read
ci.ymlas text:pnpm --dir ui exec vitest run scripts/__tests__→ exit 0, Test Files 178 passed, 2 skipped (180); Tests 5097 passed.Human Minimum
packages/specholds no runtime logic. (No schema touched.)pnpm lintis CI's repo-wide run, not run locally.main, one pull request.skip-changeset; both declaration lines are above.packages/specnot touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code