Repository navigation
fix(plugin-detail): show an object-level rule refusal without the _record label - #13296
Merged
objectstack-fleet[bot] merged 1 commit intoOct 21, 2026
Merged
Conversation
…record label (objectui#13292) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
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
|
objectstack-fleet
Bot
deleted the
claude/issue-13292-record-level-refusal
branch
October 21, 2026 04:13
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 free
to 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 #13292
Clause-②: no
What changed
InlineEditSaveBar(@object-ui/plugin-detail) now sorts aVALIDATION_FAILEDrefusal into field-level and record-level entries before presenting it.fieldis the_recordsentinel (the engine's documented name for an object-level rule: ascriptrule, or a rule whosefieldsis empty), or names no field of the record. Its message shows alone in the banner, with no label in front of it, and it is not published as a per-field hint. This matches howform.tsxfalls back to the envelope text for entries that name no rendered field.extractFieldErrors(shared, in@object-ui/react) is not changed. The decision is made in the save bar (ruling 4).How "a field of the record" is decided. The bar has no object schema, so it uses what it can see. A name counts as a field when:
data); orfieldLabelForresolves it to a label other than the machine name. The console host echoes the machine name back for an unknown field, so that answer counts as no label._recordis always record-level, whatever these signals say.Record-level lines in the banner. They are kept in local state beside the exact
errortext they were rendered into. They show only while the session'serroris still that text. The context's own clears (enter(), teardown, the next save) therefore retire them, with no second reset path.Pins (
InlineEditSaveBar.recordLevelRefusal-13292.test.tsx)_recordentry: the banner text is exactly the rule message,_recordappears nowhere in the document, and no hint is published.fieldnaming a non-existent field: the same as (a).converted) still shows "Converted: message" and publishes its hint._recordmessage is bare, and onlystatusis published as a hint.Existing pin adjusted. In
InlineEditSaveBar.serverVerdictFieldHint-6868.test.tsx, the test "falls back to the field machine name when the host resolves no label" refusedclose_date. That name was neither staged nor in the record, so under ruling 1 it can no longer be told apart from a non-existent field. The test now putsclose_dateon the record (data), which keeps what it pins: a real field with no host label falls back to its machine name.Ablation (one-off, no permanent file)
I mutated the split condition through
scripts/ablation-replace.mjs, so that every entry is labelled again: anchorif (entry.field !== RECORD_LEVEL_FIELD && isRecordField(entry.field)) {x1 -> x0, replacement x0 -> x1. The blob changed 2861661d -> a1929103.git checkout HEAD -- …under anEXIT INT TERMtrap with an absolute path. The blob after restore is 2861661d3901a20672537abdcf8f758115b9d911, equal to the HEAD blob.git diff HEADis 0 bytes, and the marker count is 0.dist/leg.Gates (at 8338edd)
--maxWorkers=1, under the shared lock:InlineEditSaveBar.*files: 30 passed;InlineEditSaveBar, plusDetailSection.inlineEdit.test.tsx: 147 passed | 10 skipped. The skips are thedescribe.runIf(DRIVEN)timezone legs.packages/plugin-detail/directory is declared to CI.turbo run build --filter='@object-ui/plugin-detail^...': 11/11 tasks.pnpm --filter @object-ui/plugin-detail run type-check(bothtsclegs) exit 0. The test tsconfig lists the new test file.eslint --no-inline-confignarrowed to the 3 changed.ts(x)files: 0 errors, 9no-explicit-anywarnings. All 9 are on lines this diff does not touch. Measured on a shared box.--format jsonoutput (3 results).eslint.config.jssets noparserOptions.project/projectService(type-aware linting is off), so this diff cannot change the verdict on any untouched file. The repo-widepnpm lintis CI's.check:phantom-deps,self-import,unreferenced-sources,doc-example-readers,handler-key-reads,side-effects-array,element-data-source-declaration,spec-symbols,action-forward-parity,designer-field-key-parity,icon-record-names,i18n-keys,i18n-drift,i18n-designer-parity,control-bytes,new-line-citations,scripts/check-hand-rolled-comment-mask.mjs,scripts/check-changeset-fixed.mjs,scripts/check-changeset-presence.mjs.Acceptance notes
packages/app-shell(RecordDetailView), which is outside this card's file surface. It is not done here..changeset/13292-record-level-refusal.md(@object-ui/plugin-detailpatch).Generated by Claude Code