Skip to content

Carry overrideNotice on a dispatch envelope at the seam, not on ActionDef (#5611) - #5644

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-5611-overridenotice-declaration
Aug 22, 2026
Merged

os-zhuang merged 5 commits into
mainfrom
claude/issue-5611-overridenotice-declaration

Conversation

@os-sales

@os-sales os-sales commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #5611

Reworked to the ruled narrow-B shape (maintainer ruling 2026-08-22), then completed with item 4 under the Option-A ruling of 2026-08-22 ~17:26Z. overrideNotice is carried on a host-composed envelope type at the dispatch seam, and the dev-mode warning that called it unknown now knows about it. The published ActionDef still declares nothing new and ACTION_DEF_KEYS still gains nothing — that prohibition is untouched; what item 4 adds to packages/core is a separate host-dispatch key list, detailed in its own section at the bottom. The earlier +32 / +6 on ActionRunner.ts / actionKeys.ts are gone; the mechanical proof that they are gone is the byte-identical dist below.

Note: GitHub's body sanitizer strips angle-bracket placeholders, so metavariables below are written in CAPS (_actions.NAME.description, git checkout BASE -- PATH).

The ruled shape, item by item

# ruled here
1 envelope type at the seam, in @object-ui/app-shell ✅ ConsoleActionDispatch — src/consoleActionDispatch.ts
2 replace the dispatch as ActionDef cast ✅ DeclaredActionsBar.tsx — the dispatch is composed AS the envelope, execute(dispatch) needs no cast
3 both param handlers narrow to the envelope ✅ useConsoleActionRuntime.tsx and RecordDetailView.tsx
4 fix the warnOnUnknownActionKeys false flag ✅ ruled Option A and implemented — HOST_DISPATCH_ACTION_KEYS in packages/core/src/actions/actionKeys.ts, unioned into KNOWN_ACTION_KEYS, pinned. Warn count 1 → 0. See the item-4 section at the bottom

All four items are now complete and verified. Item 4 was escalated as a ruling-level question, ruled Option A, and implemented in a second round; the escalation section below is kept as the record of how that decision was reached, and the section at the bottom is what actually landed.

1. The envelope

packages/app-shell/src/consoleActionDispatch.ts (new):

export type ConsoleActionDispatch = ActionDef & {
  overrideNotice?: string;
};

Why that home. It belongs to neither the producer nor the reader — it is the contract between them — so it sits at the package root beside the other package-wide contracts (types.ts, urlParams.ts, runtime-config.ts) rather than inside views/ or hooks/. It is deliberately not re-exported from src/index.ts: @object-ui/app-shell's exports map has exactly one entry pointing at dist/index.d.ts, so keeping the type off the barrel means this card adds no published surface in any package. @object-ui/core's surface does not move either (byte-identical, below), so the authored-metadata surface is exactly as strict as it was on main — writing overrideNotice in an ActionDef literal is still a compile error.

The docblock carries the ruling's own grounds, so the next reader finds the reasoning rather than re-deriving it.

2 + 3. The cast is gone, and both handlers come off any

Before, the key crossed the whole seam undeclared: const dispatch: any = … → execute(dispatch as ActionDef) on one side, action?: any on the other. Producer and reader could disagree in silence — and no existing test could see it, because each side's suite spells the key itself (DeclaredActionsBar.overrideAffordance.test.tsx reads dispatch.overrideNotice off its own spy; useConsoleActionRuntime.overrideNotice.test.tsx hands in a literal). Rename it on one side and the notice stops appearing, all green.

RecordDetailView's handler does not read the key. It still takes the envelope, per the ruling — so the two handlers on this seam cannot drift from each other, and a reader added there later has a declaration instead of a reach for a cast. There is no sequencing cost: #5610 landed 2026-08-21T18:37:09Z, so the dead title limb is already gone from that handler and this file's change is the single annotation.

4. The warnOnUnknownActionKeys false flag — the escalation (historical; RULED and implemented, see the bottom)

The defect is real and reproduced at base (built @object-ui/core at f1c27f037, driving the exact dispatch DeclaredActionsBar composes on the override branch):

KNOWN_ACTION_KEYS.has("overrideNotice") = false
classifyActionKeys -> {"unknown":["overrideNotice"],"retired":[]}
warn call count = 1
WARN> [ActionRunner] action "approval_reject" carries a key no reader recognizes:
      `overrideNotice`. Nothing will read it — check for a typo, or promote the key
      to an explicit field on `ActionDef` …

The ruling asks for a seam-level known-key, not an ACTION_DEF_KEYS entry. There is no mechanism for one today, and the fences on this rework forbid creating it. Enumerated mechanically rather than asserted:

  • one call site, and it is core-internal — packages/core/src/actions/ActionRunner.ts:919, first statement of execute(). No host code stands between the producer and it.
  • KNOWN_ACTION_KEYS takes no seam contribution — actionKeys.ts:297 builds it once at module scope from three core-owned lists (ACTION_DEF_KEYS, SPEC_ACTION_KEYS, NAVIGATION_ALIAS_KEYS), and classifyActionKeys:313 is its only reader. Grepping @object-ui/core/src for a registration API (register*, addKnownKey, anything naming the set) returns those two lines and nothing else.
  • ActionRunner's host-facing configuration surface is ten members — setConfirmHandler, setToastHandler, setModalHandler, setNavigationHandler, setParamCollectionHandler, setResultDialogHandler, registerHandler, unregisterHandler, registerScript, unregisterScript. None touches the key set.

So any fix is one of: (a) a fourth, host-dispatch key list in packages/core/src/actions/actionKeys.ts unioned into KNOWN_ACTION_KEYS (not an ACTION_DEF_KEYS entry, not a declaration on ActionDef — there is in-file precedent in HOST_STASHED_PARAM_KEYS, which already names host-stashed keys and cites DeclaredActionsBar by name); (b) a core registration API the seam calls at module init, which is the literal "seam-level" reading but adds mutable global state and an init-order hazard; (c) mutating the exported ReadonlySet from app-shell through an as Set<string> cast — which would reintroduce exactly the invisible cast this card exists to delete, so it is listed only to be rejected; (d) defer to a follow-up card.

All of (a)–(c) touch packages/core, which this rework is fenced against. Recommendation is (a), but that is a decision, not a dev call — see the report on #5611.

Two things worth stating about the cost of leaving it: the dev-console lie continues on every privileged-override dispatch, and its prescription now points at a shape the ruling forbids ("promote the key to an explicit field on ActionDef"). #5642 covers the message's own wrongness and stays open, unassigned.

Reverse verification — two legs, opposite directions, each measured failing

The fix is a type, so the gauge has to be the compiler. src/__tests__/consoleActionDispatch.pin.test.ts (new) compiles the same seven cases against both ConsoleActionDispatch and ActionDef — same harness as packages/core/src/actions/__tests__/actionKeys.types.test.ts — and asserts the delta between the two columns is exactly overrideNotice. Green: 16 passed (16).

leg mutation mutation proven on disk result
1 — the envelope loses the key delete overrideNotice?: string; from consoleActionDispatch.ts anchored line count 1 → 0; git diff --numstat = 0 1 pin 3 failed / 13 passed; type-check exit 2
2 — the REJECTED shape returns declare overrideNotice?: string; on ActionDef in ActionRunner.ts injected line count 0 → 1; git diff --numstat = 1 0 pin 3 failed / 13 passed, naming both overrideNotice rows and the delta row

Leg 1's tsc output is the more interesting half, because it is four diagnostics where #4282 and this card both measured three:

src/hooks/useConsoleActionRuntime.tsx(261,45): error TS2339: Property 'overrideNotice' does not exist on type 'ActionDef'.
src/hooks/useConsoleActionRuntime.tsx(261,83): error TS2339: …
src/hooks/useConsoleActionRuntime.tsx(262,18): error TS2339: …
src/views/DeclaredActionsBar.tsx(314,18):      error TS2339: …

The fourth is the producer, and it exists only because the cast is gone. Under dispatch as ActionDef that file was invisible to the compiler; removing the cast is what put it under one. That is the card's own thesis, measured.

Leg 2 doubles as the harness's resolution proof. Core's dist was deliberately not rebuilt for it, and the control printed 0 occurrences of overrideNotice in dist/actions/ActionRunner.d.ts before and after the mutation — so a harness reading dist would have stayed green. It went red, which is how the file's paths-based source resolution is demonstrated rather than claimed. (The harness also throws loudly on any diagnostic landing in its own import header, so an unresolvable import can never be read as "the compiler accepted everything".)

Both legs restore under trap … EXIT INT TERM. After each, the tree was verified byte-identical to eb3ccfd77 — git status --porcelain empty and git diff --stat HEAD empty. The restore is written as git checkout SHA -- PATH then git reset -q HEAD -- PATH then git checkout -- PATH, because the first form stages the base content and a bare follow-up git checkout -- PATH would otherwise restore from the index rather than from the commit.

packages/core is byte-identical to base — the mechanical proof of the ruling's first clause

Two independent clean builds: one from this branch, one from a worktree checked out at the pinned base f1c27f037 that never contained the diff. tsc is composite and skips emit when tsconfig.tsbuildinfo survives — it lives outside dist/, so both were cleared and the count is printed as a control (0 after clean, 1 regenerated, so emit really ran).

base leg (f1c27f037 worktree) head leg (eb3ccfd77)
files emitted 180 180
dist/index.d.ts sha256 f6494f80… f6494f80…
dist/actions/ActionRunner.d.ts sha256 81a74ca5… 81a74ca5…
whole dist/ tree sha256 8bd78cc9… 8bd78cc9…

Compared by hash, not byte count. 81a74ca5… is the same figure this PR's previous round independently recorded for its base leg, so the head build now reproduces base exactly. git diff --stat BASE HEAD -- packages/core is also empty, which is the same fact from the source side.

dist/index.d.ts is the file that matters for reachability — ActionDef reaches the published entry through export *, so a grep of the barrel for its name means nothing and only the hash answers. It does not move.

Scope proof for the declared test narrowing

pnpm test is the repo-wide farm CI owns. The narrowing here is not a judgement call — it is measured: this diff changes no executable JavaScript anywhere in @object-ui/app-shell.

Two clean builds of the package, one with the diff and one with it reverted in place:

  • emitted .js files: 432 (head) vs 431 (base); the only set difference is the new ./consoleActionDispatch.js, a type-only module.
  • shared files whose content differs: 3 — useConsoleActionRuntime.js, DeclaredActionsBar.js, RecordDetailView.js.
  • changed lines across those three: 20, and 20 of 20 are // comment lines (removeComments is not set anywhere in the tsconfig chain, so comments survive emit). Non-comment deltas: 0.

as casts and type annotations are erased, so execute(dispatch as ActionDef) and execute(dispatch) emit identically. With zero executable change, no pre-existing runtime test in this repo can change verdict because of this diff, which is what makes the suite selection below a superset rather than a sample.

Verification

All at final commit eb3ccfd77, union re-run after the last commit, working tree clean.

  • @object-ui/app-shell — type-check exit 0 with both tsc projects run (tsc --noEmit && tsc -p tsconfig.test.json; the && short-circuits, so exit 0 is the only reading that proves the test project ran).
  • vitest run --maxWorkers=2 over the new pin, both DeclaredActionsBar suites, all of hooks/__tests__/, and all 14 RecordDetailView.* suites → Test Files 43 passed (43) / Tests 421 passed (421).
  • @object-ui/core control — vitest run packages/core/src/actions/ → Test Files 23 passed (23) / Tests 407 passed (407), including actionKeys.pin.test.ts and actionDef-closed-surface.test.ts. Green because core is at base.
  • All vitest runs from the repo root — package-cwd is refused by the pnpm --filter @object-ui/app-shell test 跑的是 @object-ui/console 的 22 个文件,app-shell 自己的 276 个一个没跑,却报绿 #3378 guard.
  • Gates, each read from its own printed verdict line rather than a bare $? (exit captured before any pipe):
    • check-control-bytes — OK (scanned 4693 tracked text file(s); skipped 85 binary)
    • check-action-forward-parity — 5 surfaces checked against 39 runtime-read keys from 4 consumers; 19 justified omissions, 7 known gaps (owed sets unchanged — this card adds no action key to any surface)
    • check-package-self-import — No package names itself inside its own src/.
    • check-phantom-dependencies — Every in-scope import is declared by the package that publishes it.
    • check-node-esm-load --specifiers-only — no un-ledgered package emits an extensionless relative specifier
    • check-type-check-coverage — 45/46 via type-check … test type-check coverage: 41/41
    • check-lint-coverage — 46/46 packages linted, 0 with outstanding errors (0 total)
    • check-changeset-presence / -no-major / -fixed — all ✅
  • Lint: pnpm --filter @object-ui/app-shell lint → ✖ 2546 problems (0 errors, 2546 warnings), exit 0. That is the whole of the only package this diff touches, not a file subset; type-aware linting is not enabled anywhere in the config (no projectService, no parserOptions.project, no recommendedTypeChecked), so no rule reads cross-file type information and this diff cannot move an untouched package's verdict. On the changed files, counted from --format json: 5 files, 0 errors, 164 warnings, and the two new files contribute 0. Measured against the same three files at base: 167 → 164 warnings, no-explicit-any 142 → 139 — the narrowing removes three anys and adds none.

Changeset

.changeset/console-action-dispatch-envelope-5611.md, empty frontmatter. The previous round's changeset described a declaration on a published interface and is deleted. Nothing here is user-visible: @object-ui/core is byte-identical, the envelope is not exported from app-shell's barrel, and the emitted JavaScript is comment-only different. check-changeset-presence.mjs is the authority and agrees:

✅  3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s):
    .changeset/console-action-dispatch-envelope-5611.md.
    Every one of them has an EMPTY frontmatter — declared as releasing nothing, which
    is the explicit exemption and a complete answer to this gate.

If item 4 lands later and the dev-console warning actually stops, that is the user-visible half and earns a real bump then.

Out of scope

#5642 stays open and unassigned — the same warning's message states a fact objectstack#4075 step 3 retired and points the author at the wrong file. It is a different defect class (shipped prose vs. a missing declaration) and is not folded in here. Its second half now matters more, not less: the prescription it ships ("promote the key to an explicit field on ActionDef") is the shape this card's ruling forbids.

Item 4 — RULED and implemented: HOST_DISPATCH_ACTION_KEYS in core (Option A)

Maintainer ruling, 2026-08-22 ~17:26Z on #5611: Option A — a host-dispatch key list in
packages/core/src/actions/actionKeys.ts, unioned into KNOWN_ACTION_KEYS, pinned. The seat's
own "packages/core must not be touched" fence is explicitly lifted by that ruling; the two
prohibitions the earlier ruling set are preserved verbatim and are quoted here because they
are the constraint the implementation had to satisfy, not decoration:

> ⛔ 不声明到 ActionDef,⛔ 不进 ACTION_DEF_KEYS(AST 派生 pin 不动)——授权面严格度与今天逐字节相同。

Both hold. ActionDef gains nothing, ACTION_DEF_KEYS gains nothing, and the AST-derived pin
actionKeys.pin.test.ts re-derives that list from the interface unchanged. Writing
overrideNotice in an ActionDef literal is still a compile error.

What landed

packages/core/src/actions/actionKeys.ts:

export const HOST_DISPATCH_ACTION_KEYS = ['overrideNotice'] as const;

unioned into KNOWN_ACTION_KEYS as its fourth input, alongside ACTION_DEF_KEYS,
SPEC_ACTION_KEYS and NAVIGATION_ALIAS_KEYS — and the first input that is not a restatement
of an authored surface. classifyActionKeys remains its only reader; nothing else moved.

The docblock is written in the style of the in-file precedent HOST_STASHED_PARAM_KEYS, which
models the same category one level down (host-composed keys inside params) and likewise cites
DeclaredActionsBar by name. It records the producer (views/DeclaredActionsBar.tsx, the
can_act:false && can_override:true branch) and both readers
(hooks/useConsoleActionRuntime.tsx, views/RecordDetailView.tsx), and states the admission
test for anything added later: composed by a host in code, never read back out of stored
metadata, read by the runtime.

The false flag is dead — measured, not asserted

Both legs drive the exact dispatch object literal DeclaredActionsBar composes on the
override branch, through classifyActionKeys / warnOnUnknownActionKeys loaded from source.

measurement before (branch head, without the change) after
KNOWN_ACTION_KEYS.has('overrideNotice') false true
classifyActionKeys(dispatch).unknown ["overrideNotice"] []
dev-console warn count 1 0
control dispatch with a real typo (targt) warns, naming overrideNotice and targt warns, naming targt alone

The "before" line is the same figure the escalation round recorded, reproduced at branch head:

[ActionRunner] action "approval_reject" carries a key no reader recognizes: `overrideNotice`.
Nothing will read it — check for a typo, or promote the key to an explicit field on `ActionDef`

That prescription is the shape the ruling forbids for this key, which is why the diagnostic was
worse than noise.

No other key's classification moved, and that is a set measurement rather than a spot check.
Importing the base file and the head file into one process and differencing the two sets:

base_size 64 → head_size 65 · added ["overrideNotice"] · removed []
ACTION_DEF_KEYS / SPEC_ACTION_KEYS / NAVIGATION_ALIAS_KEYS: identical · RETIRED_ACTION_KEYS: identical

Pins

Four new assertions in packages/core/src/actions/__tests__/actionKeys.pin.test.ts (13 → 17
tests):

  1. HOST_DISPATCH_ACTION_KEYS exact contents ['overrideNotice'] — toEqual on the whole
    array, not toContain. The set is the ruling's scope, and the risk this list carries is
    growth: a key in it is a key the warning stops asking about, so a silent second member must
    be a red test that names it.
  2. KNOWN_ACTION_KEYS.has('overrideNotice') === true.
  3. The authored surface stays closed, read off the interface's own AST — declaredOnActionDef: false, inActionDefKeys: false, inSpecActionKeys: false. Re-declaring the key on ActionDef
    "for consistency" fails here by name.
  4. Behavioural, both directions: the host dispatch produces no warning, and a typo riding the
    same dispatch still produces exactly one — naming targt and not overrideNotice. Without
    the second half, stubbing classifyActionKeys to return nothing would pass the first.

Ablation — one leg, from the committed state

Mutation: ['overrideNotice'] as const → [] as const. Proven on disk by anchored occurrence
count
, because an editor's exit code is not evidence a replacement landed:

pre-mutation : intact declaration 1 · ablated declaration 0
python replace: anchor found 1 time(s)
post-mutation: intact declaration 0 · ablated declaration 1 · git diff --numstat = 1 1

Result: Tests 4 failed | 13 passed (17) — all four new pins red and named
(expected [] to deeply equal [ 'overrideNotice' ], expected false to be true,
expected "warn" to not be called at all, but actually been called 1 times,
expected '[ActionRunner] action "approval_rejec…' not to contain 'overrideNotice'), and the
node repro's warn count back to 1 with the false message restored. The third pin — the
authored surface staying closed — stayed green, which is correct: that half must not depend
on the list, and an ablation that reddened it would mean the two halves were entangled.

packages/core's dist was deliberately not rebuilt for this leg. The harness resolves
@object-ui/core through paths → packages/core/src (root tsconfig.json, and the same alias
in vitest.config.mts), so a dist-reading harness would have stayed green; going red is the
demonstration of source resolution rather than a claim of it.

Restored under trap … EXIT INT TERM. Tree verified byte-identical afterwards: git status --porcelain empty, git diff --stat HEAD empty, and the file's blob hash equal to the committed
one (75fae1e6…).

A gate the dispatch list did not name, and my own diff tripped it

check:spec-symbols (check-spec-symbol-derivation.mjs) went red on the first draft of the
new docblock: it read the word "mirrors", written about the other three lists, as a
spec-alignment claim standing behind HOST_DISPATCH_ACTION_KEYS with nothing under it.

❌  a spec-alignment claim has nothing behind it:
    • @object-ui/core claims spec alignment on 1 declaration that references nothing from the spec:
        `HOST_DISPATCH_ACTION_KEYS`  packages/core/src/actions/actionKeys.ts:318  (claim: "mirrors")

The gate is right, and its own third prescription applies — "delete the sentence, because it is
not true here". This list derives from nothing in @objectstack/spec and must not, so the
wording now states that negative outright instead of implying a positive. Re-run: exit 0,
spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages (the
pre-existing ledger; this symbol is not among them). Recorded rather than quietly fixed, because
the gate that catches you is worth more than the list you were handed.

Changeset — core's published surface moves this time

HOST_DISPATCH_ACTION_KEYS reaches @object-ui/core's package entry (actions/index.ts →
src/index.ts, both export *), verified by importing the built package entry rather than
the source: ["overrideNotice"], KNOWN_ACTION_KEYS.has('overrideNotice') true, set size 65.
So .changeset/host-dispatch-action-keys-5611.md declares a real patch on @object-ui/core.

The items-1–3 changeset kept its empty frontmatter but lost one sentence that item 4 made false —
it claimed @object-ui/core was untouched. It now names the second changeset instead. Both are
counted by the gate: 7 source file(s) of 2 released package(s) changed, and this change declares 2 changeset(s).

Verification — union re-run AFTER the final commit eeaa7eb, tree clean

Every exit captured before any pipe; each verdict below is the gate's own printed line.

  • @object-ui/core — vitest run packages/core/ → Test Files 93 passed (93) / Tests 1950
    passed (1950)
    , including actionKeys.pin.test.ts, actionDef-closed-surface.test.ts and
    actionKeys.types.test.ts.
  • @object-ui/app-shell — the whole package ran green at the pre-amend tree: Test Files 489
    passed (489) / Tests 4809 passed | 1 skipped (4810)
    . The only delta between that tree and
    eeaa7eb is the docblock reword above — non-comment changed lines: 0, confined to one core
    source file — and at eeaa7eb the three suites that actually spell this key re-ran green:
    consoleActionDispatch.pin.test.ts, DeclaredActionsBar.overrideAffordance.test.tsx,
    useConsoleActionRuntime.overrideNotice.test.tsx → 3 passed / 38 passed. Declared as a
    narrowing rather than presented as a full re-run.
  • Both tsc projects, both packages — tsc --noEmit && tsc -p tsconfig.test.json, exit 0 each,
    with the script name echoed so a zero-match --filter cannot read as green. The dependency
    closure was built first (pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build, exit 0).
  • All vitest runs from the repo root — package-cwd is refused by the pnpm --filter @object-ui/app-shell test 跑的是 @object-ui/console 的 22 个文件,app-shell 自己的 276 个一个没跑,却报绿 #3378 guard.
  • Gates: check:spec-symbols ✅ · check-control-bytes OK (scanned 4694 tracked text file(s); skipped 85 binary) · check-action-forward-parity 5 surfaces checked against 39 runtime-read keys from 4 consumers; 19 justified omissions, 7 known gaps (unchanged — this card adds no
    action key to any renderer surface) · check-package-self-import No package names itself inside its own src/. · check-phantom-dependencies Every in-scope import is declared by the package that publishes it. · check-node-esm-load --specifiers-only no un-ledgered package emits an extensionless relative specifier · check-type-check-coverage 45/46 via type-check … test type-check coverage: 41/41 · check-lint-coverage 46/46 packages linted, 0 with outstanding errors (0 total) · check-changeset-presence / -no-major / -fixed ✅. Also swept
    and green: check:published-dist, check:i18n-keys, check:i18n-drift, check:i18n-dead-keys,
    check:skills-paths, check:eager-closure.
  • Lint — eslint --format json packages/core, population chosen by eslint's own config, not by
    me: 185 files, 0 errors, 513 warnings; the two changed files contribute 0 errors, 0
    warnings
    . Type-aware linting is not enabled anywhere in eslint.config.js (grep for
    projectService / parserOptions / TypeChecked exits 1, captured before any pipe), so no
    rule reads cross-file type information and this diff cannot move an untouched package's verdict.
    The repo-wide eslint . farm is CI's run and is not claimed here.

Items 1–3 generated by Claude Code
Item 4 generated by Claude Code


Generated by Claude Code

os-sales and others added 3 commits August 21, 2026 22:14
… inventory

`overrideNotice` was produced, read, and declared nowhere. `DeclaredActionsBar`
composes the dispatch as `any` and hands it over through a `dispatch as
ActionDef` cast; `useConsoleActionRuntime`'s param-collection handler took
`action?: any`. The key therefore crossed the entire producer/reader seam
without one declaration, and `warnOnUnknownActionKeys` told the author, in dev,
that a key "no reader recognizes" was present — on every privileged-override
dispatch, about a key two files read.

Same shape objectstack#4075 step 3 promoted `description` out of, and for the
stated reason: authorable-or-host-composed, forwarded, read, and undeclared.
Declaring it widens nothing — the key is already accepted at runtime through
that cast; this only makes the type layer say so.

Steps 1 and 2 move together because `actionKeys.pin.test.ts` re-derives
`ACTION_DEF_KEYS` from the interface's AST: either half alone turns the pin red.

Documented at the declaration as objectui dialect with no spec counterpart, and
in a stronger sense than `description` — that key at least derives from
`@object-ui/types`' renderer view, while this one is not authorable metadata at
all. Hand-typed `string` precisely because there is no spec field to derive
FROM. objectui#5178's ruling that it must NOT be folded into `description` is
restated at the declaration, since that is what makes a separate key correct
rather than redundant.

Co-authored-by: Claude <noreply@anthropic.com>
… any` to `ActionDef`

The payoff of the declaration in the previous commit, and the half objectui#4282
measured and backed out rather than casting to compile. With `overrideNotice`
declared, the annotation is a one-token change on each handler — `ActionDef` was
already imported by both files, so no new import and no barrel export.

This is what makes the compiler cover these two files at all. Every other read in
both handlers (`objectName`, `params`, `name`, `label`, `description`) was already
a declared field; `overrideNotice` was the only key holding the `any` in place.

Line numbers re-derived on the current tip rather than taken from the card:
`useConsoleActionRuntime.tsx:196` and `RecordDetailView.tsx:500`, both unmoved.

The rejected alternative stays rejected: casting the `overrideNotice` read at its
use site would have swapped a visible `any` for an invisible cast and re-hidden
the undeclared key.

Co-authored-by: Claude <noreply@anthropic.com>
… narrowing

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3785.8 KB 3867.2 KB
Main entry chunk (gzip) 151.7 KB 350 KB
Entry file index-CGHHcjjs.js —
Status PASS —

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

Package Size Gzipped
app-shell (index.js) 10.04KB 3.72KB
app-shell (runtime-config.js) 8.91KB 2.99KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 29.34KB 7.05KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 6.35KB 2.43KB
auth (index.js) 2.77KB 1.22KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.02KB 0.89KB
auth (useIsWorkspaceAdmin.js) 3.04KB 1.45KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 507.00KB 113.72KB
core (index.js) 4.51KB 1.80KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 159.80KB 44.33KB
fields (index.js) 238.85KB 60.13KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.22KB 3.08KB
i18n (provider.js) 23.13KB 7.63KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.95KB 10.97KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.55KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.35KB 3.31KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.42KB 1.42KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 1.81KB 0.83KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.65KB 18.32KB
plugin-chatbot (index.js) 181.41KB 43.22KB
plugin-dashboard (index.js) 128.33KB 32.93KB
plugin-designer (index.js) 212.30KB 42.80KB
plugin-detail (index.js) 242.16KB 60.90KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 125.07KB 30.43KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 200.79KB 54.26KB
plugin-kanban (index.js) 52.93KB 14.60KB
plugin-list (index.js) 111.70KB 27.17KB
plugin-map (index.js) 20.06KB 6.62KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.49KB 11.93KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.50KB 20.68KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 43.66KB 14.77KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.33KB 0.69KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (index.js) 4.77KB 2.16KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 10.76KB 3.17KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 6.92KB 2.40KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.08KB 1.53KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

… the seam

Reworks this branch to the ruled narrow-B shape (maintainer ruling 2026-08-22).
`packages/core` returns to base: the published `ActionDef` stays closed and
`ACTION_DEF_KEYS` gains nothing, because `overrideNotice` is the first action key
no author supplies — declaring it on the authored-metadata mirror would make an
unenforced key legally writable in metadata.

Instead the key is declared at the dispatch seam, in the one package where its
producer (`DeclaredActionsBar`) and its reader (`useConsoleActionRuntime`) both
live: `ConsoleActionDispatch = ActionDef & { overrideNotice?: string }`.

- `DeclaredActionsBar` composes the dispatch AS that type; the
  `dispatch as ActionDef` cast is gone and `execute(dispatch)` needs none.
- Both param-collection handlers narrow off `action?: any` to the envelope,
  which is what puts those functions under the compiler at all.
- A compiler-driven pin compiles the same seven cases against BOTH types and
  asserts the delta between them is exactly `overrideNotice` — so dropping the
  key from the envelope and declaring it on `ActionDef` each turn it red.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012u2pRjcqAYtoEjgr3wwhnK
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3914.3 KB 3990.2 KB
Main entry chunk (gzip) 152.2 KB 350 KB
Entry file index-AmuAx78x.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 10.04KB 3.72KB
app-shell (runtime-config.js) 12.80KB 4.47KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 29.34KB 7.05KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 9.63KB 3.74KB
auth (index.js) 2.77KB 1.22KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.02KB 0.89KB
auth (useIsWorkspaceAdmin.js) 3.04KB 1.45KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 507.01KB 113.85KB
core (index.js) 4.92KB 1.97KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 160.15KB 44.52KB
fields (index.js) 238.40KB 59.89KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 23.13KB 7.63KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.95KB 10.97KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.55KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.53KB 3.38KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.64KB 1.50KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 1.93KB 0.88KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.65KB 18.32KB
plugin-chatbot (index.js) 181.41KB 43.22KB
plugin-dashboard (index.js) 128.41KB 32.95KB
plugin-designer (index.js) 212.30KB 42.80KB
plugin-detail (index.js) 242.34KB 60.98KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 125.63KB 30.64KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 200.79KB 54.26KB
plugin-kanban (index.js) 52.93KB 14.60KB
plugin-list (index.js) 111.80KB 27.20KB
plugin-map (index.js) 20.06KB 6.62KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.49KB 11.93KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.61KB 20.74KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 43.66KB 14.77KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.33KB 0.69KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (index.js) 4.77KB 2.16KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 10.76KB 3.17KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 6.92KB 2.40KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.59KB 1.79KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-sales os-sales changed the title feat(core): declare overrideNotice on ActionDef, then narrow both param handlers' action?: any Carry overrideNotice on a dispatch envelope at the seam, not on ActionDef (#5611) Aug 22, 2026
…ops crying wolf

`ActionRunner.execute` classifies the object it was HANDED, and a console host
hands it a DISPATCH rather than a stored metadata row. Every list feeding
`KNOWN_ACTION_KEYS` restated an AUTHORED surface, so `overrideNotice` — composed
by `DeclaredActionsBar` on the privileged-override branch and read by both
param-collection handlers — was reported as a key "no reader recognizes", with a
prescription to promote it to an explicit field on `ActionDef`. That is the one
shape the 2026-08-22 ruling forbids for this key, so acting on the diagnostic
walked an author into a rejected design as well as a red pin. The path it fires
on is the branch that finalises an approval over approvers who have not acted.

Adds `HOST_DISPATCH_ACTION_KEYS` (sole member `overrideNotice`) and unions it
into `KNOWN_ACTION_KEYS` as its fourth input — the first that is not an
authored-surface restatement. Documented at the declaration in the style of the
in-file precedent `HOST_STASHED_PARAM_KEYS`, which models the same category one
level down, inside `params`.

The authored surface does not move, and the pins say so by name: `overrideNotice`
is not declared on `ActionDef`, not in `ACTION_DEF_KEYS`, not in
`SPEC_ACTION_KEYS`, asserted off the interface's own AST. The new list's contents
are pinned exactly, because the set is the ruling's scope and a second member
must not be able to arrive quietly.

The declaration's docblock says outright that it claims no derivation from
`@objectstack/spec`. A first draft called the other three lists "mirrors" of the
surfaces they restate, and `check:spec-symbols` read that as a spec-alignment
claim standing behind this symbol with nothing under it — the gate is right, so
the wording states the negative instead of implying the positive.

Measured on the exact dispatch the bar composes: `KNOWN_ACTION_KEYS.has` false to
true, unknown `['overrideNotice']` to `[]`, warn count 1 to 0, the key set grown
by exactly one member with none removed, and a real typo riding the same dispatch
still warned about — naming `targt` alone.

Part of #5611
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3914.3 KB 3990.2 KB
Main entry chunk (gzip) 152.2 KB 350 KB
Entry file index-DHs6kHQ8.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 10.04KB 3.72KB
app-shell (runtime-config.js) 12.80KB 4.47KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 29.34KB 7.05KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 9.63KB 3.74KB
auth (index.js) 2.77KB 1.22KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.02KB 0.89KB
auth (useIsWorkspaceAdmin.js) 3.04KB 1.45KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 507.01KB 113.85KB
core (index.js) 4.92KB 1.97KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 160.15KB 44.52KB
fields (index.js) 238.40KB 59.89KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.44KB 1.39KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 23.13KB 7.63KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 33.40KB 8.71KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.95KB 10.97KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.55KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useResponsiveConfig.js) 1.37KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.53KB 3.38KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.64KB 1.50KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 1.93KB 0.88KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.65KB 18.32KB
plugin-chatbot (index.js) 181.41KB 43.22KB
plugin-dashboard (index.js) 128.41KB 32.95KB
plugin-designer (index.js) 212.30KB 42.80KB
plugin-detail (index.js) 242.34KB 60.98KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 125.63KB 30.64KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 200.79KB 54.26KB
plugin-kanban (index.js) 52.93KB 14.60KB
plugin-list (index.js) 111.80KB 27.20KB
plugin-map (index.js) 20.06KB 6.62KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 43.49KB 11.93KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.61KB 20.74KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 43.66KB 14.77KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.33KB 0.69KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (index.js) 4.77KB 2.16KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 10.76KB 3.17KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 6.92KB 2.40KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.59KB 1.79KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-zhuang
os-zhuang marked this pull request as ready for review August 22, 2026 18:11
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 22, 2026
Merged via the queue into main with commit 7138bc1 Aug 22, 2026
23 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5611-overridenotice-declaration branch August 22, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants