Uh oh!
There was an error while loading. Please reload this page.
Pin @objectstack/* to 17.1.0 - #5529
Conversation
…oves Lockfile refresh only — every manifest already declared `^17.0.0`, which admits 17.1.0, so no dependency range changed. spec, client, formula and lint move in lockstep (a split resolution is what produced the dual-version spec graph that reddened check:spec-symbols in this repo's history). Green-keeping, each forced by the new build and nothing else: - data-objectstack: identity alias row for `icontains`, a canonical VIEW_FILTER_OPERATORS member as of 17.1.0 and itself a member of VALID_AST_OPERATORS. Unmapped, an authored `icontains` reaches the wire raw — the shape that shipped an unfiltered query in objectstack#3948. - app-shell palette: drop the now-stale `element:filter` exclusion, exclude the newly-declared `record:discussion` as the same renderer as the offered `record:chatter`. Nothing the palette offers changes. - check-spec-symbol-derivation DEBT: `ReferenceRailEntry`, which 17.1.0 started exporting under a name objectui already used. The shapes disagree on `icon` (spec's schema is $strict and refuses it), so reconciling is a contract call — filed as #5494. - check-action-forward-parity KNOWN_GAPS: `onSuccess` x4 declared surfaces. ActionRunner has honoured it all along; 17.1.0 supplied the missing half by declaring it authorable, so it became owed. Forwarding it is capability wiring — filed as #5493. check:eager-closure is NOT addressed here and is left red deliberately: the closure grows 129,270 gzipped bytes (3,871,997 to 4,001,267), 41,267 over a ceiling the maintainer ruled on today in #5468 — "the absolute aggregate ceiling stays as shipped", and "gate-strength policy is the maintainer's". Refs #5328
All four are forced by the new contract and nothing else. - plugin-view: map the newly-canonical `icontains` onto the builder's `containsCaseInsensitive` (the id that authors the spec's `$icontains`). The table is keyed by ViewFilterOperator, so this was a compile error, not a silent gap. Deliberately not folded onto `contains`, which would rewrite a case-insensitive filter as case-sensitive on the next save. - test-support tombstone judge: 17.1.0 retires `element:filter` WHOLLY — it leaves PageComponentType while its props schema stays in ComponentPropsMap with every key tombstoned. That is a retired block, not the "broken probe" the old floor assumed, so the floor now applies to blocks the enum still offers. The control key is searched for rather than taken from found[0], which had made it depend on sort order. - console registry parity: delete the two `targetVariable` exemptions, which went dangling-and-stale exactly as that file's docblock predicted they would at the next pin; pin the five `record:*` blocks 17.1.0 adds to ComponentPropsMap (37 entries to 42) using the same pin-dependent shape GA_ONLY_BLOCKS already established; exempt `record:reference_rail.entries`, an array of objects a flat scalar `inputs` carrier cannot express, whose editor also needs #5494's `icon` question settled first. Refs #5328
Three inventories that enumerate a spec vocabulary, all named by their own ratchets on the bump. - plugin-list `mapOperator`: explicit `icontains` arm. The emitted spelling equals the input, so `default` already returned it — but that file's header records relying on the AST set happening to accept a raw view spelling as exactly how it stopped discriminating in #3641, so the arm is written out and pinned in EXPECTED_AST_TARGET. - plugin-list tab presets: VIEW_FILTER_OPERATORS is 20, not 19. - core `SPEC_ACTION_KEYS`: add `onSuccess`. Diagnostic only — the list feeds warnOnUnknownActionKeys, so without it an author writing the key the spec now declares gets told it is unknown. The forwarding gap stays open and tracked (#5493). Refs #5328
❌ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-support-ai
commented
Aug 21, 2026
PM review — holding at draft, blocked on a maintainer decisionReviewer of record: the spec@objectui seat ( The red gate is correctly red, and correctly not fixed here
The dev's citation checks out. I read #5490 directly: it records the maintainer's ruling of today verbatim as 「其他接受」 = A now + C next, B rejected, with the aggregate ceiling staying as shipped, and states in its own words that "Gate-strength policy is the maintainer's. ⛔ No seat should pick this." Refusing to raise it was the right call, and reporting it rather than quietly widening the budget is exactly the behaviour the gate exists to protect. Escalated with a four-axis analysis and three costed options: #5531. What I verified, beyond the report
On the out-of-scope findings#5493, #5494 and #5495 were filed rather than ridden in, and each was parked in the gate's own ratcheted ledger so the entry dies when the real fix lands. That is the right shape — a pin bump takes no riders. I have not re-graded them; grading is triage's. One judgement I specifically agree with: mapping VerdictNot ACCEPT, not REWORK — ESCALATE. The implementation is sound and I found nothing to send back. It waits on #5531. ⛔ Staying draft. Not flipped to ready, not queued, not auto-merged. Generated by Claude Code |
os-support-ai
commented
Aug 21, 2026
CI is fully in: 1 failure, and it is the escalated oneAll 22 check runs are now This upgrades the PR body's "everything else is green" from a self-report to a CI-verified fact. Green includes CI and the dev's local measurement agree exactly — the same numbers in different units:
One reading CI adds that the local run did not surface: the entry chunk is 151.1 KB against a 350 KB budget — comfortably inside. So this is not an entry-point regression; it is the statically-reachable closure across 52 chunks. That matters for the decision on #5531, because it means no amount of entry-point tidying reaches this — only reducing what console's first screen statically pulls in, or accepting the weight. Why I am not pushing a fix⛔ The only change that turns this green is raising the ceiling, and that is gate-strength policy — the maintainer's, per the ruling recorded on #5490 today ("Gate-strength policy is the maintainer's. ⛔ No seat should pick this."). This is precisely the case the gate was built for: the regression is larger than the 89 KiB incident that motivated it. Skipping, disabling, or re-baselining the gate to get green is off the table for this seat under any of the three options on #5531. The PR stays draft until that card is answered. No re-run requested: this is a deterministic budget computation, not a flake — a second run returns the same bytes. Generated by Claude Code |
Fixes#5328
⛔ One gate is deliberately red and I did not fix it —
check:eager-closure. It needs a maintainer decision, described at the bottom. Everything else is green; verification is quoted below against the merged HEAD.The pin
A lockfile refresh, nothing else. All four
@objectstack/*packages move together — a split resolution is what produced the dual-version spec graph that reddenedcheck:spec-symbolsin this repo's history.@objectstack/spec17.0.017.1.0@objectstack/client17.0.017.1.0@objectstack/formula17.0.017.1.0@objectstack/lint17.0.017.1.0No manifest edit was required, confirming the card's assumption: all 38 declarations across 33 packages are
^17.0.0, a single distinct range per package, and^17.0.0already admits17.1.0. Two transitive@objectstack/*packages move in lockstep with them (core,sdui-parser17.0.0→17.1.0), which is what keeps the graph single-version —grep -c '@objectstack/[a-z-]*@17\.0\.0' pnpm-lock.yamlis 0. One unrelated transitive re-resolved inside its own caret:@mongodb-js/saslprep1.4.13 → 1.5.0.motionis untouched, so PR #4958's lockfile change was not absorbed — the branch point is correct.Note on
pnpm update, because it does more than the card asked for: run against the four package names it rewrote all 31 manifests from^17.0.0to^17.1.0, and also silently re-indented two unrelatedcheck:*script lines in the rootpackage.json. Both were reverted and the install re-run, so the lockfile'sspecifier:fields still read^17.0.0whileversion:reads17.1.0. The diff is lockfile-only for the pin, as the card specified.Green-keeping
Each item below is forced by the new build and nothing else. Every one was counter-probed against
origin/mainwith the 17.0.0 lockfile to confirm it is bump fallout rather than a pre-existing red.Fixed here — mechanical, one correct answer already pinned by existing evidence:
icontainsis a new canonicalVIEW_FILTER_OPERATORSmember (vocabulary 19 → 20) and is itself a member ofVALID_AST_OPERATORS. Three places needed it:data-objectstack's alias table (an identity row likecontains— unmapped, an authoredicontainsreaches the wire raw, the shape that shipped an unfiltered query in objectstack#3948);plugin-view's canonical-to-builder table, which is keyed byViewFilterOperatorand so failed to compile (mapped to the builder'scontainsCaseInsensitive, the id that authors$icontains— deliberately not folded ontocontains, which would rewrite a case-insensitive filter as case-sensitive on the next save); andplugin-list'smapOperator, given an explicit arm rather than left to thedefaultpassthrough that happens to work today.onSuccessadded tocore'sSPEC_ACTION_KEYS— diagnostic only. That list feedswarnOnUnknownActionKeys, so without it an author writing the key the spec now declares is told it is unknown.element:filterexclusion is dropped and the newly-declaredrecord:discussionexcluded as the same renderer as the already-offeredrecord:chatter. Nothing the palette offers changes.targetVariableexemptions deleted — they went dangling-and-stale exactly as that file's own docblock predicted they would at the next pin; the fiverecord:*blocks 17.1.0 adds toComponentPropsMap(37 → 42) pinned using the same pin-dependent shapeGA_ONLY_BLOCKSalready established.element:filterwholly — it leavesPageComponentTypewhile its props schema stays inComponentPropsMapwith every key tombstoned. That is a retired block, not the "broken probe" the old floor assumed, so the floor now applies to blocks the enum still offers, and the control key is searched for rather than taken fromfound[0](which had made the assertion depend on sort order).Recorded, not fixed — each is capability wiring or a contract call, which a pin bump does not take as a rider. Each uses the gate's own purpose-built, ratcheted ledger, so the entry dies the moment the real fix lands:
onSuccessis dropped by all four declared action surfaces →KNOWN_GAPS, filed asonSuccessis authorable as of @objectstack/spec 17.1.0 and honoured by ActionRunner, but all four declared action surfaces drop it one hop before the runner #5493.ActionRunner.ts:1197has honoured the key all along; 17.1.0 supplied the missing half by declaring it authorable (0 → 53 occurrences in the spec'sdist/**/*.d.ts), so it became owed for the first time. Forwarding it is the same class as plugin-gantt: schema 上的 viewMode 只被 ResourceWorkload 分支读,时间轴静默忽略 —— 且该键在 ObjectGanttSchema 与 spec 的 GanttConfigSchema 都未声明 #5074 / ListView never forwards the view-levelmapconfig block to plugin-map — spec'sListMapConfigSchema(objectstack#9340) is authorable but inert at runtime; switcher wiring included #5042, which this card defers to its dependants.ReferenceRailEntryis now a spec-owned name →DEBT, filed asReferenceRailEntryis owned by @objectstack/spec as of 17.1.0 and objectui's local copy declares an extraiconkey the spec's strict schema refuses #5494. objectui did not fork it; 17.1.0 started exporting the name. The shapes disagree onicon, which the spec's$strictschema refuses while this repo's renderer reads it — so importing, deriving or renaming each decides that key's fate.record:reference_rail.entries→UNPUBLISHED_EXEMPTIONS. Newly judged rather than newly missing: the registration has always published onlyhideEmpty, andentriesis an array of objects a flat scalarinputscarrier cannot express. Its editor also needsReferenceRailEntryis owned by @objectstack/spec as of 17.1.0 and objectui's local copy declares an extraiconkey the spec's strict schema refuses #5494'siconquestion settled first.One observation filed and not acted on: the palette advertises the pair under the legacy alias (
record:chatter) and now explicitly excludes the canonicalrecord:discussion— #5495.Also worth recording, because it defeats the obvious check:
PageComponentTypehas 34 members before and after.element:filterleft asrecord:discussionarrived, so a member-count assertion cannot see this release at all.Verification
Run on merged HEAD
97c1162af(this branch aftergit merge origin/main), exit codes captured before any pipe.pnpm build— turbo:Tasks: 43 successful, 43 totalpnpm type-check— turbo:Tasks: 81 successful, 81 totalpnpm lint— turbo:Tasks: 47 successful, 47 total(the full farm, not a narrowed run)pnpm test, all four shards: 1,762 files, 22,433 passed, 1 skipped, 0 failedcheck:spec-symbols·check:phantom-deps·check:self-import·check:action-forward-parity·check:control-bytes·check:published-dist·check:node-esm-load·check:esm-specifiers·check:doc-types·check:doc-snippets·check:i18n-keys·check:i18n-drift·check:i18n-dead-keys·check:skills-paths·lint:coverage·type-check:coverage·quick-reference:check·changeset:check·check-changeset-presenceTheir own verdict lines, rather than a bare exit code:
⛔ The one red gate —
check:eager-closure, and why I did not touch itorigin/main@2524e7450with the 17.0.0 lockfileMAX_EAGER_CLOSURE_GZIP_BYTESThe growth is real content, not a packaging accident — the spec's own
dist.mjsgoes from 11,661,923 to 12,593,720 bytes (+8%) — and essentially all of it lands in one chunk:vendor-objectstack1493.3 KB → 1619.5 KB.I did not raise the ceiling, for three reasons:
expect()—MAX - BASELINE.gzipBytesmust stay belowREGRESSION_THIS_GATE_MUST_CATCH_BYTES(91,136) — so covering a 129,692 B delta means also rewriting the hardcodedBASELINEinscripts/__tests__/check-eager-closure-budget.test.ts, i.e. dismantling the very assertion [Decision] Should the eager-closure budget be tightened below today's payload — absolute ceiling, true ratchet, or per-chunk budgets? #5468 cites as the ceiling's guarantee.vendor-objectstackadvancedChunks group folds the lazily-imported@objectstack/lintinto an eagerly-loaded chunk — 89 KiB gzipped on every page load #5266 incident the gate was built to catch. The gate is working exactly as designed; this is the case it was sized for.There are also queued cards pointing at this chunk specifically — #5490 is
pm:queueto add per-chunk budgets starting withvendor-objectstack, and #5325 / #5359 are the cleave direction — so widening the aggregate now would hide the growth inside headroom right before a card lands a budget on it.The decision needed: either re-baseline the ceiling deliberately (accepting +126.7 KiB on every console page load, which is what the mandated 17.1 upgrade costs), or land a cleave first and let this PR follow. I have no recommendation to offer past the measurements — the ruling above puts this choice outside a dev seat.
Generated by Claude Code