Uh oh!
There was an error while loading. Please reload this page.
feat(core): declare overrideNotice on ActionDef, then narrow both param handlers' action?: any - #5644
Draft
os-sales wants to merge 3 commits into
Draft
feat(core): declare overrideNotice on ActionDef, then narrow both param handlers' action?: any#5644os-sales wants to merge 3 commits into
overrideNotice on ActionDef, then narrow both param handlers' action?: any#5644os-sales wants to merge 3 commits into
Conversation
… 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>
Contributor
✅ 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
|
This was referenced Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#5611
overrideNoticewas produced, read, and declared nowhere.DeclaredActionsBarcomposes the dispatch asanyand hands it to the runner through adispatch as ActionDefcast (DeclaredActionsBar.tsx:305,:312);useConsoleActionRuntime's param-collection handler tookaction?: any. The key crossed the entire producer/reader seam without one declaration — which is whywarnOnUnknownActionKeystold the author, in dev, that a key "no reader recognizes" was present, on every privileged-override dispatch, about a key two files actually read. Fixing that is restoring an invariant, not adding a feature.Three commits, in the order the pin requires.
1. Fresh diagnostics re-measured on the current tip, before anything was written
The card's three
TS2339s were measured at7a28e1e3f, before #5610 landed, and triage flagged them as stale in the direction that matters. Re-run onf1c27f037by applying only the narrowing (no declaration), then reverting:overrideNotice-only, no fourth key ⇒ the grading is confirmed and nothing comes back to triage.Details worth stating rather than assuming:
type-checkistsc --noEmit && tsc -p tsconfig.test.json, and the&&short-circuits — the first run failing means the test project never ran. Measured separately,tsconfig.test.jsonyields the same three diagnostics and no test-call-site errors, so the list above is complete rather than truncated by a short-circuit.RecordDetailView.tsx. Its handler reads onlyobjectName/params/name/label/description, all declared. The narrowing there is free —RecordDetailViewcarries a second copy of the param dialog's deadaction?.titlefallback #5610 already removed the deadtitlelimb.2. Declaration + inventory, in one commit (
e52146ddf)actionKeys.pin.test.tsre-derivesACTION_DEF_KEYSfrom the interface's AST, so either half alone turns the pin red. Both move together.Documented at the declaration as objectui dialect with no spec counterpart, and dialect in a stronger sense than
description: that key at least derives from@object-ui/types' renderer view of an action, while this one is not authorable metadata at all — a host composes it in code. Hand-typedstringprecisely because there is no spec field to derive from. #5178's ruling that it must not be folded intodescriptionis restated there, since that is what makes a separate key correct rather than redundant: the reader resolvesdescriptionthrough the_actions.NAME.descriptionbundle key and prefers a bundle hit over the passed literal, andplugin-approvalsships exactly such an entry forapproval_reject— so a safety notice routed throughdescriptionwould be silently replaced by ordinary "Reject this request?" copy in every locale that has the bundle.This widens nothing. The key is already accepted at runtime through the
dispatch as ActionDefcast; the declaration only makes the type layer say what already happens.3. The narrowing (
d787b6dfe)Line numbers re-derived by code on the current tip rather than taken from the card — both unmoved:
useConsoleActionRuntime.tsx:196andRecordDetailView.tsx:500.ActionDefwas already imported by both files, so no new import and no barrel export; it is one token per handler.⛔ The rejected alternative stays rejected: casting the
overrideNoticeread at its use site would swap a visibleanyfor an invisible cast and re-hide the undeclared key. Turned down on #4282, not rediscovered here.Reverse verification — two controls, each with its own mutation leg, each measured failing
overrideNotice?: string;fromActionDef@object-ui/corerebuilt, and the marker proven absent fromdist/actions/ActionRunner.d.tsbefore reading anythinggit diff --numstat=0 1TS2339s return'overrideNotice'fromACTION_DEF_KEYSdistinvolved; stated rather than skipped silentlygit diff --numstat=0 1expected { missing: [ 'overrideNotice' ] } to deeply equal { missing: [], stale: [] }— 1 failed, 11 passedLeg 1's rebuild is the load-bearing step: without it the ablation reads the pre-mutation
.d.tsand reports "removing the declaration changed nothing", which is the false conclusion in the more dangerous direction. Both legs restore from a shelltraponEXIT INT TERM, and the restore was verified by re-deriving the anchor counts afterwards.Changeset
check-changeset-presence.mjsis the authority. Before:❌ 4 source file(s) of 2 released package(s) changed, and this change adds no changeset. After:minor, nevermajor(fixed group). This adds a declared field to a published interface, so the.d.tsdoes move — measured at the realdist/path, both legs clean-built after deletingdist/andpackages/core/tsconfig.tsbuildinfo(verified to live outsidedist/for this package, so clearingdist/alone would have lettscskip emit):packages/core/dist/actions/ActionRunner.d.tsf1c27f03781a74ca5…64daa795…overrideNotice?: string;linesdist/tree hashfe020e37…12c18e85…Compared by hash, not byte count. The head leg was measured again after the base leg and came back byte-identical to the pre-ablation head build, which is what rules out a stale artefact being read — and that check earned its keep: it caught a restore that had silently failed, because
git checkout BASE -- PATHstages the base content, so the follow-upgit checkout -- PATHrestored from the index rather than fromHEAD. Re-restored fromHEADand re-measured before any figure above was recorded.Verification
All at final commit
8238b453d, and the union was re-run after the last commit.@object-ui/core— build exit 0;type-checkexit 0;vitest run packages/core/src/actions/→ Test Files 23 passed (23) / Tests 407 passed (407) (includesactionKeys.pin.test.tsandactionDef-closed-surface.test.ts)@object-ui/app-shell—type-checkexit 0 (both tsc projects ran, no short-circuit);vitest run packages/app-shell/src/hooks/__tests__/ packages/app-shell/src/views/__tests__/→ Test Files 40 passed (40) / Tests 393 passed (393)vitestis refused by the repo's own guard (pnpm --filter @object-ui/app-shell test跑的是 @object-ui/console 的 22 个文件,app-shell 自己的 276 个一个没跑,却报绿 #3378).check-action-forward-parity✅ (owed sets unchanged — this key is in neither the spec vocabulary norui-action.ts, so it joins no surface's owed set),check-control-bytes✅,check-type-check-coverage✅,check-lint-coverage✅ (46/46 packages linted, 0 with outstanding errors),check-changeset-presence/-no-major/-fixed✅pnpm lintis a repo-wide farm CI owns; this is a declared narrowing to the changed files, with the evidence that the narrowing excluded nothing: (1) type-aware linting is not enabled — noprojectService,parserOptions.projectorrecommendedTypeCheckedanywhere in the config — so no rule reads cross-file type information and this diff cannot move the verdict of a file it does not touch; (2) file count read from--format json, not asserted: 4 files linted, 0 errors, 170 warnings; (3) every warning is a pre-existing@typescript-eslint/no-explicit-any, and zero fall on any added line (checked against the added ranges). The narrowing in fact removes twoanys.Known-broken gauges, noted and not touched:
check-eager-closure-budgetexits 2,check-doc-snippet-typesexits 1.Out of scope, filed not fixed
#5642 — the same warning's dev-console message states a fact step 3 retired ("
ActionDefstill carries[key: string]: any") and points the author atactionKeys.tsto add a field to an interface that lives inActionRunner.ts. That second half has teeth: following it edits only the inventory, which is exactly the half-change the pin goes red on. Different defect class from this card (shipped prose vs. a missing declaration), so it is filed unassigned rather than folded in here.Generated by Claude Code