Skip to content

feat(lint): data-model advisories carry a localized user sentence - #33140

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-91iouu
Nov 13, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-91iouu

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

Fixes #32838

Clause-②: no
Metadata-protocol: none

维护者速读

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 runRuntimeAuthoringRules on origin/main 5c005e0e, with object, view (flattened overlay and container), dataset, page and flow writes:

Rule file Door-reaching advisory ids (write) Not reaching the door
lint-autonumber-formats.ts autonumber-unrecognized-token, autonumber-references-optional-field (object) —
validate-sortable-fields.ts sort-field-unprovisioned (object, view) page-field-unprovisioned reaches it on a page write, but is validate-page-field-bindings.ts's id (#32840)
validate-searchable-fields.ts searchable-field-unprovisioned (object, view) —
validate-object-references.ts object-reference-unregistered-platform (dataset, the base-object site) the field, view, action, dashboard-filter and navigation sites
data-model-rules.ts — unique/double-declaration, unique/legacy-organization-composite, field/select-missing-options, relationship/master-detail-required, relationship/association-inline-edit
validate-record-title.ts — title-unresolvable

The seat agreed to cover the five and name the rest (surface amendment on the card). See Acceptance notes for each reason.

packages/lint.

  • Four catalogs, new, beside their rules, each in all 11 PLATFORM_LOCALE_TAGS and in the console's terms from ui/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-token has one arm per kind (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 per role (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.
  • Push sites: lint-autonumber-formats.ts sets userTextParams at both warning sites; checkSortDeclaration and checkSearchableFieldList set it at their unprovisioned-anchor sites (so every caller of those cores carries it); validate-object-references.ts sets it at the dataset base-object site only, through an optional check argument. Each finding interface gains userTextParams?. Rule ids, message and hint are unchanged.
  • authoring-rules.ts: the lintAutonumberFormats registry adapter re-maps each field and dropped userTextParams; 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's lintFlowCredentialLiterals line). No other entry changes.
  • finding-user-text.ts: FINDING_USER_TEXT_CATALOG merges the four catalogs via mergeUserTextCatalogs.
  • No new export: the catalogs stay internal, as SECURITY_POSTURE_USER_TEXT is.

Changeset. .changeset/32838-advisory-user-text.md, @objectstack/lint patch, with Clause-②: no and Metadata-protocol: none. Precedent followed: #32837 (PR #33118), the sibling sub-card, declared none and patch for the same lint-only change, reading #32790 (the #32655 PR): its added came only from the @objectstack/spec key RuntimeAuthoringIssueSchema.userMessage, and it shipped the lint half as patch. 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 point main 5c005e0e). The head 4605d6ef merges main 5b2ec820 through scripts/pm/os-regen-merge.sh (one incoming commit, #33122 in packages/spec stack.zod.ts; none touches packages/lint; no conflict; no generated artifact left to regenerate). After the merge: pnpm --filter @objectstack/spec build, then check: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):
    • exact coverage: each of the four catalogs holds exactly its door-reaching ids, each in exactly the 11 platform locales; all are the entries FINDING_USER_TEXT_CATALOG serves; the five ids are pinned by value;
    • the six ids the door never returns have no catalog entry;
    • every push site rendered from the rule's real findings (7 cases: both autonumber token arms, the optional-field site, the list-view sort site, both search roles, the dataset site): severity warning, the exact params, every locale truthy, no undefined or template residue, every interpolated name present, and no English stand-in in any non-English locale;
    • the two token arms and the two search roles render apart in every locale;
    • zh-Hans and en spot checks on the Auto Number sentence;
    • no params where the finding is not door advice: an autonumber error, the page-sort page-field-unprovisioned warning, and an object field's lookup site of the object-reference rule;
    • from the runtime gate to the wire field: an object write's autonumber advisory (through the registry adapter), a view write's sort and search advisories, and a dataset write's object-reference advisory come out of runRuntimeAuthoringRules with their params, and the rendered userMessage (zh-CN, fr-FR, ja-JP requests) parses under RuntimeAuthoringIssueSchema beside 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 --noEmit and check:test-typecheck), then build: VERDICT command-exit 0.
  • Consumer reading (@objectstack/metadata-protocol, which runs the gate on every save; closure built with pnpm --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)
# Mutation Observed
1 authoring-rules.ts: drop the userTextParams spread in the lintAutonumberFormats adapter 1 failed, 19 passed (the object-write gate case)
2 validate-object-references.ts: drop { dataset: dsName } at the dataset site 2 failed, 18 passed (the dataset render case and the dataset-write gate case)
3 validate-searchable-fields.ts: drop userTextParams at the unprovisioned site 4 failed, 16 passed (both role cases, the arms case, the view-write gate case)

Each mutation landed (anchor 1 → 0, blob changed) and each restore read blob == HEAD and git diff HEAD is empty.

Acceptance notes

Verification

Local subset at f4ce7b50, derived with node 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 head 4605d6ef, 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 is spec-seat-2/r2026-11-13/out/32838-gates-ran-f4ce7b50.list in the project files.

Four families needed a prerequisite before their reading
  • node scripts/check-plugin-teardown-shape.mjs --self-test: its pinned fixture commit 621a4876 was 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 full pnpm 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-closure read 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

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
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/lint, touching 17 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/validating-metadata.mdx (via AUTHORING_RULES (symbol, a top-level const object))
What this run could not see
  • the SDK route bridge reached 65 of 247 client-bound route-ledger rows — the other 182 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 182: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 59 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 123 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 4 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 5b2ec820c8abca113eae23745f71331f55ec7aed → packageMentionDocs.

Which tree this was computed on

This run read content/docs from b323a8a3c952575e3675e363d4e5755d01f74d10 — the merge of head 4605d6ef3740fec8a664784c882fe0fc5383c498 into base 5b2ec820c8abca113eae23745f71331f55ec7aed, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# 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

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 5b2ec820c8abca113eae23745f71331f55ec7aed → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#2 · os-tesla · session_01L9qibvfX5bawZKtfa6u7j9

维护者速读

席位意见:可以落地。

席位核对

ACCEPT · seat domain:spec#2 · head 4605d6ef · 2026-11-13T17:30Z

  1. Shape: Fixes #32838, draft, base main, 12 files, +886/−1; changeset .changeset/32838-advisory-user-text.md (@objectstack/lint patch). Clause-②: no, Metadata-protocol: none, matching claim 6858401007, amendment 6858508915 (the lintAutonumberFormats adapter line) and dev report 6859456351.
  2. Premise: spec: user-facing refusal and advisory text is in the request locale (userMessage locale rule, advisory user text field), per ruling C on #32440 #32655's pattern; 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 (PR feat(lint): dashboard and report advisories carry a localized user sentence #33118) and 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 (PR fix(lint): the approval and flow advisories a flow save returns carry a user sentence in every platform locale #33120) use the same catalog list. The dev re-measured through runRuntimeAuthoringRules: 5 of the card's 10 ids reach the publish door (object, view and dataset writes). The other 5 are named with reasons in the changeset and Acceptance notes: three run only on the CLI (unique/double-declaration, unique/legacy-organization-composite, title-unresolvable), and three belong to the os lint best-practice sweep. page-field-unprovisioned's page-sort site in validate-sortable-fields.ts is 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, whose order and claim 6859188621 name it.
  3. Review: dispatch-gates --tier: no path-derived mandate (packages/lint only, no narrowing), so this is the seat's own review of record. It read the code diff: the four catalog imports and the merge list; the adapter's conditional spread; the params at the push sites (autonumber object, field, token, kind / ref; sort and search object, field, role; object reference dataset plus the resolved object, set only at the dataset base-object site the door reaches). The new test drives the real gate for all three write types (runRuntimeAuthoringRules with object, view, dataset).
  4. Gates / check-runs: dev: lint 204 files / 8654 tests, metadata-protocol 337 files / 22799 tests, 62/62 derived gates exit 0 (32838-gates-ran-f4ce7b50.list); 3 ablations red as expected (adapter spread, dataset params, searchable params). CI on 4605d6ef: 66 runs, 55 success, 11 skipped, 0 failed. K = 2 (fix(lint): the approval and flow advisories a flow save returns carry a user sentence in every platform locale #33120, feat(storage,mcp): an upload link for a file field of a record not yet created #33123); git merge-tree against main 67188849 is clean, fix(lint): the approval and flow advisories a flow save returns carry a user sentence in every platform locale #33120's catalog lines and this PR's sit side by side in finding-user-text.ts.
  5. Accepted deviations and out-of-scope findings: the 5 unreachable ids stay on the English message. Agent-written non-English sentences are listed for the native-review round. The page-sort site 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 (carrier noted, not filed). 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 edits finding-user-text.ts and validate-sortable-fields.ts too, so it merges main after this lands.
  6. Landing: not governed, 887 changed lines. The seat readies the PR and arms auto-merge under the maintainer's standing words 「车道经理应该使用 pm-dispatch 技能审核和落地pr」. On MERGED: 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 closes via Fixes; pm:dispatched comes off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

2 participants