Repository navigation
ci(workflows): measured timeout-minutes on 17 jobs, PR-only concurrency on 11 workflows, a paths filter on check-links - #26376
Conversation
…ls; concurrency on 11 PR workflows Claude-Session: https://claude.ai/code/session_01ADHkmSfkkJZXxR3bPjvRzh Co-authored-by: Claude <noreply@anthropic.com>
…ADR step read Claude-Session: https://claude.ai/code/session_01ADHkmSfkkJZXxR3bPjvRzh Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
席位核对 · REVISE · devx seat 2 · 2026-10-27T01:06ZSeat One item to fix (blocking, small):
Checked and accepted as is:
Noted, not for this PR: |
Requested by Steve · project thread
Fixes #26085
Clause-②: no
Metadata-protocol: none
维护者速读
timeout-minutes;给 11 个 PR 触发的工作流加concurrency,同一 PR 的新推送取消旧运行;check-links只在改到它读的文档时才跑。release.yml的 publish 超时(设 120 分钟,按各步骤上限求和再加一半,杀在changeset publish中途就是半发布);取消只对pull_request生效,push、merge_group、schedule、dispatch 一律不取消。回滚 = revert 本 PR,纯 YAML。.github/workflows/release.yml(publish 的 120 分钟及注释)、.github/workflows/pr-automation.yml(concurrency 按「推送 / 标签与编辑」分两组)、.github/workflows/check-links.yml(paths 与目标侧盲区说明)。PR Automation运行没有取消opened那次运行(两次都完成);下一次推送后,上一轮 PR 工作流显示 cancelled。.github/workflows/**,Tier H):请 GOVERNED_APPROVERS(os-zhuang 或 hotlong)批准,批准后由席位落地。What changes
1.
timeout-minuteson the 17 jobs the card lists. Re-read onorigin/main6390fe5 first: exactly the card's 17 jobs lacked one (no job moved), and after this PR every non-reusable job in.github/workflows/declares one (read below). Each value comes from that job's own recent runs and is written beside it in the YAML. Where only a run-level time exists, the run wall (updated_at − run_started_at, queue included) is used as an upper bound for the job.check-links / link-checkercodeql / analyzecross-repo-issue-closer / close-foreign-issuesdocker-publish / publishdocs-drift-check / docs-driftduplicate-fix-guard / duplicate-fix-guardpartof-closing-keyword-guard / partof-closing-keywordpr-automation / pr-sizepr-automation / auto-labelpr-automation / changeset-checkrelease / version-prrelease / release-integrityrelease / stale-promptsrelease / publishsingle-claim-path-guard / single-claim-pathspec-liveness-check / livenessstale / staleAll minutes. Three values are deliberately wider than "p99 plus a bit", and each says why in the YAML:
publish= 120. One reading cannot give a p99, and a timeout here cancels mid-changeset publish— the half-published state that job's own concurrency note exists to prevent. So it is set from the steps' ceilings: build + Console build about 15 min cold (6.6 + 7.3 on 18.1.0),release-verify-npm.mjs's retry budget of up to 35 min afterchangeset publish, and the dist-tags step's owntimeout-minutes: 15— about 80 min in all, plus half again. The approval wait at thereleaseenvironment is not job time.docker-publish= 30. Four readings; the image is built for two platforms with arm64 under QEMU, and a cold layer cache was never measured.stale= 45. p99 is 0.6 min, but one green run took 26.6 min (run 33285517150, 2026-08-30); the bound keeps it.2.
concurrencyon the 11 PR-triggered workflows (check-links,docs-drift-check,duplicate-fix-guard,engine-split-metric,os-create-smoke,pack-smoke-optin,pr-automation,scaffold-e2e,spec-liveness-check,upgrade-harness-optin,validate-deps— re-read on 6390fe5, the same 11). The group key isci.yml:112-114's, prefixed with the file stem:cancel-in-progressis an expression rather than ci.yml'strue, so only apull_requestrun is ever cancelled: none of the 11 runs onpush, and the one withmerge_group(spec-liveness-check) can never cancel a queue run — its key is also the queue ref, unique per entry. Schedule and dispatch runs share a group per event and wait instead of cancelling.Two key refinements, because these workflows fire on PR activity other than a push:
pr-automationruns onlabeled/unlabeled/editedtoo, and on those onlyCheck Changesetruns (pr-sizeandauto-labelskip). One group would let a label cancel a push run's size and label jobs — and the relay'spr_createwrites labels right after the draft opens, so that would happen on almost every PR. The key gets a last segment,metafor those three actions andcodeotherwise, so each kind only supersedes its own.pack-smoke-optin/upgrade-harness-optinrun onlabeled, but the job runs only for their own opt-in label. A run for any other label goes to a group of its own (github.run_id), so adding an unrelated label never cancels a 30–45 min opt-in run.3.
check-links.ymlgets apaths:filter (workflow_dispatchkept): the wholecontent/anddocs/trees, the eight root pages inLYCHEE_ARGSsince #26313,lychee.toml,.lycheeignore, and the ADR step'sscripts/check-adr-links.mjs(+ its one import) anddocs/adr/**, plus the workflow itself. Checked with lychee 0.24.2's--dump-inputsunder CI's exact argv: 521 inputs, 0 outside the filter. On the last 49 landings ofmain, 10 touched one of these paths. The YAML states the blind spot (below) and that promoting the lane to required removes the filter in the same change.Not in this PR: the card's optional
permissions: {}(out of the claim),ci.yml(untouched), and no job was renamed.Tests
node scripts/ci/scheduled-full-run.mjs --check-concurrency→ exit 0 (ci.yml and lint.yml groups unchanged; this gate reads only those two files).timeout-minutes: a YAML walk of every.github/workflows/*.ymllisting jobs with neithertimeout-minutesnoruses:→ empty (it listed the card's 17 on 6390fe5). The oneuses:job,release / docker, is bounded by the callee's newdocker-publish / publishvalue.LYCHEE_ARGS: 2883 links, 0 errors;--dump-inputs521 files, all inside the newpaths:.Acceptance notes
check-linksfilter. Lychee also reads the files links point AT. Measured on 6390fe5, links from the inputs resolve to paths outsidecontent/anddocs/(about 100 links:packages/*directories from CONTRIBUTING.md,LICENSEandui/LICENSEfrom LICENSING.md,examples/*,skills/…,.github/workflows/…). A PR that only renames or deletes one of those now skips this advisory lane; the break shows on the next PR that touches a doc or on a dispatch run. Covering it would meanpackages/**in the filter (which nearly every PR touches) or a scheduled run; neither is in this card's scope.scripts/release-verify-npm.mjsL80-82 says "the publish job declares notimeout-minutes, so GitHub's 360-minute job default bounds this step". After this PR the publish job's 120 min bounds it. That file is outside this claim's file surface, so the comment is left as is and reported to the seat.version-pr; not looked into here.Verification
Local gate subset (
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 55 commands at HEAD 62f0d0f), each exit taken before any pipe,--ranreconciliation55 derived, 55 run, 0 NOT-MEASURED, 0 UNRUN(a DERIVED zero):Gate readings
node scripts/check-adr-links.mjsnode scripts/check-adr-links.mjs --self-testnode scripts/check-aggregator-roster.mjsnode scripts/check-aggregator-roster.mjs --self-testnode scripts/check-changeset-fixed.mjsnode scripts/check-ci-filter-parity.mjsnode scripts/check-closing-keyword-parity.mjsnode scripts/check-closing-keyword-parity.mjs --self-testnode scripts/check-comment-mask-corpus.mjsnode scripts/check-cross-repo-closer-outcome.mjsnode scripts/check-cross-repo-closer-outcome.mjs --self-testnode scripts/check-engine-split-ratio.mjs --days 90node scripts/check-osv-exemptions.mjsnode scripts/check-osv-exemptions.mjs --self-testnode scripts/check-self-test-wired.mjsnode scripts/check-self-test-wired.mjs --self-testnode scripts/check-self-test-workflow-commands.mjsnode scripts/check-self-test-workflow-commands.mjs --self-testnode scripts/check-step-collectors.mjsnode scripts/check-step-collectors.mjs --self-testnode scripts/check-whole-set-label-write.mjsnode scripts/check-whole-set-label-write.mjs --self-testnode scripts/ci/scheduled-full-run.mjs --self-testnode scripts/docs-audit/check-affected-docs.mjsnode scripts/docs-audit/check-drift-comment.mjsnode scripts/osv-base-relative.mjs --self-testnode scripts/pm/ci-failure.mjs --self-testnode scripts/release-dist-tags.mjs --self-testnode scripts/release-verify-npm.mjs --self-testpnpm check:agent-test-spellingpnpm check:cross-package-test-inputspnpm check:declared-population-livepnpm check:driver-memory-censuspnpm check:gitlink-declaredpnpm check:node-versionpnpm check:nul-bytespnpm check:override-consistencypnpm check:partof-closing-keywordpnpm check:pm-dispatch-gatespnpm check:pm-expected-skipspnpm check:pm-governed-mergespnpm check:pm-post-stampedpnpm check:pm-record-recogniserspnpm check:pnpm-acquisitionpnpm check:pnpm-filter-targetspnpm check:refd-timer-probepnpm check:required-contextspnpm check:shard-attestationpnpm check:single-claim-pathspnpm check:stall-guard-budgetpnpm check:stall-guard-headroompnpm check:vendor-export-contract-resolvepnpm check:watch-hint-literalpnpm check:workflow-status-functionspnpm check:workflow-step-name-quotingnode scripts/check-engine-split-ratio.mjs --days 90first exited 2 (PREREQUISITE: the shallow clone sat inside its 90-day window); aftergit fetch --shallow-since=2026-07-22 origin mainit exited 0 (ratio 97.6%).Also run, from the roster block that keeps its list under
.github/workflows:check-platform-checklist-watchdog(+--self-test),check-ci-filter-parity --self-test,ci/select-shard-timings-run --self-test,pr-labels --self-test,check:pm-governed-prose,check:select-gate-families→ all exit 0.check-governed-queue-guard.mjsexits 1 locally because it reads onlyGITHUB_EVENT_PATH; its verdict is the requiredGoverned Surface Queue Guardcheck on this PR.Families that take a value from the workflow (
check-partof-closing-keyword,check-single-claim-paths,check-required-contexts --verify-required-set, the shard attestations) are NOT MEASURED locally and are read from this PR's own check-runs.Generated by Claude Code