Repository navigation
ci: Spec Main Shape Gate leaves the required set — advisory on PRs, hourly on main; the required-check pin declares the seven ruled names (objectui#12240) - #12250
Conversation
… and a main-red on its hourly run (objectui#12240) The context leaves the merge queue's required set on the maintainer's ruling B (objectui#12214 ACCEPT 6123370050, question 1). Requiredness is the ruleset's property, so the workflow needs no mechanism for it: no `continue-on-error`, no trigger dropped, nothing it verifies touched. The header now says what each event is for, that a red on the hourly `main` run is a main-red for the domain:devx lane under objectstack#22998's rule 3, and why `merge_group` stays subscribed: until the maintainer's ruleset edit the queue still requires the name, and a workflow that stopped reporting there would stall every queue build at the 60-minute timeout. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqNgdPZB2Jnr5HpGbaqLeB
…mbstones Spec Main Shape Gate (objectui#12240) The maintainer's ruling B (objectui#12214 ACCEPT 6123370050, question 1) takes `Spec Main Shape Gate` out of the merge queue's required set. The patrol's declaration (PINNED `Type Check` plus WATCHED) becomes the seven names the ruling installs: `Spec Main Shape Gate` leaves under a tombstone, and `Governed Surface Queue Guard`, enrolled under objectui#6596 and never declared here (every live reading printed it as required but not declared), joins WATCHED. The test pins the merge-then-edit window on a verbatim live reading of 2026-10-12: the patrol reads it as DRIFTED naming `Spec Main Shape Gate`, exit 0. The control fixture is that reading minus the one context; the ablation fixture is the control minus `Type Check`. The two #9969-era fixtures, read by nothing else, are retired. The in-tree half of the removal: `scripts/dependabot-merge-gate.mjs` moves the name from `REQUIRED_CONTEXTS` back to `NOT_A_GATE` with its reason, so a Dependabot bump stops waiting for an advisory check; its test pins the move by name with a control. That also takes the workflow out of the derived `merge_group` floor, while the workflow keeps the trigger (see its header). Two other enumerations move with it: the present-tense ruleset list in repo-gates.yml's header, and the stale counts in required-check-set-patrol.yml's comments. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqNgdPZB2Jnr5HpGbaqLeB
…urly run, and the patrol section carries no count (objectui#12240) The inventory row and the gate's section say the context left the required set by the maintainer's ruling B, what each event is for now, that a red on the hourly `main` run is a main-red for the domain:devx lane, why `merge_group` stays subscribed, and that the Dependabot gate classifies it `NOT_A_GATE`. The fold paragraph's present-tense "their contexts are required" is dated to the fold. The patrol section's "the other eight" / "the nine" counts become pointers to the script's declaration. The command-parity ledger's two reasons for this section are re-worded to the new classification; their keys are unchanged. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqNgdPZB2Jnr5HpGbaqLeB
维护者速读(终稿)· PR #12250 · 席位已对照 diff 逐行校正,2026-10-12T13:17Z改了什么: 为什么改:你在 objectui#12214 的问题 1 上选了 B(「我接受你的建议」)。这个检查是每个 PR 最慢的一环(约 13 分钟),且它红的时候约七成是 objectstack 那边在变,不是这个 PR 的错。拿掉之后,PR 的等待时间降到 风险与代价(含回滚):一个 objectstack 改坏 objectui 编译的变化,不再在 PR 上被拦住,而是在下一次整点运行时在 席位意见:建议批准。改动的实质只有一处清单(七项)和 Dependabot 门,工作流本身零语义改动;收益是每个 PR 少等约 3 分钟并止住"objectstack 漂移把 objectui 的 PR 踢出队列"这一类红。dev 提出的后续项(规则改完后让该门不再在合并队列上跑,省每天约 440 runner 分钟的公共 runner 占用)席位取 B,另立一张小卡排在你改规则之后。 你要做的:① 在 PR 上 Approve(席位随后翻正式并入队);② 同一次操作里到 Settings → Rules → Rulesets → |
Fixes #12240
Clause-②: no
Spec Main Shape Gateleaves the merge queue's required set on the maintainer's ruling B (objectui#12214, ACCEPT 6123370050, open question 1 answered B, filed as objectui#12240). It keeps running and keeps posting its verdict; nothing it verifies changes (the bypass, the anti-false-green marker with the injected sha and time, the attribution). This pull request moves every in-tree declaration of the required set. The ruleset edit itself is the maintainer's act.The required names, before and after
Before (live, read 2026-10-12 with
gh api repos/objectstack-ai/objectui/rules/branches/main, ruleset 11776024, in the endpoint's order):Lint·Type Check·Build & E2E·Build Docs·Changeset Declaration·Test·Spec Main Shape Gate·Governed Surface Queue GuardAfter the maintainer's edit (the same list minus one, order kept):
Lint·Type Check·Build & E2E·Build Docs·Changeset Declaration·Test·Governed Surface Queue GuardThe "after" list is byte-identical to the seven names
scripts/check-required-check-set.mjsnow declares (PINNED_CONTEXTS=Type Check,WATCHED_CONTEXTS= the other six) and to the committed control fixtureruling-12240.json.The maintainer's act, in the same sitting as the merge
Settings → Rules → Rulesets → ruleset 11776024 (
main) → "Require status checks to pass" → removeSpec Main Shape Gate. Nothing else in the ruleset changes.Either order is safe, because
spec-main-shape-gate.ymlkeeps itsmerge_grouptrigger (see the trigger decision below). One case forces "edit first": ifSpec Main Shape Gatehappens to be red when this pull request is enqueued (objectstack drift), its own queue build is still gated by the context until the edit.What
required-check-set-patrolreads in between: GREEN, not redRead from
scripts/check-required-check-set.mjs, not assumed: a required context the pin does not declare makes the verdictdrifted;exitCodeFor('drifted')is 0; the patrol's "Fail the run" step runs only on a non-zero exit. Measured with this branch's script over the live answer:DRIFTED — every pinned context present; 0 watched missing, 1 undeclared (8 required context(s) read), summary line "Required but not declared here:Spec Main Shape Gate.", exit 0. Pinned by the test on the dated verbatim readinglive-2026-10-12.json.ruling-12240.jsonfixture):INTACT — 1 pinned and 6 watched context(s) all present (7 required context(s) read), exit 0.main, before this PR: the same live answer already reads DRIFTED, namingGoverned Surface Queue Guardas required but not declared (enrolled under objectui#6596, never added to the pin). This PR declares it, as the ruling's seven names include it.main's old pin reads DRIFTED naming both halves, exit 0.The patrol cannot go red from this change in any order: its one pinned name,
Type Check, is untouched.The trigger decision:
merge_groupstays (H2 refuted on sequencing)The PM's suggestion was to drop
merge_group. Kept, deliberately; the workflow header now says why.max_entries_to_build: 5), would never report a context the ruleset still requires and would wait outcheck_response_timeout_minutes: 60and fail: objectui#3523's shape, on the way out. Keeping it makes this PR order-independent.scripts/__tests__/spec-main-shape-gate.test.ts› "subscribes merge_group, so a maintainer can enrol it without stalling the queue" reds on the drop. Measured: an ablation deleting the two trigger lines ran the five affected test files at 1 failed / 211 passed (that test only), restored to the HEAD blob.merge-queue-reporting.test.ts's derivedmerge_groupfloor stops covering this workflow once the Dependabot gate classifies the nameNOT_A_GATE(below), so that pin does not bind.merge_groupruns of this workflow (2026-10-09T12:50Z to 2026-10-12T12:17Z;total_count1255) are about 33.6 runs a day at a 13.1-minute median wall, about 440 runner-minutes a day; public repository, not billed. After the edit those runs gate nothing and do not lengthen a queue entry (the queue waits only on required contexts); they occupy runner slots. For scale,pull_requestruns: 100 in the newest 1.08 days, 12.1-minute median.merge_groupand rewords that pin to "re-subscribe before re-enrolling". The report carries it as an open question.H1: partly refuted, there was a second blocking mechanism in the tree
Whether a check blocks the queue is the ruleset's property, so the workflow needs no mechanism: no
continue-on-error(it would hide the verdict), and no placeholder or plumbing step exists in the file. The concurrency rule that never cancels a queue build exists for the required role and is not dead whilemerge_groupis subscribed; left as is. Butscripts/dependabot-merge-gate.mjsdeclared the name inREQUIRED_CONTEXTS, so the Dependabot auto-merge gate waited for the check and refused a red: a pull-request-side block the ruleset edit would not remove, and the line the workflow header itself called the in-tree half of the enrolment. It moves toNOT_A_GATEwith its reason; the test pins the move by name with a control (the same red onType Checkstill refuses). Window note: between merge and edit the Dependabot gate no longer waits for it while the queue still does; a red there is caught by the queue build.H3: confirmed
The hourly
schedule(cron: '48 * * * *') is inspec-main-shape-gate.ymlitself (PR #12232,21fdeb34). This card owns no line ofci.ymland touches none. NOT MEASURED: the first scheduled run (PR #12232 merged 12:10Z; at 12:55Z the Actions API listed noschedulerun of this workflow yet).H4: every enumeration moved, and the grep
git grep -n 'Spec Main Shape Gate'onmain(923504f4): 52 hits in 32 files.Moved (enumerations of, or claims about, the required set):
.github/workflows/spec-main-shape-gate.yml: the header section that said the context was "NOT required yet" is replaced by the advisory posture, the main-red rule and themerge_groupreasoning. Comment-only: the parsed YAML is identical tomain's.scripts/check-required-check-set.mjs: the pin (tombstone naming this card and ACCEPT 6123370050's answer B;Governed Surface Queue Guarddeclared).scripts/__tests__/check-required-check-set.test.tsand its fixtures: new dated live readinglive-2026-10-12.json, new controlruling-12240.json,type-check-removed.jsonregenerated from the new control;ruling-9499.jsonandruling-9969.jsonretired (read by nothing else).scripts/dependabot-merge-gate.mjsand its test:REQUIRED_CONTEXTStoNOT_A_GATE..github/workflows/repo-gates.yml: its header's present-tense list of required names is dated to the fold (comment-only).content/docs/guide/ci-cd-pipeline.md: the inventory row, the gate's section, the fold paragraph;scripts/__tests__/ci-cd-pipeline-doc.test.ts: the two command-parity reasons for that section re-worded (keys unchanged).Count enumerations without the name, moved:
required-check-set-patrol.yml("requires nine check contexts", "the eight WATCHED contexts"), the guide's patrol section ("the other eight", "the nine"), and the script header's present-tense "currently holds nine contexts". Each now points at the script instead of carrying a number (AGENTS.md #9). No script or test reads any of these counts, so nothing was loosened to "at least".Left, because they are not enumerations of the required set: three pending changesets (11573, 12093, 12170) and three published CHANGELOG entries describe the gate as a compile target; 21 hits in 16 files under
packages/name it as the compile against objectstackmain;scripts/spec-main-shape-gate.mjsprints it as a summary heading. None says the context is required.AGENTS.mdandCONTRIBUTING.mdcarry no enumeration of the set.Gates, on head
22124378objectstack's
dispatch-gates.mjs --commands --repo objectstack-ai/objectuirefuses by design (it derives only from an objectstack checkout), so the list is hand-derived from this repository'spackage.jsonand workflows:pnpm exec vitest run scripts/ eslint-rules/: 191 files passed, 2 skipped, 1 failed, 5778 tests passed (lock VERDICT command-exit 1). The one failure isdollar-dialect-alias-census.test.tstiming out at 15 s with the import phase at 344 s on a shared box; it reads none of the changed files and passes alone (37/37, 8.1 s).check-required-check-set,dependabot-merge-gate,merge-queue-reporting,spec-main-shape-gate,ci-cd-pipeline-doc,check-merge-queue-head): 252/252.node scripts/check-required-check-set.mjs --self-test: 32 cases pass, exit 0. Live: node's fetch answers 401 through the agent proxy (as on objectui#12214), so the live answer was taken withghand fed through--fixture: DRIFTED, exit 0, as above.pnpm type-check:scripts: exit 0 (--listFilesOnlyincludes the three edited test files).eslint --no-inline-config --format jsonover the five changed.mjs/.tsfiles: 5 files, 0 errors, 0 warnings. The narrowing is proven: population fromeslint.config.js(flat-config defaultjs/mjsplusfiles: ['**/*.{ts,tsx}']; no ignore coversscripts/); count from the JSON output; noparserOptions.project/projectService(type-aware linting off) and no rule undereslint-rules/reads the disk, so this diff cannot move the verdict on an untouched file.check-governed-queue-guard --self-test(and--testover the 12 paths: NOT GOVERNED),check-merge-queue-head --self-test,check-changeset-presence(no changeset owed),check-control-bytes,check-doc-links,check-doc-fence-languages,check-action-ref-convention,check-new-cross-file-line-citations(0 new),check-pre-install-import-graph,check-lint-coverage,check-test-path-roots.main's.actionlint: NOT MEASURED (not installed).Ablations (committed first, through
ablation-replace.mjswith its trap and blob proof):Spec Main Shape Gatere-added toWATCHED_CONTEXTS: 6 failed / 25 passed incheck-required-check-set.test.ts; restored to blob76373853.Spec Main Shape Gateput back inREQUIRED_CONTEXTS: 4 failed (the new block and the partition test) / 53 passed acrossdependabot-merge-gateandmerge-queue-reporting; restored to blob21f065a2.merge_groupcounterfactual above: 1 failed / 211 passed; restored to blobba27aba4.Acceptance notes
Type Checkbound; the gate visible as non-required; the hourly run carrying it) is measurable only after the maintainer's edit and the first scheduled runs.concurrencyandtimeout-minutescomments still reason about queue builds; true whilemerge_groupis subscribed and the context is required, moot for an advisory check afterwards. Left untouched (timeout-minutesis out of this card's scope); amerge_groupfollow-up would be their carrier..github/workflows/**is called Tier H in the claim;node scripts/check-governed-queue-guard.mjs --testanswers NOT GOVERNED for all 12 paths. The PR stays a draft either way: it is a dispatched PR.check-changeset-presenceexit 0).维护者速读(草稿)
改了什么:
Spec Main Shape Gate(用 objectstackmain现编出的 spec 编译本仓)从合并队列的必过检查里拿掉。它照样在每个 PR 上跑、照样给出结论,只是不再挡合并;每小时在main上跑一次,作为完整测试的一部分。仓内所有"必过检查清单"的记录一起改成新的七项,Dependabot 自动合并也不再等它。它检查的内容一个字没动。为什么改:你在 objectui#12214 的问题 1 上选了 B(「我接受你的建议」)。这个检查是每个 PR 最慢的一环(约 13 分钟),而且它红的时候多数是 objectstack 那边在变,不是这个 PR 的错。拿掉之后,PR 的等待时间降到
Type Check那一档。风险与代价(含回滚):一个 objectstack 改坏 objectui 编译的变化,不再在 PR 上被拦住,而是在下一次整点运行时在
main上变红;那时按两档 CI 的规则算作 devx 这条线的 main-red,下一个 PR 先修它。巡检(required-check-set-patrol)在合并和你改规则之间读作"有漂移",但不会变红。回滚:在规则集里把这个检查加回去,并还原本 PR 的三个提交;工作流仍订阅合并队列,所以加回去不会卡住队列。席位意见:
你要做的:批准并合并本 PR;同一次操作里到 Settings → Rules → Rulesets → 11776024(
main)→ 必过状态检查,删掉Spec Main Shape Gate,剩下七项保持不动。先后顺序都可以;只有当这个检查在入队时正好是红的,才需要先改规则再入队。Generated by Claude Code