From a1d7030269379fc43c96d06b85500514165c1338 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 08:54:08 +0000 Subject: [PATCH 1/3] fix(cli): catch the app-generator lucide-react range up to the workspace The routed temp app's generated manifest declared lucide-react at ^1.29.0 while all 22 sibling manifests that declare it had moved to ^1.31.0, so a generated app asked npm for an icon library older than the one every @object-ui/* package it installs alongside was built against. app-generator.test.ts derives its expectation from the in-repo range, so the drift was caught -- both pins were red. They just went red too late to stop anything: the dependency PR merged while those shards were still running, and the failure then surfaced on the merge ref of every unrelated open PR. The other 12 anchored ranges were swept against the same dependabot batch and are all in sync. Deriving the value rather than quoting it was considered and rejected; the reasoning is recorded at the call site. Fixes #4968 Co-authored-by: Claude --- .../cli-app-generator-lucide-range-4968.md | 27 +++++++++++++++++++ packages/cli/src/utils/app-generator.ts | 19 ++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 .changeset/cli-app-generator-lucide-range-4968.md diff --git a/.changeset/cli-app-generator-lucide-range-4968.md b/.changeset/cli-app-generator-lucide-range-4968.md new file mode 100644 index 0000000000..ca32e4ed0c --- /dev/null +++ b/.changeset/cli-app-generator-lucide-range-4968.md @@ -0,0 +1,27 @@ +--- +'@object-ui/cli': patch +--- + +The routed temp app's generated manifest now asks for the same `lucide-react` range this repo installs. + +`utils/app-generator.ts` writes the routed variant's `dependencies` with two +quoted third-party ranges, and `lucide-react` had fossilised a minor behind the +22 sibling manifests that declare it: the generated manifest said `^1.29.0` +while the repo had moved to `^1.31.0`. A generated app therefore asked npm for +an icon library older than the one every `@object-ui/*` package it installs +alongside was built against. + +The drift was not silent — `app-generator.test.ts` derives its expectation from +the in-repo range precisely so a bump on one side and not the other fails a +test, and both of its pins were red. What went wrong is that they went red too +late to stop anything: the dependency PR that moved the repo range merged while +those shards were still running, so the failure surfaced on `main` and then on +the merge ref of every unrelated open PR. The range is now caught up; the +reporting hole and the merge-ordering hole are filed separately (objectui#4968). + +The remaining eleven anchored ranges were swept against the same dependabot +batch and are all in sync, so this is the batch's only consumer-side follow-up. +Deriving the value from the workspace instead of quoting it was considered and +rejected: nine of the thirteen anchored ranges quote the repo root manifest, +which is not published with this CLI, so no single derivation can serve the +table and a bespoke one for this one name would leave the class untouched. diff --git a/packages/cli/src/utils/app-generator.ts b/packages/cli/src/utils/app-generator.ts index 8d5e996964..5e6c26238d 100644 --- a/packages/cli/src/utils/app-generator.ts +++ b/packages/cli/src/utils/app-generator.ts @@ -177,6 +177,23 @@ function buildAppDependencies(): Record { * with an unsatisfiable import. Declaring it at the producer is the fix — the * alias becomes a workspace convenience rather than the only thing holding the * import up. + * + * Both ranges here are QUOTED from this repo, per the objectui#3742 / + * objectui#3754 anchoring discipline: `react-router-dom` from the root + * manifest, `lucide-react` from the sibling manifests that declare it (the root + * does not). `app-generator.test.ts`'s `DEPENDENCY_ANCHORS` names the anchor for + * each and fails when a bump on either side leaves this file behind — which is + * the whole reason the values are allowed to be literals at all. + * + * That gate is not decoration; it has fired. objectui#4968: a dependabot bump + * moved `lucide-react` across all 22 sibling manifests and this literal stayed + * a minor behind, so the pin went red on every open PR's merge ref until the + * literal caught up. Deriving the value instead was considered and rejected in + * that PR — 9 of the 13 anchored ranges quote the repo ROOT manifest, which is + * not published with this CLI, so there is no one derivation the whole table + * could share and a bespoke one for this single name would buy nothing. The + * durable cure is upstream of this file: the shards carrying the gate have to + * finish before a dependency PR can merge. */ function buildRoutedAppDependencies(): Record { const range = platformPackageRange(); @@ -184,7 +201,7 @@ function buildRoutedAppDependencies(): Record { react: REACT_RANGE, 'react-dom': REACT_RANGE, 'react-router-dom': '^7.18.2', - 'lucide-react': '^1.29.0', + 'lucide-react': '^1.31.0', ...Object.fromEntries(PLATFORM_RUNTIME_PACKAGES.map((name) => [name, range])) }; } From e7b77777b0c7f17557f344987d51865046d391db Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 08:59:11 +0000 Subject: [PATCH 2/3] fix(create-plugin): move the jest-dom template range with the same dependabot wave The scaffolded plugin's generated devDependencies declared @testing-library/jest-dom at ^7.0.0 while the repo root had moved to ^7.0.1 (#4948's dev-dependencies group), so templates.test.ts's anchor rule was red on main independently of the lucide-react drift in the previous commit. Same defect class, same wave, and the same pairing the previous occurrence of this incident was fixed as (#4098 / PR #4099 moved these two templates in one PR). Found only by sweeping the class rather than the package: the anchor rule throws on its first mismatch, so this second template reported nothing until the first was green. The doc table above the map is moved with it -- it states each anchored range, so leaving it would just relocate the fossil into a comment. Co-authored-by: Claude --- .../create-plugin-jest-dom-range-4968.md | 21 +++++++++++++++++++ packages/create-plugin/src/templates.ts | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 .changeset/create-plugin-jest-dom-range-4968.md diff --git a/.changeset/create-plugin-jest-dom-range-4968.md b/.changeset/create-plugin-jest-dom-range-4968.md new file mode 100644 index 0000000000..957db8e70f --- /dev/null +++ b/.changeset/create-plugin-jest-dom-range-4968.md @@ -0,0 +1,21 @@ +--- +'@object-ui/create-plugin': patch +--- + +A scaffolded plugin's generated manifest now asks for the same `@testing-library/jest-dom` range this repo installs. + +`src/templates.ts`'s `DEV_DEPENDENCIES` had fossilised one patch behind the repo +root: the template said `^7.0.0` while the root manifest had moved to `^7.0.1`. +`templates.test.ts`'s anchor rule caught it and was red on `main`. + +Same defect class, same day and same dependabot wave as the `lucide-react` drift +in `@object-ui/cli`'s app generator, so both templates move together here — which +is how the previous occurrence of this incident was handled too (objectui#4098 / +PR objectui#4099 moved these same two templates in one PR). This one came from +the dev-dependencies group bump rather than the single-package bump, and it was +found only because the two ratchets live in different packages: the anchor rule +throws on its first mismatch, so nothing reports the second template until the +first is green. + +The remaining seven anchored ranges in this template were swept against the same +wave and are all in sync. diff --git a/packages/create-plugin/src/templates.ts b/packages/create-plugin/src/templates.ts index cde472d777..3ff336bc8c 100644 --- a/packages/create-plugin/src/templates.ts +++ b/packages/create-plugin/src/templates.ts @@ -59,7 +59,7 @@ export const VITEST_SETUP_FILE = 'vitest.setup.ts'; * * | dependency | range | anchor | * | --------------------------- | --------- | ------------------------------------------ | - * | `@testing-library/jest-dom` | `^7.0.0` | repo root package.json (also apps/console) | + * | `@testing-library/jest-dom` | `^7.0.1` | repo root package.json (also apps/console) | * | `@testing-library/react` | `^16.3.2` | repo root package.json (also apps/console) | * | `@vitejs/plugin-react` | `^6.0.5` | every `packages/plugin-*` (not in root) | * | `jsdom` | `^30.0.1` | repo root package.json | @@ -84,7 +84,7 @@ export const VITEST_SETUP_FILE = 'vitest.setup.ts'; * monorepo, not a failing install. */ const DEV_DEPENDENCIES: Record = { - '@testing-library/jest-dom': '^7.0.0', + '@testing-library/jest-dom': '^7.0.1', '@testing-library/react': '^16.3.2', '@vitejs/plugin-react': '^6.0.5', jsdom: '^30.0.1', From 46f679c4d18122466ddeaf7868b6ca6bdb2dd035 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 09:35:04 +0000 Subject: [PATCH 3/3] fix(ga-pin): follow the quick-reference spec/client rows to GA, cite $like/$ilike as undecided MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two residues of the `@objectstack/spec` 17.0.0 GA pin were red on `main` itself, so every open PR inherited a red `Test (shard 3/4)` (objectui#4977). 1. `QUICK_REFERENCE.md`'s "Current Release" block still stated `^17.0.0-rc.6` for `@objectstack/spec` and `@objectstack/client` while the manifests it names as its anchors declare `^17.0.0`. Both rows now quote the anchor. The pin derives its expectation from the manifest, so the doc followed the manifest; nothing in `scripts/__tests__/quick-reference-current-release-4143.test.ts` was relaxed. 2. GA's `FieldOperatorsSchema` added `$like` and `$ilike`, which no builder operator authors, so the #2942 reachability sweep reported them exactly as designed. They are excluded through that gate's own citation mechanism as "undecided — see #4911" with the harvest condition written on the entry: a ruling on #4911 must either delete the members and add the operators, or restate the paragraph as a decision carrying its reopen condition. No operator is implemented, no other gate logic moves, and the authoring-surface ruling stays with the maintainer. Co-authored-by: Claude --- ...esidue-quickref-and-like-exemption-4977.md | 21 +++++++++++++++ QUICK_REFERENCE.md | 4 +-- .../FilterConditionField.operators.test.ts | 27 ++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 .changeset/ga-pin-residue-quickref-and-like-exemption-4977.md diff --git a/.changeset/ga-pin-residue-quickref-and-like-exemption-4977.md b/.changeset/ga-pin-residue-quickref-and-like-exemption-4977.md new file mode 100644 index 0000000000..3045749b55 --- /dev/null +++ b/.changeset/ga-pin-residue-quickref-and-like-exemption-4977.md @@ -0,0 +1,21 @@ +--- +--- + +Clears the two GA-pin residues that were red on `main` itself, so every open PR stopped +inheriting a red `Test (shard 3/4)` (objectui#4977). No published behaviour changes: the +only files touched are a root doc and a test file. + +`QUICK_REFERENCE.md`'s "Current Release" block still quoted `@objectstack/spec` and +`@objectstack/client` as `^17.0.0-rc.6` after the manifests moved to the `^17.0.0` GA +range. Both rows now state the range their named anchor declares — the doc followed the +manifest, the pin that derives the expectation was not loosened. + +The `@objectstack/spec` GA `FieldOperatorsSchema` added `$like` and `$ilike`, which no +builder operator authors, so the #2942 reachability sweep in +`packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts` reported +them by design. They are excluded through that gate's own citation mechanism as +**undecided — see objectui#4911** (the open decision box on whether the visual filter +builder should offer raw pattern matching), with the harvest condition written on the +entry: a ruling on #4911 must either delete the members and add the operators, or restate +the paragraph as a decision carrying its reopen condition. No operator was implemented and +no other gate logic moved — the product ruling stays with the maintainer. diff --git a/QUICK_REFERENCE.md b/QUICK_REFERENCE.md index 79128b1e05..491fb4bebe 100644 --- a/QUICK_REFERENCE.md +++ b/QUICK_REFERENCE.md @@ -113,9 +113,9 @@ that test tells you to edit this block. The one exception is called out on its r - **Version:** 17.5.0 (the version every `@object-ui/*` manifest carries — they are one `fixed` group in `.changeset/config.json`, so a release moves all of them together) -- **Spec:** `@objectstack/spec` ^17.0.0-rc.6 (declared by the root `package.json` and by +- **Spec:** `@objectstack/spec` ^17.0.0 (declared by the root `package.json` and by `apps/console/package.json`) -- **Client:** `@objectstack/client` ^17.0.0-rc.6 (declared by `apps/console/package.json` +- **Client:** `@objectstack/client` ^17.0.0 (declared by `apps/console/package.json` and `packages/data-objectstack/package.json`) - **Node.js:** ≥ 22 (see root `engines.node`) - **pnpm:** ≥ 9 (the workspace pins `pnpm@10.31.0` via `packageManager`) diff --git a/packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts b/packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts index d14b0a3054..6d03d42b64 100644 --- a/packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts +++ b/packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts @@ -58,8 +58,33 @@ const noTypes = () => undefined; * it between @objectstack/spec 17.0.0-rc.2 and rc.5, and no builder operator * could author it. `containsCaseInsensitive` now does, so the entry is gone and * the parity assertion below is what holds that honest. + * + * `$like` and `$ilike` arrived with the `@objectstack/spec` 17.0.0 GA pin + * (objectui#4636). Their entry here is **undecided — see #4911**, and it claims + * nothing else: whether this builder should offer raw pattern matching at all is + * an authoring-surface question that has NOT been ruled on, so this is a CITED + * OPEN QUESTION, not a finding that the tokens should stay unauthorable. It was + * taken because the sweep below is red on `main` itself under the GA pin, which + * every open PR inherits (objectui#4977); the question keeps waiting on the + * maintainer either way. + * + * Harvest condition — a ruling on #4911 must change these two members or this + * paragraph. Neither survives the ruling untouched: + * + * - ruled A (build the operators): delete both members and add the builder + * operators that author them; the parity assertion below then holds that + * honest, exactly as it did when objectui#4023 retired `$icontains`. + * - ruled B (the builder will not offer raw pattern matching): rewrite this + * paragraph as the refusal the ruling makes it — stated as a decision, with + * the ruling's own reopen condition on the entry — and reopen #4911 if that + * condition is ever met. + * + * Leaving it reading "undecided" after a ruling lands is the stale-exclusion rot + * this comment block already warns about, one level up: the ratchet below can + * only check that a member is still a spec operator, never that its reason is + * still the true one. */ -const KNOWN_UNREACHABLE = new Set(['$eq', '$between']); +const KNOWN_UNREACHABLE = new Set(['$eq', '$between', '$like', '$ilike']); /** Pull the operator keys out of a `{ field: { $op: v } }` fragment. */ function operatorsOf(frag: Record | null): string[] {