Repository navigation
ci: the six Test Core shards build their dependency closure with DTS on — spec's 6 GB-heap declaration pass and cli's full tsc run on every shard although vitest never reads a .d.ts; set OS_SKIP_DTS=1 on the shard legs and their main seed #25375
Description
Filing gate: ③ maintainer-directed task (CI performance programme, 2026-10-23). Reader: the domain:devx execution seat, dispatch step — one os-dev, one PR. Dedup: search_issues on objectstack-ai/objectstack, closed included, "OS_SKIP_DTS test shard dependency closure build dts tsup skip declarations CI" → 29 hits; on-topic are #11907 and #12078 (both closed — a DTS-less cached build served where DTS was needed; the repair that followed is turbo.json's globalEnv: OS_SKIP_DTS), none open. Session: session_01GVTBi44LAWbPWg4evKfE1T.
One-sentence problem
Each of the six Test Core shards first builds the packages its tests depend on, and that build emits TypeScript declarations for every package — including @objectstack/spec's separate 6 GB-heap declaration pass and @objectstack/cli's full type-checking tsc — even though the tests only load JavaScript; on a cold run that is 3–6 minutes per shard spent producing files nothing in the job reads.
Evidence (file lines at objectstack commit 303aef0)
grep -rn OS_SKIP_DTS .github/workflows→ 0 hits: CI never sets it. 20 of 22tsup.config.*files readdts: !process.env.OS_SKIP_DTS(onedts: false, none unconditionally on); the roottsup.config.tsthe same.packages/spec/package.json:267—build=gen:migration-registry && gen:schema && gen:openapi && tsup && NODE_OPTIONS=--max-old-space-size=6144 BUILD_DTS=true tsup && check-dts-emitted && check-dts-references && check-dev-prereqs --stamp; spec's source is 2174 .ts files / 30 MB.packages/clibuildis a fulltsc -p tsconfig.build.json(type-checks) and switches to--noCheckonly underOS_SKIP_DTS;cli#typecheckrunstsc --noEmitagain — cli is type-checked twice per lane today.ci.yml:758-760— the shard's "Build this shard's dependency closure" step (turbo run build --filter=PKG^...); measured cold 3.1–6.0 min per shard on PR run 39891259937 (Σ ≈ 31 runner-min), 3.0–3.4 min on merge_group 39894014103, 0–1.7 min warm.turbo.json:4—globalEnv: ["OS_SKIP_DTS"]: the variable is in every task hash, so a DTS-less artifact can never be replayed where a DTS-on one is expected (the Local turbo cache served a DTS-less@objectstack/plugin-authbuild in a fresh worktree withOS_SKIP_DTSunset — its own typecheck then reds on a diff that never touched it #11907 class is structurally closed) — and equally the shard legs will not replay Build Core's DTS-on artifacts once they differ.- AGENTS.md line 575 notes
OS_SKIP_DTS=1as the local fast path; line 1108: "OS_SKIP_DTS=1greenscheck:api-surfacelocally and reds it in CI" — the consumer gates that readdist/*.d.ts(lint.ymltypecheck-consumers, AGENTS.md 745–748) must keep DTS on. This card touches only the six shard legs.
Governing text
- AGENTS.md line 43: "tsup/vitest never type-check" — type-checking belongs to
pnpm typecheck, which is the lint workflow's job, not the test shards'. - AGENTS.md line 1108 (above) fixes the boundary: DTS stays on wherever a gate reads declarations.
Change
ci.ymlTest Core legs: setOS_SKIP_DTS: '1'on the closure build step and the test step (same hash namespace within the job), and on the push-main seed of the same job so the saved seed matches what PRs restore.- Verify no test in the shard set reads a
.d.tsor asserts on emitted declarations:git grep -l "\.d\.ts" -- 'packages/*/src/**/*.test.ts' 'packages/*/test/**'and thecheck-test-source-alias.mjsledger; any hit is listed in the PR with its disposition. - Measure on the PR itself, cold, both ways (one run with the variable, one without — a
workflow_dispatchor two pushes) and pin the winner in the PR body: the DTS saving per shard versus the lost chance of replaying Build Core's remote artifacts (different hash namespace). If the replay loss wins, the card closes with that measurement and no change.
Acceptance
- Cold shard closure build step ≤ 60% of today's on the same closure (e.g. 6.0 → ≤ 3.6 min) with all six legs green; Build Core, typecheck lanes and consumer gates unchanged and green.
cli#test(which depends on its ownbuild,turbo.json:209) still passes — the--noCheckbuild must emit what the cli spawner tests execute.
Work estimate
Lane domain:devx · 1 PR (.github/workflows/ci.yml; possibly turbo.json if a per-task env is preferred over the job env) · precedent: turbo.json's globalEnv line from the #11907 repair — PR not reachable from this depth-50 clone. Clause-②: no · Metadata-protocol: none · Tier H (governed surface — the PR waits for a GOVERNED_APPROVERS approval before ready).
Prior rulings read: os_skip_dts, dts, closure → docs/adr 1 hit, AGENTS.md 3 hits (lines 575, 1108 cited above); ADR none; thread: none.
Related: #11907 (closed), #12078 (closed), #22077 (closed).
Maintainer directive (verbatim, untranslated)
同意,立卡
— the maintainer, 2026-10-23, in reply to the director seat's offer 「(a) 我按 PM 流程把 A1–A5、B1–B3 立成卡进队列(英文卡面、带 Governing text: 与工作量列),由 os-dev 派发」. The CI performance analysis those letters index is the seat's 2026-10-23 five-line audit (objectstack ci.yml + lint.yml; the other 39 workflows; the repo-side turbo/vitest/gate configuration; objectui's 28 workflows; GitHub Actions run data for the preceding 5–55 hours). The maintainer's stated goal, verbatim: 「我希望优化的是性能和效率速度」.
Activity
objectstack-fleet commentedon Oct 23, 2026
Path: instrument — CI time-to-green for every lane (area:devpath, the road's dev/verify step) | none — no platform-checklist item asserts CI speed | priority:p2 (North Star rule 3: an instrument card inherits along the chain; the queue position is set by the maintainer directive below) | none
Triage: lands in domain:devx (objectstack) — .github/workflows/ci.yml Test Core legs; labels
tooling·area:devpath·priority:p2·pm:queue; type Task (the create door carries no type flag — triage sets it on first touch); rationale: CI never sets OS_SKIP_DTS, so six shard closure builds emit declarations (spec 6 GB heap, cli full tsc) that vitest never reads; the card asks the dev to measure the DTS saving against the lost remote replay and pin the winner.Direct-dispatch channel (pm-dispatch cross-repo-coordination: 「维护者直派通道:当面指挥的 PM 会话直接路由,只对明示指挥的卡成立。直派的审计评论逐字引用授权指令。」). The authorising words, verbatim and untranslated — the maintainer, 2026-10-23, replying to the director seat's offer:
The word covers filing and dispatch; the lane seat dispatches this card under it even while a p1 sits in the lane queue (优先序:维护者裁决 > 北极星). Labels and domain were set by the filing seat under this channel, not by triage — triage may spot-check (SKILL.md 域车道 例外二).
Filed by the director seat, session
session_01GVTBi44LAWbPWg4evKfE1T, from the 2026-10-23 CI performance audit (five read-only lines: objectstack ci.yml + lint.yml; the other 39 workflows; repo-side turbo/vitest/gate configuration; objectui's 28 workflows; GitHub Actions run data).Written 2026-10-23T04:43Z by the director seat.
objectstack-fleet commentedon Oct 23, 2026
Claim: PM loop round 3 · 2026-10-23T11:46Z
Session:
session_01VqzDQEbeHPVJoaEoutGsTi(card thread, dispatched by seat sessionsession_01LKHDniRQSWjRJyDtacwpEd)Account:
os-elon-muskBranch:
claude/project-thread-qwwbnr(the harness-pinned branch for the card thread; it names no issue, so this claim is the identity record)Worktree:
objectstack-issue-25375Domain:
domain:devxSeat:
domain:devx#1(seat post #6023)File surface:
.github/workflows/ci.yml, plusturbo.jsononly if a per-task env is preferred over the job env. Tier H: the PR stays draft until a GOVERNED_APPROVERS approval. (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier,effort: highClause-②: no
Metadata-protocol: none
Responsibility: n/a — CI time-to-green instrument (no defect producer)
Thread-read: none
Serial constraints cleared: #25373 and #25374 also edit
ci.yml. Re-readmainbefore each push, and mergemainif one of them lands first.Dispatched under the maintainer's 「同意」 to the director's ruling batch 1, item 5A (devx dispatches p1–p3). This card is also covered by the maintainer's 「同意,立卡」 for the CI performance audit cards, where the card says so. Dispatch order:
/mnt/project-files/pm-devx-seat/dispatch-25375.md.objectstack-fleet commentedon Oct 23, 2026
ACCEPT (seat review) → PR #25465 ·
domain:devxseat 1 ·session_01LKHDniRQSWjRJyDtacwpEd· 2026-10-23T15:36Ze62c37b1df: one file,.github/workflows/ci.yml(+40 / -1). It adds one step before each Test Core shard's closure build. The step writesOS_SKIP_DTS=1to$GITHUB_ENVunless the shard's package list (shard-packages.txt, first field) carries one of theDTS_READERSpackages,@objectstack/clior@objectstack/metadata.main.turbo.jsonhasglobalEnv: ["OS_SKIP_DTS"], and the tsup configs and cli's build already honour the variable. So the closure build, the test step and the shard's main seed all hash in one namespace per shard. No package or turbo file changes..d.ts" is false for cli and metadata. A full local run underOS_SKIP_DTS=1reds only their TS7016 tests: cli's published-subpath pins and the scaffold typecheck/test-script tests, and metadata's typescript-serializer-annotation. Keeping declarations on shards that carry either package is the right narrowing. A new.d.tsreader on a skipping shard reds loudly (TS7016), not silently. The silent-skip check is good: 32 packages re-run with DTS on gave identical totals. The one exception is spec's root-entry-type-nameability pin, which skips by design and runs inlint.yml's built-dist step.--force): 5m59s with DTS, 1m24s without.be7daa3f.main. ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds #25419 edits the region next to this step, so a textual conflict there is likely and is resolved by keeping both..github/workflows/**). A GOVERNED_APPROVERS approval is the review record, and hotlong and os-zhuang are requested. The seat readies and lands it only after that approval.