Repository navigation
Commit 5eb5400
ci(spec-shape-gate): install objectui through its pinned-build directories, packed from this commit (#24469)
Fixes #24424
Clause-②: no
## What was red
Every `Spec Shape Gate` run since objectui `749ed760`
(objectstack-ai/objectui#12957): step "Install objectui dependencies"
ran a bare `pnpm install --frozen-lockfile` in objectui, whose root
`package.json` now overrides every `@objectstack/*` package to
`file:node_modules/.cache/objectstack/NAME`, a directory only objectui's
`scripts/objectstack-pin.mjs build` fills. Reproduced locally against
objectui `4016370af3` (its `main` when this was measured): exit 254,
`ENOENT: no such file or directory, scandir
'.../objectui/node_modules/.cache/objectstack/client'`. Run
`39188135125` step 14 concluded `failure` with the annotation `Process
completed with exit code 254` (its raw log host answers 403 from this
container, so the annotation is the reading).
## The change
`.github/workflows/spec-shape-gate.yml`:
1. The objectstack-side install and build widen from the spec to the
packages objectui overrides. The names come from
`objectui/package.json`'s `pnpm.overrides`, the list the pin script
packs, and the selector is `--filter-prod=NAME...`: runtime edges only,
as the pin script's own build uses (a plain `...` filter pulls in the
client's dev closure of runtime, drivers and services). If no override
is found, that step exits 2.
2. A new step runs before the frozen install: objectui's `pnpm run
objectstack:build` with `OBJECTSTACK_ROOT` set to this checkout. That is
objectui's stand-in input: it packs every overridden package from this
tree into those directories, with no lockfile change. The step calls
objectui's script by name rather than by path. `check-self-test-wired`'s
live corpus maps every workflow `node PATH` to a file in THIS
repository, and its self-test went red on the path spelling at
`bfa828074` (exit 0 on BASE).
3. The `inject` step stays (measured below). Its comment now says what
it still adds.
`scripts/ci/spec-shape-gate.mjs`: two summary lines now name the subject
the compile reads, `@objectstack/spec` and every other `@objectstack/*`
package objectui installs. The self-test's pinned substring
(`type-checks against`) is unchanged.
No gate was added, no step skipped, and no `continue-on-error` set.
`report`'s exit-2 meaning is unchanged.
## The dispatch's hypotheses, measured
Readings at BASE `725a5b131`, objectui `4016370af3`, pnpm 10.31.0, node
22.22.0.
1. **The red is the bare frozen install failing with ENOENT on the cache
directory.** Confirmed, as above.
2. **`OBJECTSTACK_ROOT=TREE` packs every package and leaves the lockfile
unchanged.** Confirmed. Seven packages were packed from `725a5b1311ec`
in 15 s and the pin script's lockfile check passed. `pnpm install
--frozen-lockfile` then exited 0 in 7 s, and objectui's `git status`
stayed clean. `pnpm run setup` would pass the variable through too. But
`setup` is also THIS repository's script name, so the self-test-wired
corpus would expand it against our `package.json`. The build and the
install are therefore two named steps.
3. **`inject` becomes redundant.** On BASE it changes nothing: every
declaration file is identical, it made 0 substitutions, and it verified
32 consumers. The only differences between npm pack and pnpm pack output
are `package.json` (npm keeps the `prepare` script) and one nested
`src/migrations/entries/README.md`. It is not redundant, though: it is
the only range check of the spec's declared dependencies. A tarball
declaring `zod: ^4.7.0` against the store's `zod@4.6.7` made `inject`
exit 2 with nothing written, while the pin script's check passed the
same drift. It stays.
4. **A manifest change since objectui's pin makes the frozen install
refuse.** BASE has no drift. Across the seven packages, 0 fields changed
in `dependencies`, `optionalDependencies`, `peerDependencies`,
`peerDependenciesMeta` or `engines` over the 157 commits from objectui's
pin `2c9bf9430a` to BASE. The mechanism itself is **falsified**. I
mutated the packed spec manifest four ways: a new dependency name, peer
`ai: ^8.0.0`, `engines.node` at 24 or above (under objectui's
`engine-strict=true`), and `zod: ^4.7.0`. objectui's frozen install
exited 0 every time and linked the drifted manifest. Only the pin script
refuses, and only for the name class.
**How the gate reads the name class.** The pin step exits 1 with the pin
script's own `objectstack-pin` error annotation, which names the package
and the dependency. Install and compile are skipped, and `report` exits
2: no reading, never a pass. That is a red with no compile verdict, and
the remedy is objectui's: move its `.objectstack-sha` with
`scripts/bump-objectstack.sh` and commit the lockfile. It is neither a
shape break nor a registered retirement, because the registry matches
diagnostics and there are none. I propose no new registry kind: a
"known" reading of a compile that never ran is a skip, which this card's
ruling forbids. Nothing refuses peer, engines or range drift in the
other six packages. In that case the compile reads objectui's
lockfile-resolved dependencies, which is what objectui's own frozen
install does with the same build.
## Local end-to-end
I extracted the edited workflow's own `run:` texts from the YAML and
replayed them under `bash -eo pipefail`.
- objectstack side, in a detached worktree at BASE after the filtered
install: step 9 (install) exit 0 in 3.6 s; step 10 (build the seven)
exit 0 in 125 s.
- objectui side, in a throwaway clone at `4016370af3` with a fresh
`node_modules`: step 13 (`pnpm run objectstack:build`) exit 0 in 14.5 s;
step 14 (frozen install) exit 0 in 7.9 s; `inject` exit 0.
- Compile: `TURBO_FORCE=true pnpm type-check --continue --concurrency=2`
exited 0, with 81 of 81 tasks successful and 0 cached, in 16m16s on a
shared box. `report --status 0` on that log exited 0 ("type-checks
against"). Two registered retirements matched nothing and are listed as
such.
- Added CI time, measured locally on a shared box: 27 s for the six
non-spec builds (spec already built), about 15 s for the pin pack, and a
few seconds for the wider filtered install on a warm store. That is
under a minute on a job sized at about 13 minutes with a 45-minute
ceiling.
## Gates
Run at `eb080715a`, the head of this PR. The 51 commands `node
scripts/pm/dispatch-gates.mjs --commands` derives for this diff all
exited 0, each exit code captured before any pipe. `--ran`
reconciliation: "51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN". Selected
verdict lines:
- `pnpm check:spec-shape-gate`: `spec-shape-gate --self-test: 60/60
passed across 7 batteries`
- `node scripts/check-self-test-wired.mjs --self-test`: exit 0 (red at
`bfa828074` on the path spelling, see above)
- `pnpm check:pnpm-filter-targets`, `pnpm
check:workflow-step-name-quoting`, `pnpm check:nul-bytes`, `pnpm
check:entry-guard`, `pnpm check:bash32-floor`: exit 0
- Outside the derived set: `pnpm check:pnpm-flag-spellings` exit 0.
The gate's own `pull_request` run on this PR (path-filtered to this
workflow and the script) is the CI end-to-end reading.
## Acceptance notes
- `inject`'s tarball comes from `npm pack`; objectui's pinned build
comes from `pnpm pack`. They differ in `package.json` (npm keeps
`prepare`) and one nested README, and tsc reads neither. Observation
only.
- `check-self-test-wired`'s live corpus does not read a step's
`working-directory`, so a `node PATH` run inside the objectui checkout
reads as a path in this repository. This PR spells objectui's entry
point by script name instead. Observation only, no carrier.
- Triage reading 6259975511 on the card: #24168 merged as `725a5b1311`
(this PR's BASE), and its Release run refused at the full-battery check
because the newest schedule run at or before that version commit is red.
## 维护者速读(草稿)
**改了什么**
Spec Shape Gate 是每小时检查 objectui 能否在本仓当前提交上编译通过的门禁,这次改的是它安装 objectui
的方式:先在本仓构建 objectui 用到的全部 7 个 `@objectstack/*` 包,再调用 objectui 自己的
`objectstack:build` 脚本把它们打包进 objectui 期望的目录,最后照常冻结安装。以前只注入 spec 一个包,现在
objectui 编译时读到的 7 个包全部来自本次提交。
**为什么改**
objectui 改为按提交消费 `@objectstack/*`
之后,门禁原来的裸安装每次都失败(找不到缓存目录),门禁一直是红的,而发版门禁读这条结果。triage 读数 6259975511:next.4
已无法挽救,可发版的路径是本卡落地、新 main 上出现一次绿色的定时 Spec Shape Gate 运行,然后发 next.5。
**风险与代价(含回滚)**
每次运行大约多一分钟(多构建 6 个小包,外加一次打包)。如果本仓某次提交给这 7 个包新增或删除了运行时依赖,objectui
的打包脚本会拒绝,门禁变红(读作"无读数",不算通过),要等 objectui 升级它的 pin 并提交 lockfile
才能转绿。回滚:revert 本 PR,门禁回到现在的红色状态。
**席位意见**
**你要做的**
看一下本 PR 自己的 `Spec Shape Gate` pull_request 运行结论;同意的话批准合并(工作流文件属于 Tier
H,需要你亲手批准)。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent fb0d85b commit 5eb5400
2 files changed
Lines changed: 46 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | | - | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
205 | 206 | | |
206 | 207 | | |
207 | 208 | | |
208 | | - | |
209 | | - | |
210 | | - | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
211 | 218 | | |
212 | 219 | | |
213 | | - | |
214 | | - | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
215 | 230 | | |
216 | | - | |
217 | | - | |
| 231 | + | |
| 232 | + | |
218 | 233 | | |
219 | 234 | | |
220 | 235 | | |
| |||
238 | 253 | | |
239 | 254 | | |
240 | 255 | | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
241 | 272 | | |
242 | 273 | | |
243 | 274 | | |
| |||
254 | 285 | | |
255 | 286 | | |
256 | 287 | | |
257 | | - | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
258 | 292 | | |
259 | 293 | | |
260 | 294 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1135 | 1135 | | |
1136 | 1136 | | |
1137 | 1137 | | |
1138 | | - | |
| 1138 | + | |
1139 | 1139 | | |
1140 | 1140 | | |
1141 | 1141 | | |
1142 | 1142 | | |
1143 | | - | |
| 1143 | + | |
1144 | 1144 | | |
1145 | 1145 | | |
1146 | 1146 | | |
| |||
0 commit comments