Skip to content

Commit 15f5e27

Browse files
committed
ci(sdui): retire the per-package SDUI manifest records; CI's regeneration holds freshness (#26137)
Build & E2E UI regenerates sdui.manifest.json and compares it with the committed bytes (#26315), on pull_request and on the merge queue's combined tree. That makes the per-package source digests under scripts/sdui-manifest.sources/ (#26051) redundant, and they were the reason two ui PRs on one registry package conflicted even when neither moved the manifest. - check-sdui-manifest: check 3 in-tree (the per-package digests) is gone. The in-tree leg keeps shape, tamper and the inTree block, and a record that still carries `inTree.registryRecords` is RED as a retired layout. The watch hints drop ui/packages/** and the records directory. Self-test: the nine digest rows go with the code they tested; two rows pin the new boundary (the per-package record is RED; a run whose artefact did not move leaves the record as it was). Floor 29 -> 21. - gen-sdui-manifest-node: no digests, no index refusal, no per-package records; it no longer imports the gate. The record note is rewritten. - scripts/sdui-manifest.sources/ is deleted and the record regenerated (artefact byte-identical, sha256 1f6e1ccb925a). - check-changeset-no-major, lint.yml, ci.yml and releases-maintenance.md stop naming the per-package records. - AGENTS.md: the manifest paragraph still described the retired objectui pin (objectui:* scripts, "check-sdui-manifest reds until you do"). It now names the in-tree command and the CI step, line-neutral (5 lines). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6SEitNngAMugGbuJHWsDS
1 parent 77a52cf commit 15f5e27

34 files changed

Lines changed: 198 additions & 687 deletions

‎.github/workflows/ci.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4148,12 +4148,12 @@ jobs:
41484148
# 81bba6c3f), then it enumerates the registry under plain Node (~8 s; ~6 s
41494149
# for the whole run when nothing moved). It serialises through the
41504150
# @objectstack/sdui-parser the step above built, so a parser edit moves
4151-
# this verdict too, which no committed digest does. On merge_group it runs
4152-
# on the queue's combined tree, the one run that sees two entries' effect
4153-
# on the manifest together. Only the artefact is compared: the records the
4154-
# generator rewrites beside it are held by `check-sdui-manifest` in
4155-
# lint.yml. The Console build below reads the registry through its src/
4156-
# aliases, so the dist this step builds does not reach it.
4151+
# this verdict too. On merge_group it runs on the queue's combined tree,
4152+
# the one run that sees two entries' effect on the manifest together.
4153+
# Only the artefact is compared: the record the generator rewrites beside
4154+
# it is held by `check-sdui-manifest` in lint.yml. The Console build below
4155+
# reads the registry through its src/ aliases, so the dist this step
4156+
# builds does not reach it.
41574157
- name: The committed SDUI manifest is the one this tree generates
41584158
run: |
41594159
node scripts/gen-sdui-manifest-node.mjs

‎.github/workflows/lint.yml‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,11 @@ jobs:
966966
# repo-root `sdui.manifest.json` is absent or unreadable, so nothing in
967967
# the production path ever says "the gate lost its whitelist" — this step
968968
# is the thing that notices. Offline record checks only (existence, shape,
969-
# sha256 vs the provenance record, and with no pin each registry
970-
# package's source digest vs its record): the regenerate-and-compare half
971-
# runs where the registry is built, as ci.yml's Build & E2E UI step "The
972-
# committed SDUI manifest is the one this tree generates" (#26137), on
973-
# pull_request and on the merge queue's combined tree. Unfiltered:
974-
# filtering it to the artefact would go dormant on exactly the PR that
975-
# moves the artefact's inputs and not the artefact.
969+
# sha256 vs the provenance record): freshness is decided where the
970+
# registry is built, by ci.yml's Build & E2E UI step "The committed SDUI
971+
# manifest is the one this tree generates" (#26137), on pull_request and
972+
# on the merge queue's combined tree. Unfiltered: it builds nothing and
973+
# runs in seconds, and an absent artefact is the failure it exists for.
976974
# Direct invocation per the GATE INVOCATION IDIOM at the top of this file.
977975
- name: SDUI manifest is present, intact and fresh at the objectui pin
978976
id: sdui-manifest-is-present-intact-and-fresh

‎AGENTS.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ The Studio/Console UI lives in this workspace under `ui/` (`@object-ui/*`; the C
159159
and `ui/AGENTS.md` adds that tree's own rules to this file's. `pnpm console:build` builds the Console and copies its
160160
dist into `packages/console/` (`packages/console/build-dist.sh`). ⛔ Never hand-edit `packages/console/dist/`.
161161

162-
**Moving the pin has a second half: regenerate the committed manifest** — `pnpm objectui:build`, then
163-
`node scripts/gen-sdui-manifest-node.mjs`, which reads objectui's BUILT tree at the pin (never an npm install, whose
164-
version string names an older commit) and takes no arguments; `scripts/check-sdui-manifest.mjs` reds until you do.
165-
`objectui:bump` and `objectui:refresh` print the step, and the console build ships that same tracked file in
166-
`packages/console/dist/`. Full procedure: `docs/releases-maintenance.md`.
162+
**A registry change has a second half: regenerate the committed manifest** with
163+
`node scripts/gen-sdui-manifest-node.mjs`, which builds the registry under `ui/`, enumerates it from `ui/apps/console`
164+
(never an npm install) and takes no arguments; commit what it writes. CI's `Build & E2E UI` runs it too and fails
165+
when the committed `sdui.manifest.json` differs, the merge queue's combined tree included, and the console build
166+
ships that same tracked file in `packages/console/dist/`. Full procedure: `docs/releases-maintenance.md`.
167167

168168
**Fast iteration on `ui/` src (no rebuild loop):** run the Console dev server —
169169
`pnpm --filter @object-ui/console dev` (Vite on **:5180**, HMR). Its `/api` proxy targets

‎docs/releases-maintenance.md‎

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,11 @@ ships the Console from the same commit as the spec it builds against.
5555
> root `.changeset/` before the first joint Version PR is #25831. New frontend
5656
> changesets go in the root `.changeset/`.
5757
58-
#### After a registry change: regenerate the committed manifest (#12924, #17735, #25712, #26051)
58+
#### After a registry change: regenerate the committed manifest (#12924, #17735, #25712, #26137)
5959

6060
The repo-root `sdui.manifest.json` (ADR-0080, the Console's public-tier component
61-
manifest), its provenance record `scripts/sdui-manifest.record.json` and one record
62-
per registry package under `scripts/sdui-manifest.sources/` are generated, and one
63-
command writes them:
61+
manifest) and its provenance record `scripts/sdui-manifest.record.json` are
62+
generated, and one command writes them:
6463

6564
```bash
6665
node scripts/gen-sdui-manifest-node.mjs # no arguments
@@ -69,31 +68,26 @@ node scripts/gen-sdui-manifest-node.mjs # no arguments
6968
It builds the registry packages under `ui/packages/`, enumerates them from
7069
`ui/apps/console` under plain Node, and serializes them through
7170
`@objectstack/sdui-parser` (it needs `packages/sdui-parser/dist`:
72-
`pnpm --filter @objectstack/sdui-parser build`). Each package record is one line:
73-
a digest of that package's own `src/` and the `sha256` of the artefact it was
74-
verified against. A run rewrites only the records whose line changed, so a PR that
75-
edits one registry package re-records that package alone; the shared record moves
76-
only when the artefact does, and then every package record names the new `sha256`.
77-
78-
A required lint step reads the tracked files on **every PR**:
79-
`node scripts/check-sdui-manifest.mjs` checks the shape, the `sha256` against the
80-
record, and recomputes each package's source digest from the index. A PR that edits
81-
a registry package's source without regenerating goes red there, naming the package,
82-
and the failure text prints the regeneration call. Two PRs that edit different
83-
registry packages touch different record files and do not conflict; two that edit
84-
the same package, or a PR that changes the artefact, still conflict once, and the
85-
later one merges `main` and re-runs the command. ⛔ There is no npm install route to the manifest; that was
86-
deleted by ruling 丙 on #17735.
87-
88-
CI also regenerates the manifest and compares it with the committed bytes (#26137):
71+
`pnpm --filter @objectstack/sdui-parser build`). The record moves only when the
72+
artefact does, so a PR that does not change the manifest touches neither file.
73+
⛔ There is no npm install route to the manifest; that was deleted by ruling 丙 on
74+
#17735.
75+
76+
CI regenerates the manifest and compares it with the committed bytes (#26137):
8977
the `Build & E2E UI` step "The committed SDUI manifest is the one this tree
9078
generates" runs the same command after the registry is built, on every PR that
9179
touches `ui/`, one of the seven packages objectui consumes (the parser among them)
9280
or the manifest's own files, and again on the merge queue's combined tree. A
93-
difference fails the step with the diff and the command to run. That covers what
94-
the source digests cannot see: an edit to `@objectstack/sdui-parser`, to a package
95-
the registry imports, and two queued PRs whose effect on the manifest only shows
96-
together.
81+
difference fails the step with the diff and the command to run. Two PRs conflict
82+
on the manifest only when both change it, and the later one merges `main` and
83+
re-runs the command; two queued PRs whose effect on the manifest only shows
84+
together fail in the queue.
85+
86+
A required lint step, `node scripts/check-sdui-manifest.mjs`, reads the tracked
87+
files on **every PR**: the artefact is present and is a component manifest, and
88+
its `sha256` and component count are the record's. It builds nothing, so it does
89+
not judge freshness. (The per-package source records under
90+
`scripts/sdui-manifest.sources/` that it used to recompute, #26051, are retired.)
9791

9892
**One producer, one artefact.** `packages/console/build-dist.sh` copies the tracked
9993
`sdui.manifest.json` into `packages/console/dist/`, so the published console carries the
@@ -234,9 +228,9 @@ What it does, in order:
234228
re-reads `main`, so **`main` may keep moving for the whole run**.
235229
2. Builds the workspace, both scopes, then the Console (`pnpm run build`, then
236230
`pnpm run console:build`) from that snapshot. The dist carries the tracked
237-
`sdui.manifest.json`, whose freshness the required lint job already held on the
238-
PR that changed it. A Console that cannot build stops the cut before anything is
239-
written.
231+
`sdui.manifest.json`, whose freshness the required `Build & E2E UI` job already
232+
held on the PR that changed it and in the merge queue. A Console that cannot build
233+
stops the cut before anything is written.
240234
3. Runs the gates that read `.changeset/*`, before versioning consumes it.
241235
4. Runs `pnpm run version` — the repo script, never a bare `changeset version` —
242236
and **fails unless the computed version equals the one you typed**.

‎scripts/check-changeset-no-major.mjs‎

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,9 +1365,8 @@ export function publishedSourceOwners(path, manifestOf) {
13651365
// packed output — one path — and never which files it copies: the day the
13661366
// console build ships a second tracked file, this leg sees it with no edit
13671367
// here, and the day it stops copying the manifest, the leg stops claiming it.
1368-
// `scripts/sdui-manifest.record.json` and the per-package records under
1369-
// `scripts/sdui-manifest.sources/` are measured OUT for that reason rather than
1370-
// by choice: the build does not copy them, so they are not part of the shipped
1368+
// `scripts/sdui-manifest.record.json` is measured OUT for that reason rather
1369+
// than by choice: the build does not copy it, so it is not part of the shipped
13711370
// artefact.
13721371
//
13731372
// ⚠️ Residual, stated rather than implied: the reader understands the plain
@@ -4876,8 +4875,8 @@ function selfTest() {
48764875
`this repository's ${PACKED_COPY_BUILD_SCRIPTS[0]} copies the repo-root sdui.manifest.json into packages/console/dist/ as read by this leg — got ${JSON.stringify(realPairs)}`,
48774876
);
48784877
assert(
4879-
!realPairs.some((p) => p.source === 'scripts/sdui-manifest.record.json' || p.source.startsWith('scripts/sdui-manifest.sources/')),
4880-
`measured, not chosen: the real build ships neither the manifest record nor a package record — got ${JSON.stringify(realPairs)}`,
4878+
!realPairs.some((p) => p.source === 'scripts/sdui-manifest.record.json'),
4879+
`measured, not chosen: the real build does not ship the manifest record — got ${JSON.stringify(realPairs)}`,
48814880
);
48824881

48834882
// ── The owner of a destination ────────────────────────────────────────
@@ -4957,21 +4956,19 @@ function selfTest() {
49574956
const no = levelOf(copyRepo({ head: { ...PR22812, '.changeset/console-bbbb.md': changeset([[CONSOLE, 'patch']]) } }), declaredNo);
49584957
assert(no.result.verdict === 'none-clean' && no.exitCode === 0, `the manifest moved under \`Clause-②: no\` + \`none\` is unaffected — got ${no.result.verdict} / ${no.exitCode}`);
49594958

4960-
// The records move with regeneration but ship nothing: the shared one, and
4961-
// the one-line record of the registry package a ui PR re-recorded.
4959+
// The record moves with regeneration but ships nothing.
49624960
const recordOnly = levelOf(
49634961
copyRepo({
49644962
head: {
49654963
'scripts/sdui-manifest.record.json': '{"objectuiSha":"bbbb"}\n',
4966-
'scripts/sdui-manifest.sources/plugin-grid.json': '{"package":"ui/packages/plugin-grid"}\n',
49674964
'.changeset/console-bbbb.md': changeset([[CONSOLE, 'patch']]),
49684965
},
49694966
}),
49704967
yesWidening,
49714968
);
49724969
assert(
49734970
recordOnly.touched.packages.length === 0 && recordOnly.touched.unreadable.length === 0 && recordOnly.result.verdict === 'clean',
4974-
`control: the records alone move no published file — got ${JSON.stringify(recordOnly.touched)} / ${recordOnly.result.verdict}`,
4971+
`control: the record alone moves no published file — got ${JSON.stringify(recordOnly.touched)} / ${recordOnly.result.verdict}`,
49754972
);
49764973

49774974
// #4690 on this leg: a build script that is THERE but yields no copy is

0 commit comments

Comments
 (0)