Skip to content

Commit bb52434

Browse files
committed
release(ui-merge): gates, release notes and docs stop naming the deleted pin pieces (objectstack#25711, WIP)
- check-pnpm-filter-targets: the foreign-scope live assertion is tree-aware; without ui/ no committed filter names @object-ui/ (build-console.sh left). - pnpm-filter-targets: the @object-ui/ foreign entry states its new cause and when it retires (the PR that lands ui/). - collect-release-notes: section 3 reads a pinless ref instead of failing on the missing .objectui-sha. - bare-root-worklist: the two check-console-injection UNJUDGED rows are gone with the gate. - check-type-check-coverage: the @objectstack/console EXEMPT note names build-dist.sh. - dispatch-gates self-test: the prerelease-pin-watch literal specimen leaves. - cut-rc builds the Console before the version commit; release.yml and cut-rc comments name console:build; packages/console README describes the in-workspace build. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0149BHSXfCdQywGaLdpRAtWe
1 parent 5c49f1b commit bb52434

9 files changed

Lines changed: 86 additions & 75 deletions

‎.github/workflows/cut-rc.yml‎

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ name: Cut RC
3333
# ---------------------------------------------------------
3434
# There is no objectui pin to read. The Console source is `ui/apps/console` in
3535
# this repository (@object-ui/console, ruling D1 「同一个版本号组」): the snapshot
36-
# above freezes it together with the spec it builds against, `pnpm run build`
37-
# builds it and `@objectstack/console` copies its dist, and the 39 published
36+
# above freezes it together with the spec it builds against, `pnpm run
37+
# console:build` builds it and copies its dist into `@objectstack/console`
38+
# (packages/console/build-dist.sh), and the 39 published
3839
# @object-ui/* packages are members of the one Changesets `fixed` group, so the
3940
# version pass below numbers them with everything else. Nothing here reaches
4041
# into another repository, and nothing moves a pin, because neither exists.
@@ -272,14 +273,18 @@ jobs:
272273
- name: Install dependencies
273274
run: pnpm install --frozen-lockfile
274275

275-
# The whole workspace, both scopes: @object-ui/console builds against this
276-
# snapshot's @objectstack/* (`workspace:^`), and `@objectstack/console#build`
277-
# (root turbo.json) copies its dist with the TRACKED repo-root
278-
# sdui.manifest.json and runs the single-zod canary on what it ships
279-
# (packages/console/build-dist.sh). `pnpm run release` below builds again,
280-
# as a turbo cache hit.
276+
# The whole workspace, both scopes, then the Console: @object-ui/console
277+
# builds against this snapshot's @objectstack/* (`workspace:^`), and
278+
# `@objectstack/console#build:dist` (root turbo.json) copies its dist with
279+
# the TRACKED repo-root sdui.manifest.json and runs the single-zod canary on
280+
# what it ships (packages/console/build-dist.sh). Built HERE, before the
281+
# version commit, so a Console that cannot build stops the cut before
282+
# anything is written; `pnpm run release` below builds both again, as turbo
283+
# cache hits.
281284
- name: Build the workspace (both scopes, the Console included)
282-
run: pnpm run build
285+
run: |
286+
pnpm run build
287+
pnpm run console:build
283288
284289
# ────────────────────────────────────────────────────────────────────────
285290
# PRE-VERSION GATES. Every one of these reads `.changeset/*`, so all of them

‎.github/workflows/release.yml‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,10 +1840,11 @@ jobs:
18401840
#
18411841
# The Console is a workspace package now: `ui/apps/console`
18421842
# (@object-ui/console) builds against this tree's @objectstack/* through
1843-
# `workspace:^`, and `@objectstack/console#build` (root turbo.json) copies
1844-
# that dist with the tracked sdui.manifest.json, so the `pnpm run build`
1845-
# below builds it with everything else. The pin-currency gate, the
1846-
# vendored-dist cache keyed on `.objectui-sha`, its SHA stamp check and
1843+
# `workspace:^`, and `@objectstack/console#build:dist` (root turbo.json)
1844+
# copies that dist with the tracked sdui.manifest.json; `pnpm run release`
1845+
# runs it (`pnpm run console:build`) after the build below. The
1846+
# pin-currency gate, the vendored-dist cache keyed on `.objectui-sha`,
1847+
# its SHA stamp check and
18471848
# its spec-injection check are gone with the pin: each answered "was the
18481849
# Console built from the objectui commit, and against the spec, this
18491850
# release names", and both are true by construction when the Console
@@ -1948,8 +1949,9 @@ jobs:
19481949

19491950
# ──────────────────────────────────────────────────────────────────────
19501951
# The publish itself. `pnpm run release` = build (both scopes; the turbo
1951-
# cache makes it the build above) + scripts/release-publish.sh, which is `changeset publish` followed by ONE
1952-
# atomic `git push origin --tags` (#2191: the action's concurrent per-tag
1952+
# cache makes it the build above) + console:build (the Console dist into
1953+
# packages/console) + scripts/release-publish.sh, which is `changeset
1954+
# publish` followed by ONE atomic `git push origin --tags` (#2191: the action's concurrent per-tag
19531955
# pushes raced GitHub's ref backend and lost ~half the tags).
19541956
#
19551957
# changesets/action is NOT used here, and that is deliberate: handed a

‎packages/console/README.md‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
**Prebuilt Console SPA, version-locked to the framework release that ships it.**
44

55
This package contains nothing but a prebuilt `dist/` directory: the static
6-
assets of the ObjectStack runtime Console, baked at the commit of
7-
[`objectstack-ai/objectui`](https://github.com/objectstack-ai/objectui)
8-
recorded in [`.objectui-sha`](../../.objectui-sha) of this framework release.
6+
assets of the ObjectStack runtime Console, built from
7+
[`ui/apps/console`](../../ui/apps/console) (`@object-ui/console`) in the same
8+
commit of this repository as the framework release that ships it.
99

1010
You never install it directly. `@objectstack/cli` declares it as a
1111
dependency, and both ship at the same version from the Changesets `fixed`
@@ -24,8 +24,8 @@ in sync.
2424

2525
| | `@object-ui/console` | `@objectstack/console` |
2626
|---|---|---|
27-
| Repo | [`objectstack-ai/objectui`](https://github.com/objectstack-ai/objectui) | [`objectstack-ai/objectstack`](https://github.com/objectstack-ai/objectstack) |
28-
| Role | Standalone Console SPA on its own release cadence | Prebuilt SPA frozen at the SHA this framework release was tested against |
27+
| Source | `ui/apps/console` in this repository | a copy of that build's `dist/` |
28+
| Role | The Console SPA, versioned with the framework in the one `fixed` group | Prebuilt SPA shipped with the framework release it was built with |
2929
| Use | Cloud overlays, advanced users, anyone consuming Console directly | What every `@objectstack/cli` install gets by default |
3030

3131
The framework CLI's `resolveConsolePath()` (in
@@ -46,20 +46,20 @@ objectui edits — not a package resolution. Cloud and objectos Docker images
4646
overlay their own Console build into `@objectstack/console`'s `dist/` — not
4747
into any `@object-ui/console` directory.
4848

49-
## Updating
49+
## Building
5050

51-
1. Run `scripts/bump-objectui.sh` (or `scripts/bump-objectui.sh <sha>`) at
52-
the repo root to update `.objectui-sha`. Prefer `pnpm objectui:refresh`,
53-
which bumps *and* rebuilds in one step.
54-
2. Opening the PR runs CI's **Console Pin Gate**, which clones objectui at
55-
the new SHA, builds `@object-ui/console` against this tree's
56-
`@objectstack/client`, and runs `pnpm check:console-sha`. A pin that
57-
cannot build fails the PR rather than the release.
58-
3. CI runs `scripts/build-console.sh` again before publish, which clones
59-
objectui at the pinned SHA, builds `@object-ui/console`, and copies
60-
`dist/` into this package.
61-
4. `pnpm publish` ships it at the same version as every other package in
62-
the Changesets `fixed` group.
51+
1. `pnpm console:build` at the repo root runs turbo's
52+
`@objectstack/console#build:dist`, which first builds `@object-ui/console`
53+
(and its closure) against this tree's `@objectstack/*` through
54+
`workspace:^`, then runs [`build-dist.sh`](./build-dist.sh): it copies
55+
`ui/apps/console/dist` here, puts the tracked repo-root
56+
`sdui.manifest.json` over `dist/sdui.manifest.json`, and fails unless the
57+
bundle carries exactly one zod instance.
58+
2. `pnpm run release` runs it after the workspace build and before
59+
`changeset publish`, so the publish ships it at the same version as every
60+
other package in the Changesets `fixed` group.
61+
62+
There is no pin to bump: a Console change is an ordinary change under `ui/`.
6363

6464
The `dist/` directory is **not** committed — it's a CI publish artifact
6565
only.

‎scripts/check-pnpm-filter-targets.mjs‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,17 @@ export function selfTest() {
485485
ok(`the live tree yields occurrences (found ${live.occurrences.length})`, live.occurrences.length > 50);
486486
ok(`and judges a real share of them (judged ${live.judged.length})`, live.judged.length > 30);
487487
ok(`and the checked-in tree is clean (dead: ${live.dead.map((d) => d.value).join(', ') || 'none'})`, live.dead.length === 0);
488-
ok('and the foreign scope is present and unjudged, not silently missing', (live.unjudgedByKind.foreign ?? 0) > 0);
488+
// The foreign scope's live population is objectui's own scripts under `ui/`. Its
489+
// first one, scripts/build-console.sh, left with the objectui pin (objectstack#25711),
490+
// so a tree without `ui/` names no `@object-ui/` filter at all and the zero there is the
491+
// reading, not a blind scan; a tree with `ui/` must still show them unjudged.
492+
const holdsUi = existsSync(join(root, 'ui', 'package.json'));
493+
ok(
494+
holdsUi
495+
? 'and the foreign scope is present and unjudged, not silently missing'
496+
: 'and, with no ui/ in this tree, no committed filter names the foreign scope',
497+
holdsUi ? (live.unjudgedByKind.foreign ?? 0) > 0 : (live.unjudgedByKind.foreign ?? 0) === 0,
498+
);
489499
ok(
490500
'the self-exemption is exactly the three files that own the rule — never a fourth',
491501
RULE_OWNING_FILES.length === 3

‎scripts/check-type-check-coverage.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ const DEBT = {
853853
// nature changes, the RECONCILED direction forces this entry out.
854854
const EXEMPT = {
855855
'@objectstack/console':
856-
'Published objectui build artifact -- package.json/README/CHANGELOG plus a dist/ pulled in by `pnpm objectui:refresh`. No TypeScript sources, no tsconfig; the sources are type-checked in the objectui repo.',
856+
'Published Console build artifact -- package.json/README/CHANGELOG plus a dist/ copied from ui/apps/console by its own build:dist (build-dist.sh, plain bash; objectstack#25711). No TypeScript sources, no tsconfig; the sources are type-checked as @object-ui/console under ui/.',
857857
'@objectstack/skills':
858858
'Published skills catalog -- package.json/README/CHANGELOG plus a dist/skills tree copied from the repository root skills/** by its own build (scripts/sync-catalog.mjs, plain node). No TypeScript sources, no tsconfig; the catalog is markdown and JSON, judged by the skill gates over skills/**.',
859859
};

‎scripts/collect-release-notes.sh‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
# 2. The changesets consumed by the release (full text — the best prose for
1010
# items that have one).
1111
# 3. The objectui (Console UI) commit range, derived from the .objectui-sha
12-
# pin at each ref.
12+
# pin at each ref. After objectstack#25711 no ref carries a pin (the
13+
# Console is built from ui/), and the section says so instead.
1314
# 4. The cloud (control plane) commits inside the release's time window.
1415
# Cloud is not pinned by the framework (it tracks it via link: deps and
1516
# versions independently), so the window between the two refs' commit
@@ -428,14 +429,23 @@ fi
428429
echo "## 3. Console UI (objectui) — pin range"
429430
echo
430431

432+
# The pin is gone from every ref after objectstack#25711: the Console is built
433+
# from this tree's ui/, so its commits are already in section 1. A range across
434+
# that boundary starts at the last pin and ends at the subtree import, and only
435+
# the objectui repository holds the commits between the two.
431436
prev_sha=$(git show "${PREV_REF}:.objectui-sha" 2>/dev/null || true)
432-
new_sha=$(git show "${NEW_REF}:.objectui-sha" 2>/dev/null || cat .objectui-sha)
437+
new_sha=$(git show "${NEW_REF}:.objectui-sha" 2>/dev/null || true)
433438

434439
echo "- previous pin: \`${prev_sha:-<none>}\`"
435-
echo "- this release: \`${new_sha}\`"
440+
echo "- this release: \`${new_sha:-<none>}\`"
436441
echo
437442

438-
if [[ -z "$prev_sha" ]]; then
443+
if [[ -z "$new_sha" ]]; then
444+
echo "_No objectui pin at ${NEW_REF}: the Console is built from ui/ in this tree (objectstack#25711), so its commits are in section 1._"
445+
if [[ -n "$prev_sha" ]]; then
446+
echo "_The last pin was \`${prev_sha}\`: the objectui commits from it up to the ui/ subtree import are not in section 1; read them in objectstack-ai/objectui._"
447+
fi
448+
elif [[ -z "$prev_sha" ]]; then
439449
echo "_No .objectui-sha at ${PREV_REF}; cannot compute the range._"
440450
elif [[ "$prev_sha" == "$new_sha" ]]; then
441451
echo "_Console pin unchanged — no objectui delta in this release._"

‎scripts/pm/bare-root-worklist.mjs‎

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,28 +1546,6 @@ export const UNJUDGED = new Map([
15461546
+ 'at :189-:193 from the `for (const root of ROOTS)` at :462, for every `.md` file under it '
15471547
+ 'minus the entry\'s own `exclude` list',
15481548
}],
1549-
['scripts/check-console-injection.mjs distDir packages', {
1550-
population: false,
1551-
base: '91f65c4ea',
1552-
why: 'the word is a `join()` path COMPONENT at check-console-injection.mjs:940 — the gate '
1553-
+ 'assembles the console dist directory from four bare single-segment words, so the extractor '
1554-
+ 'sees the top-level one and nothing else. It never walks that root: `evaluate` at :247 opens '
1555-
+ 'the index file at :252, the stamp beside it at :268, and every JavaScript asset directly '
1556-
+ 'inside that directory\'s assets child at :269 — `readBundle` in console-spec-probes.mjs, '
1557-
+ 'non-recursive. Surfaced by the #17057 property widening because the component sits inside '
1558-
+ 'the `distDir` property of the argv object, which the recogniser now reads',
1559-
}],
1560-
['scripts/check-console-injection.mjs specDir packages', {
1561-
population: false,
1562-
base: '91f65c4ea',
1563-
why: 'the same shape one line down, at check-console-injection.mjs:941: a `join()` component of '
1564-
+ 'the spec package directory, assembled from bare words. The gate reads that package\'s '
1565-
+ 'manifest and the built JavaScript its `exports` map points at — `readSpecBlob` in '
1566-
+ 'console-spec-probes.mjs, reached at :348 — never an arbitrary file under the top-level '
1567-
+ 'root. ⚠️ Both of this gate\'s real populations are themselves invisible to the derivation, '
1568-
+ 'for the DIFFERENT reason that they are assembled rather than spelled; that is a fact this '
1569-
+ 'note records and not a verdict on what, if anything, should be declared for them',
1570-
}],
15711549
['scripts/check-doc-frontmatter.mjs ROOTS docs', {
15721550
population: false,
15731551
base: '91f65c4ea',

‎scripts/pm/dispatch-gates.self-test.mjs‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,10 @@ export function selfTest({ tier = 'full' } = {}) {
658658
// sources: `pr-automation.yml` (the `--base` gates), `ci.yml` (the shard
659659
// attestation), `engine-split-metric.yml` (`--days 90`),
660660
// `required-set-patrol.yml` (a complete argv behind a continuation and a
661-
// redirection), `prerelease-pin-watch.yml` (`--verbose 2>&1`). The live half
662-
// at the end of the block re-reads them from the workflows themselves.
661+
// redirection), `prerelease-pin-watch.yml` (`--verbose 2>&1`; that workflow
662+
// left with the objectui pin, objectstack#25711, and its row stays as a
663+
// fixture of the shape). The live half at the end of the block re-reads the
664+
// others from the workflows themselves.
663665
const keyWf = [
664666
'jobs:',
665667
' gates:',
@@ -1002,10 +1004,11 @@ export function selfTest({ tier = 'full' } = {}) {
10021004
'scripts/check-adr-0087-registration.mjs', 'scripts/check-changeset-no-major.mjs']
10031005
.every((script) => valueBearing.some((i) => i.script === script)),
10041006
);
1007+
// The card named three; the third, `scripts/check-prerelease-pin-watch.mjs
1008+
// --verbose`, left with the objectui pin it watched (objectstack#25711).
10051009
t(
1006-
'⭐ …and the three the card called value-bearing that are really LITERAL render as runnable commands instead',
1007-
['scripts/check-engine-split-ratio.mjs --days 90', 'scripts/check-required-contexts.mjs --verify-required-set',
1008-
'scripts/check-prerelease-pin-watch.mjs --verbose']
1010+
'⭐ …and the two the card called value-bearing that are really LITERAL render as runnable commands instead',
1011+
['scripts/check-engine-split-ratio.mjs --days 90', 'scripts/check-required-contexts.mjs --verify-required-set']
10091012
.every((key) => direct.some((i) => i.check === key && i.argvVariables.length === 0)),
10101013
);
10111014
t(

‎scripts/pnpm-filter-targets.mjs‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,21 @@ const HERE = dirname(fileURLToPath(import.meta.url));
104104
*
105105
* Declared, never inferred: a new foreign scope has to be added here
106106
* deliberately, which is the difference between a documented exemption and a
107-
* silent hole. `scripts/build-console.sh` runs its `@object-ui/console` filters
108-
* inside `$BUILD_ROOT` -- a checkout of `objectstack-ai/objectui` at the SHA
109-
* pinned in `.objectui-sha` -- never against this workspace, so resolving those
110-
* against this tree would be asking the wrong root.
107+
* silent hole. The `@object-ui/` entry's first cause is gone: it was
108+
* `scripts/build-console.sh`, which ran its `@object-ui/console` filters inside a
109+
* checkout of `objectstack-ai/objectui` at the SHA pinned in `.objectui-sha`, and
110+
* both left with the pin (objectstack#25711). It stays declared until the objectui
111+
* subtree lands under `ui/` (sub-issue 5 of objectstack#25677): before that a
112+
* filter naming an `@object-ui/` package matches nothing in this tree by design.
113+
* ⛔ Retire the entry in the PR that lands `ui/`, where every such name becomes a
114+
* workspace package this gate can judge.
111115
*/
112116
export const FOREIGN_SCOPES = [
113117
{
114118
scope: '@object-ui/',
115119
reason:
116-
'the objectui repo (objectstack-ai/objectui); scripts/build-console.sh runs these '
117-
+ 'filters inside that checkout, not this workspace',
120+
'the objectui tree, which this workspace holds under ui/ only once the subtree import '
121+
+ 'of objectstack#25677 lands',
118122
},
119123
];
120124

@@ -451,9 +455,8 @@ export function extractFilters(text) {
451455
* THIS workspace naming a package that does not exist.
452456
*
453457
* The `cd` bail-out is the load-bearing one: a command that changes directory
454-
* may be filtering against another root entirely (`scripts/build-console.sh`
455-
* does exactly that, in the objectui checkout), and this function has no way to
456-
* know which. Unknown root, no verdict.
458+
* may be filtering against another root entirely, and this function has no way
459+
* to know which. Unknown root, no verdict.
457460
*
458461
* @param {string} command
459462
* @param {string} cwd

0 commit comments

Comments
 (0)