Repository navigation
feat(lint): form layout, visibility and page-sort advisories carry a localized user sentence - #33143
Conversation
…isories carry a localized user sentence Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibyb4HJHsnssCRLUw4F
… from real findings and the publish door Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibyb4HJHsnssCRLUw4F
…ences Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibyb4HJHsnssCRLUw4F
…-168lt2 # Conflicts: # packages/lint/src/finding-user-text.ts # packages/lint/src/validate-sortable-fields.ts
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 4 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 35706675750a8399c0604a75a7adc217a454d378 && git checkout 35706675750a8399c0604a75a7adc217a454d378
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin bf02d33bd64f496aa8166e1a235ef10977927947 40ff8f9149359b0ac7a49cb8e261ed5d2b0475e2 && git checkout -B drift-repro bf02d33bd64f496aa8166e1a235ef10977927947 && git merge --no-ff 40ff8f9149359b0ac7a49cb8e261ed5d2b0475e2
node scripts/docs-audit/affected-docs.mjs --json bf02d33bd64f496aa8166e1a235ef10977927947
|
|
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9 维护者速读
席位意见:可以落地。 席位核对ACCEPT · seat
|
Requested by Tesla · project thread
Fixes #32840
Clause-②: no
Metadata-protocol: none
维护者速读
data./record.)、页面按外部对象并不存储的列排序,共 4 条规则 id;规则 id、message、hint一字不变。userMessage(那是 server: userMessage producers and the save door compose user-facing text in requestLocale (ruling C on #32440, layer 2) #32656),所以所有返回内容不变。@objectstack/lint按 patch 发版。回滚即 revert。packages/lint/src/validate-visibility-predicates.user-text.ts(按root分两种写法、按视图/页面换名词)、packages/lint/src/validate-form-layout.ts(字段分组提示的参数在调用处补上,共享 helper 不动)、packages/lint/src/finding-user-text.pages-forms.test.ts。pnpm --filter @objectstack/lint exec vitest run src/finding-user-text.pages-forms.test.ts,应见 26 个测试全绿,其中三条是从发布门(两次视图写入、一次页面写入)拿到的提示渲染成能被RuntimeAuthoringIssueSchema解析的userMessage。What changes
Layer 1 of #32654 for the page, form, navigation and translation advisories, in the pattern #32655 landed (
validate-security-posture.user-text.ts,finding-user-text.test.ts), under ruling record 6819749037 (option C).Re-measured first. The card's table (9 ids in 8 files, a static-scan upper bound) was checked on
origin/main5b2ec820: each advisory was planted in a whole stack, confirmed by calling its rule, and then every item of that stack was written throughrunRuntimeAuthoringRules(typesobject,view,page,app,flowas the stack held them) with the snapshot context the door carries.validate-form-layout.tsform-field-unknown,form-section-group-unknown(card: 1)validate-visibility-predicates.tsvisibility-root-mislayeredvalidate-page-field-bindings.tspage-field-unprovisioned,page-field-unknown(itsskippedgrade),page-section-group-unknown(card: 1)page-field-unprovisionedonly at the page-sort site invalidate-sortable-fields.ts(page); none at this rule's own sitesvalidate-react-page-props.tsreact-page-source-unparseable,react-prop-deprecated,react-prop-typo,react-chart-aggregate-invalid(its warning arm),react-chart-field-unprovisioned(card: 2)validate-nav-access.tsnav-object-ungrantedvalidate-nav-target-refs.tsnav-target-unresolvedvalidate-translation-references.tstranslation-option-key-unknownvalidate-translatable-sections.tstranslation-section-name-missingSo 4 ids reach the door and get a sentence; the seat agreed to cover those and name the rest (see Acceptance notes).
packages/lint.PLATFORM_LOCALE_TAGSand in the console's terms fromui/packages/i18n(view, page, form, section, field, field group, object, external object, sort, thevisibleWhenrule as the record form names it):validate-form-layout.user-text.ts:form-field-unknown(view,object,field) andform-section-group-unknown(view,object,group).validate-visibility-predicates.user-text.ts:visibility-root-mislayered(surface,name,root). One arm perroot:dataon a runtime view or page (writerecord.),recordon a metadata-editing form (writedata.), as the rule's message does;surfacepicks the noun (view or page).validate-page-field-bindings.user-text.ts:page-field-unprovisioned(page,object,field), addressed to the page whose sort is ignored.validate-form-layout.tssetsuserTextParamsat the section-field site, and adds them tocheckSectionGroupRefs' findings at its call site (keyed by each finding'spath, which is its reference's). The shared helper inobject-field-groups.tsis untouched: its other host emitspage-section-group-unknown, which the door never returns.validate-visibility-predicates.ts:checkElementtakes the element's owner ({ surface, name }, passed by its three callers) and sets the params at the mislayered-root site only.validate-sortable-fields.ts:checkPageSortDeclarationtakes the page name (passed by all five page-sort callers) and sets the params at itspage-field-unprovisionedsite.userTextParams?. Rule ids,messageandhintare unchanged. No registry adapter drops the field (validateFormLayout,validateVisibilityPredicatesand the reference-integrity suite pass findings through), soauthoring-rules.tsis untouched.finding-user-text.ts:FINDING_USER_TEXT_CATALOGmerges the three catalogs viamergeUserTextCatalogs.SECURITY_POSTURE_USER_TEXTis.Changeset.
.changeset/32840-advisory-user-text.md,@objectstack/lintpatch, withClause-②: noandMetadata-protocol: none. Precedent followed: #32837 (PR #33118), the sibling sub-card, declarednoneandpatchfor the same lint-only change, reading #32790 (the #32655 PR): itsaddedcame only from the@objectstack/speckeyRuntimeAuthoringIssueSchema.userMessage, and it shipped the lint half aspatch. This PR moves no spec key and no accepted value.Not in this PR. The save door composing
userMessage(#32656) and the console rendering it (#32657). Until #32656 lands, every save and publish response is byte-identical.Tests
Counts from the merged head
40ff8f91(branch tipd2634c67onmain5b2ec820, thenmaindd4ce50bmerged throughscripts/pm/os-regen-merge.shonce #33140 landed). The merge conflicted in two files only, both resolved by keeping both sides:finding-user-text.ts(the catalog import and merge lists now carry #33140's four and this PR's three) andvalidate-sortable-fields.ts(oneuserTextParamsfield onSortableFieldFinding, its docblock now naming both the list-view and the page-sort sites; the duplicate type import dropped). #33140's own pin that asserted the page-sortpage-field-unprovisionedwarning carries no params is replaced by a pointer to this PR's pin, and its catalog note invalidate-sortable-fields.user-text.tsnow names the catalog that site feeds. No generated artifact left to regenerate;pnpm --filter @objectstack/spec check:generatedexit 0 after a fullpnpm turbo run build(120/120 tasks).packages/lint/src/finding-user-text.pages-forms.test.ts(new, 26 tests):FINDING_USER_TEXT_CATALOGserves; the four ids are pinned by value;config; the section-group site from both thesectionsand the legacygroupsbucket; the mislayered root from a view section, a view field, a page component and a metadata-editing form; the page-sort site from all five callers:interfaceConfig,record, a block'ssort, a block'sdataSourceand a related list'sparentDataSource): severitywarning, the exact params, every locale truthy, noundefinedor template residue, every interpolated name present, and no English stand-in in any non-English locale;rootarms and the view and page nouns render apart in every locale;viewwrites (the section-group advisory, whose params come from the call-site mapping, and the unknown field) and onepagewrite (the unstored sort and the mislayered root) come out ofrunRuntimeAuthoringRuleswith their params, and the rendereduserMessage(de-DE, ja-JP, zh-CN, fr-FR requests) parses underRuntimeAuthoringIssueSchemabeside the unchanged rule id and message.VERDICT command-exit 0.pnpm --filter @objectstack/lint test: Test Files 205 passed (205), Tests 8762 passed (8762),VERDICT command-exit 0.pnpm --filter @objectstack/lint typecheck:VERDICT command-exit 0.@objectstack/metadata-protocol, which runs the gate on every save; after the full build): Test Files 337 passed, 7 skipped (344); Tests 22799 passed, 36 skipped (22835);VERDICT command-exit 0.Ablations (committed first, mutated through scripts/ablation-replace.mjs, restored to the HEAD blob)
validate-form-layout.ts: the call-site mapping setsgroup: ''instead of the reference's keyvalidate-sortable-fields.ts: dropuserTextParamsat the page-sort siteEach mutation landed (anchor 1 → 0, blob changed) and each restore read
blob == HEAD and git diff HEAD is empty.Acceptance notes
react-page-source-unparseable,react-prop-deprecated,react-prop-typo,react-chart-aggregate-invalid,react-chart-field-unprovisioned,nav-object-ungranted,nav-target-unresolved,page-field-unknown(skippedgrade),page-section-group-unknown,translation-option-key-unknownandtranslation-section-name-missing, pluspage-field-unprovisionedatvalidate-page-field-bindings.ts's own sites. Their rules are reference-integrity members on the frozenflowdefault (reference-integrity-suite.ts, noruntimeTypes), so the door runs them only on a flow write, and a flow write's snapshot carries no pages, apps or translations (RuntimeStackContextholds objects, permissions, books, datasets, flows).translation-section-name-missingon an object's own sections is context on both sides of the differential and cancels. A sentence the door can never render would be declared but not delivered. A pin asserts each of them has no catalog entry.validate-react-page-props.tsemits 5 advisory ids, not 2 (react-prop-typois a literal, not a constant, and two chart ids warn on one arm);validate-form-layout.tsemits 2, not 1 (form-section-group-unknownis pushed through the shared helper);validate-page-field-bindings.tsemits 3, not 1. None of the extra ids of the react and bindings rules reaches the door either.page-field-unprovisioned's catalog lives with its owner. The constant and its own push sites arevalidate-page-field-bindings.ts's, so the catalog isvalidate-page-field-bindings.user-text.ts, and its sentence speaks of a sort: the page-sort site invalidate-sortable-fields.tsis the only one that carries params. lint: the the data model: objects, fields, sorting, search, record titles and autonumbers advisories carry a localized user sentence (10 rule ids in 6 rule files), per ruling C on #32440 #32838 (PR feat(lint): data-model advisories carry a localized user sentence #33140) left this id to this card by name.zh-Hans,zh-Hant,es,ar,fr,pt-BR,ru,de,ja,ko) × 4 entries, 5 sentences per locale counting the tworootarms (form-field-unknown,form-section-group-unknown,visibility-root-mislayered×2,page-field-unprovisioned), each with the view or page noun. Points worth a native reader's eye:zh-Hantwrites "區段" for section, where the console's own string reads "分割槽" (a conversion of the Simplified "分区" that means partition);kouses the console's "보기" for view;aruses "العرض" for view; Korean particles are written in the dual form (이(가),은(는)) because the name is interpolated; the external-object sort sentence follows the wording of the landedsort-field-unprovisionedanddashboard-filter-field-unprovisionedsentences;visibleWhen,data.andrecord.stay untranslated, as the console's ownvisibleWhenrefusal keeps the key.finding-user-text.test.ts. The pins sit infinding-user-text.pages-forms.test.ts, as lint: the dashboards, charts and widgets advisories carry a localized user sentence (11 rule ids in 3 rule files), per ruling C on #32440 #32837's sit infinding-user-text.dashboards.test.ts, so parallel sibling cards do not collide; the shape is the same.ruling|Ruling-ref|maintainer|⛔):validate-visibility-predicates.ts27 (the parse-only, unknown-function andhas()rulings, all on the gating ids),validate-sortable-fields.ts3 (type-list notes),validate-form-layout.ts1 (the colSpan note),validate-page-field-bindings.ts1 (ruling B on a related list's object),finding-user-text.ts2 (ruling record 6819749037 and the one-locale-list rule); none constrains a user sentence or the push-site params.Verification
Local subset at the merged head
40ff8f91, derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(62 families, 11 paths against merge basedd4ce50b), every line run with stdin closed and its exit code captured before any pipe, then reconciled with--ran: 62 derived, 62 run, 0 NOT-MEASURED (a derived zero: all 62 recorded an exit code, none is 3). All 62 exit 0. The record isspec-seat-2/r2026-11-13/out/32840-gates-ran-40ff8f91.listin the project files. The pre-merge headd2634c67read the same (61 derived, 61 exit 0).Prerequisites before some readings
node scripts/check-plugin-teardown-shape.mjs --self-test: its pinned fixture commit621a4876was fetched first (shallow clone).pnpm check:docs-transcript-drift,pnpm check:dual-build-cjs-loads,pnpm check:lean-entry-closure,pnpm check:type-check-debt: read after a fullpnpm turbo run build(before it, the first answered exit 3 PREREQUISITE NOT MET, no lint dist).node scripts/check-cli-command-ids.mjs(run after editing the catalogs, and again on the merged head): exit 0.node scripts/check-nul-bytes.mjs: exit 0.CI runs the rest of the farm on this PR; its check-runs are the reading for every family outside the local subset.
Generated by Claude Code