Repository navigation
feat(lint): dashboard and report advisories carry a localized user sentence - #33118
Conversation
…ntence The widget-binding and chart-binding rules' advisory ids that the publish door returns gain a sibling user-text catalog (all 11 platform locales), userTextParams at each push site, and a merge into FINDING_USER_TEXT_CATALOG. Rule ids, message and hint are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibyUPga1xgca5r6vaew
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 2 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 e9c7975a4c92af846c50f578a922c4395f05e3f3 && git checkout e9c7975a4c92af846c50f578a922c4395f05e3f3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e997113cb058b6eb733179612fff608828e282a6 715ce9e360f7706a34aa8bac1c8b0f3897f68ad0 && git checkout -B drift-repro e997113cb058b6eb733179612fff608828e282a6 && git merge --no-ff 715ce9e360f7706a34aa8bac1c8b0f3897f68ad0
node scripts/docs-audit/affected-docs.mjs --json e997113cb058b6eb733179612fff608828e282a6
|
|
domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9 维护者速读
席位意见:可以落地。 席位核对ACCEPT · seat
|
Requested by Tesla · project thread
Fixes #32837
Clause-②: no
Metadata-protocol: none
维护者速读
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-widget-bindings.user-text.ts(7 条的各语言文案)、packages/lint/src/validate-chart-bindings.ts(只在报表图表系列条目上带参数的那两处)、packages/lint/src/finding-user-text.dashboards.test.ts。pnpm --filter @objectstack/lint exec vitest run src/finding-user-text.dashboards.test.ts,应见 24 个测试全绿,其中两条是从发布门(仪表盘写入、报表写入)拿到的提示渲染成能被RuntimeAuthoringIssueSchema解析的userMessage。What changes
Layer 1 of #32654 for the dashboard and report 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 (11 ids, a static-scan upper bound) was checked by running every warning push site of the three files whole-stack and through
runRuntimeAuthoringRulesonmain2c98485d. Nine ids reach the publish door; two do not:validate-widget-bindings.ts(dashboard write)widget-legacy-analytics-shape,dashboard-filter-field-unprovisioned,chart-field-unknown(x-axis site, and the y-axis/series site),chart-measures-missing,widget-measures-missing,chart-dimensions-missing,table-count-onlymeasure-aggregate-incoherentvalidate-chart-bindings.ts(report write, a report chart'sseries[]entry)chart-measure-unknown,chart-axis-not-selectedvalidate-page-visualization-bindings.tspage/visualization-without-bindingThe seat agreed to cover the nine only (thread record, 14:18Z). See Acceptance notes for why the two stay on the English
message.packages/lint.validate-widget-bindings.user-text.ts(new, beside the rule): the 7 widget ids' sentences in all 11PLATFORM_LOCALE_TAGS, in the dashboard editor's terms fromui/packages/i18n(dashboard, widget, dataset, dimensions, values, measure, metric).chart-field-unknownhas one arm per position (axis:x,y,series) andwidget-measures-missingone per what the widget fails to show (shows:numberfor the metric family,tablefor the tabular one), as the rule's message does.validate-chart-bindings.user-text.ts(new): the 2 chart ids' sentences, addressed to the report's chart series entry, the one advisory position the door reaches.chart-axis-not-selectednames the measure the chart plots.validate-widget-bindings.tssetsuserTextParamsat the 8 push sites of the 7 ids (bothchart-field-unknownsites);validate-chart-bindings.tssets it on the two ids'report-seriesfindings only, carrying the report name on the report chart binding (ChartBinding.report). Both finding interfaces gainuserTextParams?. A query-positionchart-measure-unknown(an error) and the page-chart presentation positions (judged on pages, which no per-write snapshot carries) carry none. Rule ids,messageandhintare unchanged.finding-user-text.ts:FINDING_USER_TEXT_CATALOGmerges the two catalogs beside the security one viamergeUserTextCatalogs.SECURITY_POSTURE_USER_TEXTis.Changeset.
.changeset/32837-advisory-user-text.md,@objectstack/lintpatch, withClause-②: noandMetadata-protocol: none. Precedent followed: #32790 (the #32655 PR) declaredMetadata-protocol: addedonly because@objectstack/specgained the authorableRuntimeAuthoringIssueSchema.userMessagekey, and it shipped itspackages/linthalf (catalog, params, merge) aspatch. This PR is that lint half alone: no spec key, no accepted value, nothing a metadata author writes changes, sononeandpatch.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
6f88ae2d(main2c98485d). The head715ce9e3mergesmaine997113cthroughscripts/pm/os-regen-merge.sh(3 incoming commits: a hook description inpackages/spec, a skills reference, PM docs; none touchespackages/lint; no conflict; no generated artifact left to regenerate). After the merge:pnpm --filter @objectstack/spec buildthencheck:generated(all 14 artifacts up to date), and the two user-text pin files, 52 passed (52),VERDICT command-exit 0.packages/lint/src/finding-user-text.dashboards.test.ts(new, 24 tests):FINDING_USER_TEXT_CATALOGserves; the 9 ids are pinned by value;widget-measures-missingarms and all threechart-field-unknownpositions, and both chart ids): severitywarning, the exact params, every locale truthy, noundefinedor template residue, every interpolated name present, and no English stand-in in any non-English locale;chart-field-unknownarms render apart in every locale, and the twowidget-measures-missingarms differ in every locale;chart-axis-not-selectednames the plotted measure;chart-measure-unknownerror, a page chart's two presentation warnings, andmeasure-aggregate-incoherent;dashboardwrite'schart-dimensions-missingand areportwrite'schart-axis-not-selectedcome out ofrunRuntimeAuthoringRuleswith their params, and the rendereduserMessage(zh-CN request; fr-FR request in a zh-CN workspace) parses underRuntimeAuthoringIssueSchemabeside the unchanged rule id and message.pnpm --filter @objectstack/lint test: Test Files 203 passed (203), Tests 8639 passed (8639),VERDICT command-exit 0.pnpm --filter @objectstack/lint typecheck(tsc --noEmitandcheck:test-typecheck): exit 0.@objectstack/metadata-protocol, which runs the gate on every save): Test Files 337 passed, 7 skipped (344); Tests 22799 passed, 36 skipped;VERDICT command-exit 0.Ablations (committed first at 6f88ae2, mutated through scripts/ablation-replace.mjs, restored to the HEAD blob)
validate-widget-bindings.ts: dropuserTextParamsat thetable-count-onlypush sitevalidate-chart-bindings.ts: dropreport: reportNamefrom the report chart bindingEach mutation landed (anchor 1 → 0, blob changed) and each restore read
blob == HEAD and git diff HEAD is empty.Acceptance notes
measure-aggregate-incoherentis judged ondatasets[]; a dashboard write carries the live datasets as context in both differential passes, so the finding cancels, and a dataset write does not runvalidateWidgetBindings(its registry entry declaresruntimeTypes: ['dashboard']).page/visualization-without-bindingis a reference-integrity member on the frozenflowdefault, and no per-write snapshot carriespages[]; a page write does not dispatch it. 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.zh-Hans,zh-Hant,es,ar,fr,pt-BR,ru,de,ja,ko) × 9 entries, 13 sentences per locale counting arms (widget-legacy-analytics-shape,dashboard-filter-field-unprovisioned,chart-field-unknown×3,chart-measures-missing,widget-measures-missing×2,chart-dimensions-missing,table-count-only,chart-measure-unknown,chart-axis-not-selected). Points worth a native reader's eye:deuses the console's "Datensatz" for dataset, sotable-count-onlysays "Einträge" for records to avoid the clash;aruses the console's "مقياس" both for the metric widget type and for a measure, so the metric widget is spelled "عنصر من نوع مقياس"; Korean particles are written in the dual form (을(를),이(가)) because the name is interpolated.finding-user-text.test.ts. The pins sit infinding-user-text.dashboards.test.tsso this card and its parallel sibling 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 do not both grow the precedent's file; the shape is the same. Moving them into that file is a mechanical follow-up if the seat prefers it.validate-expressions.ts; this PR does not touch it. 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 also adds one line tofinding-user-text.ts; whichever lands second mergesmainand keeps both catalogs.Verification
Local subset at
6f88ae2d(the merge brought in no file this derivation reads, and the change set againstmainis the same 7 paths), derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(60 families), every line run with stdin closed and its exit code captured before any pipe, then reconciled with--ran: 60 derived, 60 run, 0 NOT-MEASURED (a derived zero: all 60 recorded an exit code, none is 3). All 60 exit 0. The record isspec-seat-2/r2026-11-13/out/32837-gates-ran-6f88ae2d.listin the project files.Four families needed a prerequisite before their reading
node scripts/check-plugin-teardown-shape.mjs --self-test: exit 3 on the shallow clone (pinned fixture commit621a4876absent); exit 0 after fetching that commit.pnpm check:dts-closure: exit 1 (a consumer closure built without declarations); exit 0 after a full workspace build with declarations.pnpm check:dual-build-cjs-loads,pnpm check:lean-entry-closure: exit 3 PREREQUISITE NOT MET (no dist); exit 0 after the same full build.node scripts/check-cli-command-ids.mjs(run after editing the catalogs, since a pt-BR or es sentence opening with "os " trips it): exit 0, 1322 command-id literals resolve.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