Repository navigation
feat(lint): data-model advisories carry a localized user sentence - #33140
Conversation
The five data-model advisory ids the publish door returns gain a user-facing sentence in all 11 platform locales, in catalogs beside their rules: autonumber-unrecognized-token and autonumber-references-optional-field (lint-autonumber-formats), sort-field-unprovisioned, searchable-field-unprovisioned, and object-reference-unregistered-platform at the dataset base-object site. Each push site sets userTextParams; the lintAutonumberFormats registry adapter now passes them through. Rule ids, message and hint are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibzvBVSWuwHDeSGbNmG
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
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 b323a8a3c952575e3675e363d4e5755d01f74d10 && git checkout b323a8a3c952575e3675e363d4e5755d01f74d10
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 5b2ec820c8abca113eae23745f71331f55ec7aed 4605d6ef3740fec8a664784c882fe0fc5383c498 && git checkout -B drift-repro 5b2ec820c8abca113eae23745f71331f55ec7aed && git merge --no-ff 4605d6ef3740fec8a664784c882fe0fc5383c498
node scripts/docs-audit/affected-docs.mjs --json 5b2ec820c8abca113eae23745f71331f55ec7aed
|
|
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9 维护者速读
席位意见:可以落地。 席位核对ACCEPT · seat
|
Requested by Tesla · project thread
Fixes #32838
Clause-②: no
Metadata-protocol: none
维护者速读
message、hint一字不变。os lint的最佳实践检查),它们没有用户文案,原因写在验收说明里。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/lint-autonumber-formats.user-text.ts(两条自动编号提示、两种写法的各语言文案)、packages/lint/src/validate-object-references.ts(只在数据集基础对象这一处带参数)、packages/lint/src/finding-user-text.data-model.test.ts。pnpm --filter @objectstack/lint exec vitest run src/finding-user-text.data-model.test.ts,应见 20 个测试全绿,其中三条是从发布门(对象写入、视图写入、数据集写入)拿到的提示渲染成能被RuntimeAuthoringIssueSchema解析的userMessage。What changes
Layer 1 of #32654 for the data-model 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 (10 ids in 6 files, a static-scan upper bound) was checked by running each warning push site of the six files through
runRuntimeAuthoringRulesonorigin/main5c005e0e, withobject,view(flattened overlay and container),dataset,pageandflowwrites:lint-autonumber-formats.tsautonumber-unrecognized-token,autonumber-references-optional-field(object)validate-sortable-fields.tssort-field-unprovisioned(object, view)page-field-unprovisionedreaches it on a page write, but isvalidate-page-field-bindings.ts's id (#32840)validate-searchable-fields.tssearchable-field-unprovisioned(object, view)validate-object-references.tsobject-reference-unregistered-platform(dataset, the base-object site)data-model-rules.tsunique/double-declaration,unique/legacy-organization-composite,field/select-missing-options,relationship/master-detail-required,relationship/association-inline-editvalidate-record-title.tstitle-unresolvableThe seat agreed to cover the five and name the rest (surface amendment on the card). See Acceptance notes for each reason.
packages/lint.PLATFORM_LOCALE_TAGSand in the console's terms fromui/packages/i18n(object, field, Auto Number, record number, required, list view, external object, sort, searchable fields, dataset, remote table):lint-autonumber-formats.user-text.ts: the two autonumber ids.autonumber-unrecognized-tokenhas one arm perkind(unknown-token,second-counter), as the rule's message does.validate-sortable-fields.user-text.ts:sort-field-unprovisioned, addressed to the list view.validate-searchable-fields.user-text.ts:searchable-field-unprovisioned, one arm perrole(canonical, the object's own searchable fields;narrowing, a list's search fields), as the rule's message does.validate-object-references.user-text.ts:object-reference-unregistered-platform, addressed to the dataset.lint-autonumber-formats.tssetsuserTextParamsat both warning sites;checkSortDeclarationandcheckSearchableFieldListset it at their unprovisioned-anchor sites (so every caller of those cores carries it);validate-object-references.tssets it at the dataset base-object site only, through an optionalcheckargument. Each finding interface gainsuserTextParams?. Rule ids,messageandhintare unchanged.authoring-rules.ts: thelintAutonumberFormatsregistry adapter re-maps each field and droppeduserTextParams; it now spreads it when present (one line, the same as lint: the automation writes: approvals, flows, hooks, actions and email templates advisories carry a localized user sentence (27 rule ids in 11 rule files), per ruling C on #32440 #32836'slintFlowCredentialLiteralsline). No other entry changes.finding-user-text.ts:FINDING_USER_TEXT_CATALOGmerges the four catalogs viamergeUserTextCatalogs.SECURITY_POSTURE_USER_TEXTis.Changeset.
.changeset/32838-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 tree at
f4ce7b50(branch pointmain5c005e0e). The head4605d6efmergesmain5b2ec820throughscripts/pm/os-regen-merge.sh(one incoming commit, #33122 inpackages/specstack.zod.ts; none touchespackages/lint; no conflict; no generated artifact left to regenerate). After the merge:pnpm --filter @objectstack/spec build, thencheck:generated(all 14 artifacts up to date), and the three user-text pin files, 72 passed (72),VERDICT command-exit 0.packages/lint/src/finding-user-text.data-model.test.ts(new, 20 tests):FINDING_USER_TEXT_CATALOGserves; the five ids are pinned by value;warning, the exact params, every locale truthy, noundefinedor template residue, every interpolated name present, and no English stand-in in any non-English locale;page-field-unprovisionedwarning, and an object field's lookup site of the object-reference rule;objectwrite's autonumber advisory (through the registry adapter), aviewwrite's sort and search advisories, and adatasetwrite's object-reference advisory come out ofrunRuntimeAuthoringRuleswith their params, and the rendereduserMessage(zh-CN, fr-FR, ja-JP requests) parses underRuntimeAuthoringIssueSchemabeside the unchanged rule id and message.pnpm --filter @objectstack/lint test: Test Files 204 passed (204), Tests 8654 passed, 5 skipped (8659),VERDICT command-exit 0.pnpm --filter @objectstack/lint typecheck(tsc --noEmitandcheck:test-typecheck), thenbuild:VERDICT command-exit 0.@objectstack/metadata-protocol, which runs the gate on every save; closure built withpnpm --filter '@objectstack/metadata-protocol^...' build): Test Files 337 passed, 7 skipped (344); Tests 22799 passed, 36 skipped (22835);VERDICT command-exit 0.Ablations (committed first at f4ce7b5, mutated through scripts/ablation-replace.mjs, restored to the HEAD blob)
authoring-rules.ts: drop theuserTextParamsspread in thelintAutonumberFormatsadaptervalidate-object-references.ts: drop{ dataset: dsName }at the dataset sitevalidate-searchable-fields.ts: dropuserTextParamsat the unprovisioned siteEach mutation landed (anchor 1 → 0, blob changed) and each restore read
blob == HEAD and git diff HEAD is empty.Acceptance notes
unique/double-declarationandunique/legacy-organization-compositeare registeredCLI_ONLYwithRUNTIME_OBJECT_ADVISORY_VOLUME, and so istitle-unresolvable(validateRecordTitle).field/select-missing-options,relationship/master-detail-requiredandrelationship/association-inline-editare emitted only bylintDataModel, theos lintbest-practice sweep, which has no registry entry: no write reaches them. A sentence the door can never render would be declared but not delivered. Parent lint: every save-door advisory rule carries a localized user sentence (67 rule ids in 36 rule files remain after the security posture), per ruling C on #32440 #32835 allows naming such ids with the reason they stay on the English fallback.page-field-unprovisionedis left to lint: the pages, forms, navigation and translations advisories carry a localized user sentence (9 rule ids in 8 rule files), per ruling C on #32440 #32840.validate-sortable-fields.tspushes it at its page-sort site (a page write returns it), but its constant, its other push site and so its catalog belong tovalidate-page-field-bindings.ts, which is lint: the pages, forms, navigation and translations advisories carry a localized user sentence (9 rule ids in 8 rule files), per ruling C on #32440 #32840's table; a rule id has one catalog owner. lint: the pages, forms, navigation and translations advisories carry a localized user sentence (9 rule ids in 8 rule files), per ruling C on #32440 #32840's catalog must also setuserTextParamsat the page-sort site invalidate-sortable-fields.ts(checkPageSortDeclaration); a pin here asserts that site carries none today.flowanddatasetwrites; only a dataset's base object is on the written item. A flow write's objects, views, actions, dashboards and apps are context on both sides of the differential, so those findings cancel (measured: a flow write over context with asys_-prefixed lookup target returns none, and an object write does not dispatch the member).zh-Hans,zh-Hant,es,ar,fr,pt-BR,ru,de,ja,ko) × 5 entries, 7 sentences per locale counting arms (autonumber-unrecognized-token×2,autonumber-references-optional-field,sort-field-unprovisioned,searchable-field-unprovisioned×2,object-reference-unregistered-platform). Points worth a native reader's eye: the console has no translated "Auto Number" label outside en and zh (engine.fieldType.autonumber), so the other locales use a plain term ("numeración automática", "Autonummernfeld", "自動採番", "자동 번호", …);deuses the console's "Datensatz" for both dataset and record, which is why the dataset sentence speaks only of data ("keine Daten") and the Auto Number sentences say "Datensatznummer"; Korean particles are written in the dual form (을(를),이(가)) because the name is interpolated; the external-object clause reuses the wording of the landeddashboard-filter-field-unprovisionedsentences.finding-user-text.test.ts. The pins sit infinding-user-text.data-model.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.finding-user-text.ts; whichever lands second mergesmainand keeps every catalog line. lint: the object_extension publish door runs no field-formula judgment, so a computed field os build refuses still publishes through PUT /meta/object_extension #33072 editsvalidate-expressions.ts; this PR does not touch it.ruling|Ruling-ref|maintainer|⛔): hits invalidate-object-references.ts(9, resolution-ladder and ADR-0130 notes),validate-sortable-fields.ts(3, type-list notes),validate-searchable-fields.ts(1),finding-user-text.ts(2, ruling record 6819749037 and the one-locale-list rule),authoring-rules.ts(63, registry entries); none constrains a user sentence or the adapter line.Verification
Local subset at
f4ce7b50, derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(62 families), every line run with stdin closed and its exit code captured before any pipe, then reconciled with--ran(again on the merged head4605d6ef, same 12 paths): 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/32838-gates-ran-f4ce7b50.listin the project files.Four families needed a prerequisite before their reading
node scripts/check-plugin-teardown-shape.mjs --self-test: its pinned fixture commit621a4876was fetched first (shallow clone).pnpm check:dual-build-cjs-loads,pnpm check:lean-entry-closure: exit 3 PREREQUISITE NOT MET (no dist); exit 0 after a fullpnpm turbo run build.pnpm check:type-check-debt: run after the same full build, outside the 10-minute foreground limit; exit 0.pnpm check:dts-closureread exit 0 both before and after it.node scripts/check-cli-command-ids.mjs(run after editing the catalogs): exit 0, 1322 command-id literals resolve.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