Skip to content

fix(platform-objects,metadata-core,service-messaging): Setup descriptions are plain admin sentences; ADR references move to the docblocks - #23845

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23802-setup-copy
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23802-setup-copy

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23802

Clause-②: no

What changed

The sentence an administrator reads under a Setup page title is the object's description; a field's help tooltip is the field's description. Both reach every locale through the generated translation bundles. This PR rewrites the Setup-visible object descriptions in the admin's words and moves every ADR number, decision id and API call out of the strings in this lane's packages and into the docblock or a comment beside the string (the card's constraint: docblocks and ADR links in code stay, only user-facing strings move). Wording only: no field, index, permission or behaviour change.

Scope at the claim: packages/platform-objects, packages/metadata-core/src/objects/sys-metadata*.object.ts and packages/services/service-messaging/src/objects/*.object.ts. The descriptions produced in plugin-approvals, plugin-security, service-automation, plugin-sharing and packages/spec/src/ui/view.form.ts (the permission set organization_admin_no_bypass, Record Shares, Approval Delegations) belong to #23829, which remains open and is untouched here.

Before / after

Measured by loading the BUILT object definitions of the three packages (61 objects; multi-line values included) and matching the card's patterns (ADR- followed by a digit, a decision id such as D2, finding F, emit(), kernel). Before, at base 1ecb08a1c: 15 distinct strings matched (17 rows; two metadata-core strings appear twice because platform-objects re-exports them). After, at a6586f72a: 0.

Object descriptions on a Setup page, rewritten (the last two carried schema vocabulary and no pattern):

Object (Setup nav entry) Before After
sys_business_unit (People and Organization, Business Units) Canonical Business Unit tree — hierarchical org/data-partition node (company / division / department / region / office). ADR-0057 D2. Your company structure — divisions, departments, regions and offices — used to scope data and reports.
sys_notification (Diagnostics, Notification Events) Notification events — one row per emit() (ADR-0030 Layer 2 ingress) Every notification the platform sent, one row per event.
sys_http_delivery (Integrations, HTTP Deliveries) Durable outbox row for one outbound-HTTP attempt (ADR-0018). Managed by @objectstack/service-messaging; do not write directly. Outgoing HTTP calls made by webhooks and flows, one row per call, with its delivery status.
sys_notification_preference (Configuration, Notification Preferences) Per-user × topic × channel notification toggle (mute/allow), with admin-global defaults. Which topics and channels each user receives; admins set the defaults.
sys_notification_template (Configuration, Notification Templates) Per (topic × channel × locale) render template for notifications. The subject and body each notification topic sends, per channel and language.

Field help on Setup forms: the ADR reference is removed and the rest of the help text is unchanged, because it is operational detail an admin acts on.

  • sys_user.role: "(ADR-0068 D2)" removed
  • sys_user.manager_id: "(ADR-0057 / @objectstack/security-enterprise)" removed
  • sys_user.primary_business_unit_id: "(ADR-0057 addendum D12)" removed
  • sys_organization.parent_organization_id: "(ADR-0105 D6)" removed
  • sys_invitation.business_unit_id and sys_invitation.positions: "(ADR-0105 D8)" removed
  • sys_sso_provider.domain_verified (Access Control, SSO Providers): "(ADR-0135 D6)" removed

Judged NOT Setup-visible (no Setup nav entry in any of the 12 contributors that declare app: 'setup', and not the subject of a Setup record page); the ADR reference is removed and the wording is otherwise kept:

  • sys_metadata_audit (metadata-core): "(ADR-0010)" removed
  • sys_metadata_commit (metadata-core; in no translation bundle): "(ADR-0067)" removed
  • sys_metadata.environment_id (metadata-core): "(ADR-0131 D6)" removed
  • sys_metadata_activation (platform-objects; in no translation bundle): "(ADR-0126 §4)" removed. It backs the Packaged Automation page, which renders its own copy rather than this description.
  • sys_notification_delivery (service-messaging): "(ADR-0030 Layer 4)" removed

They are edited anyway because they sit in the claimed file surface, three of them ship in the platform-objects bundles to every locale, and the test below then pins every object a package ships. No hand-kept Setup roster is needed, so it cannot go stale when a plugin adds a nav entry.

Setup nav labels and the SETUP_APP description carried none of the patterns. No nav string changed.

Translations: what the generator required

os i18n extract (run for all nine bundle sets by node scripts/check-i18n-bundles.mjs --write, which reads each package's documented command) rewrites the en bundle from source on every run. It keeps any non-empty translated-locale value (merge mode). A translated leaf whose source moved is therefore NOT updated by the generator. Its own generated header says to re-translate it by hand. So the order was:

  1. platform-objects zh-CN / ja-JP / es-ES objects bundles: the 11 affected leaves re-translated in place (leaf values only, no key added or removed). None of them had a recorded source hash, so the provenance tables did not move.
  2. service-messaging zh-CN: the 4 affected descriptions re-translated in place.
  3. service-messaging ja-JP / es-ES: these bundles are untranslated English fills with recorded provenance, so the 4 stale fills were emptied and the generator re-filled them from the new source. It refreshed their entries in ja-JP / es-ES.source-hashes.generated.ts itself. If they had been left alone, both locales would have kept a byte-identical superseded draft, which check:i18n-stale-fill exists to catch.
  4. check-i18n-bundles --write regenerated the en bundles and the hash tables. pnpm check:i18n and pnpm check:i18n-stale-fill are green after it.

Acceptance 1: tests in the packages' own suites

No new check:* script, lint rule or CI wiring.

  • packages/platform-objects/src/apps/setup-copy-vocabulary.test.ts covers four populations: every object this package and @objectstack/metadata-core export (each label / pluralLabel / description anywhere in the definition); every leaf of the four objects bundles; the type-level label / description of the four metadataForms bundles (the sentence a Setup metadata page such as Capabilities shows); and SETUP_APP plus SETUP_NAV_CONTRIBUTIONS plus each locale's apps.setup subtree. It also has a positive control showing the matcher recognises each kind of vocabulary.
  • packages/services/service-messaging/src/objects/admin-copy-vocabulary.test.ts applies the same rule to every messaging object and its four bundles. platform-objects cannot import service-messaging, and no dependency was added for a test.
  • Patterns are case-sensitive except kernel. The decision-id pattern uses word boundaries and matched no legitimate text in any population. The one lower-case hit in the instrument run, adr-0104-file-references (a migration id inside sys_migration.id's help), is a machine id; the case-sensitive pattern does not match it.

Ablation: four legs through scripts/ablation-replace.mjs, each restored with blob hash equal to HEAD and an empty git diff HEAD.

  • (A) an ADR reference re-added to the Business Units source description turned the object test red, naming sys_business_unit.description.
  • (B) the old emit() / ADR sentence put back into the zh-CN bundle turned the zh-CN bundle test red.
  • (C) an ADR reference added to the messaging preference description turned the messaging object test red.
  • (D) an ADR reference added to sys_metadata_commit, with metadata-core rebuilt, turned the object test red. ablation-dist-preflight confirmed the marker was present in 4 dist files. Restore leg: rebuild, then --absent confirmed the marker gone from all 12 dist files with a clean tree, and the suite was green again.

Local verification (HEAD a6586f72a)

  • pnpm --filter @objectstack/platform-objects test: 71 files, 1103 tests passed.
  • pnpm --filter @objectstack/service-messaging test: 51 files, 574 passed.
  • pnpm --filter @objectstack/metadata-core test: 18 files, 733 passed (run at 3b5ffa17f; nothing in metadata-core changed after it).
  • typecheck for all three packages: exit 0. Both new test files are in their tsc programs (counted with --listFiles).
  • pnpm check:i18n, pnpm check:i18n-stale-fill and pnpm check:i18n-coverage: exit 0.
  • Derived gate list (dispatch-gates --commands, 66 families): 65 exit 0. check:dual-build-cjs-loads printed PREREQUISITE NOT MET (exit 3, it reads every package's dist and this worktree built only the CLI closure); that is NOT MEASURED locally and left to CI. --ran reconciliation: 66 derived, 65 run, 1 NOT-MEASURED, 0 UNRUN.

Acceptance notes

  • sys_notification_subscription keeps its description ("Standing subscription of a principal (role/team/user) to a notification topic."). Its docblock records that the subscription-to-recipient expansion is not wired, so the Setup grid is admin-authored data, not routing. Any user-voice sentence of the "who receives this topic" kind would advertise behaviour the runtime does not deliver.
  • Not Setup-visible, schema vocabulary, no pattern, left as is: sys_inbox_message, sys_notification_receipt ("Per-recipient × channel receipt …") and sys_business_unit_member (shown only as a related list, which renders the label).
  • SETUP_APP.protection.reason ("… see ADR-0010.") is a lock reason, not a nav label or description. Not edited.
  • Out of this lane, reported to the PM rather than edited:
    • Setup's Permission Sets and Positions forms show spec form help that carries ADR numbers. Producers: packages/spec/src/security/permission.form.ts (isDefault, managedBy, packageId, adminScope) and packages/spec/src/identity/position.form.ts (delegatable).
    • The "Installed Apps" note the card quotes is produced in objectui (packages/i18n/src/locales/*.ts, key installedAdditiveNote, rendered by InstalledListWidget.tsx), not by cloud-connection.
  • The Studio-only metadata-form help texts in the same bundles (object, field, view, action, agent, skill) also carry ADR numbers. They are spec copy outside Setup and were not judged here.

Generated by Claude Code

…escriptions read as plain admin sentences; ADR references move to the docblocks

Claude-Session: https://claude.ai/code/session_01TQLy3Yq6vF4SDpTXdr3Uwi
Co-authored-by: Claude <noreply@anthropic.com>
…o design-record vocabulary

Claude-Session: https://claude.ai/code/session_01TQLy3Yq6vF4SDpTXdr3Uwi
Co-authored-by: Claude <noreply@anthropic.com>
…ct via check-i18n-bundles --write)

Claude-Session: https://claude.ai/code/session_01TQLy3Yq6vF4SDpTXdr3Uwi
Co-authored-by: Claude <noreply@anthropic.com>
… before reading names

Claude-Session: https://claude.ai/code/session_01TQLy3Yq6vF4SDpTXdr3Uwi
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Oct 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-core, @objectstack/platform-objects, @objectstack/service-messaging, touching 27 documentable anchor(s).

31 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 0cfd0c49bd2635da048fae96b35a38448141fa9d.

⛔ 11 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 1 anchor(s) matched too much of the corpus to be a work list: sys_user (symbol, 41 pages)
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 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 — 9 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 0cfd0c49bd2635da048fae96b35a38448141fa9d → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 21912479c47bf389cbda1a22bd2451fbea188f47 — the merge of head a6586f72adbb6bbc55192f35fe92885dc1cc8e73 into base 0cfd0c49bd2635da048fae96b35a38448141fa9d, 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 21912479c47bf389cbda1a22bd2451fbea188f47 && git checkout 21912479c47bf389cbda1a22bd2451fbea188f47
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0cfd0c49bd2635da048fae96b35a38448141fa9d a6586f72adbb6bbc55192f35fe92885dc1cc8e73 && git checkout -B drift-repro 0cfd0c49bd2635da048fae96b35a38448141fa9d && git merge --no-ff a6586f72adbb6bbc55192f35fe92885dc1cc8e73

node scripts/docs-audit/affected-docs.mjs --json 0cfd0c49bd2635da048fae96b35a38448141fa9d

⚠️ 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 0cfd0c49bd2635da048fae96b35a38448141fa9d → 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

席位核对 · ✅ ACCEPT: PR #23845 at a6586f72ad · domain:engine seat 2 · session_01TQLy3Yq6vF4SDpTXdr3Uwi · 2026-10-16T08:45Z

Basis: claim 6209951290 on #23802; triage's retriage answer 6207761541; the dev's report on #23802; the seat's own reading of every non-generated hunk and of the zh-CN bundle hunks, against origin/main.

Correction to this seat's dispatch, on record: the dispatch said the generated translation files are "regenerated with the repo's generator, never hand-edited". That was wrong. AGENTS.md (the **/translations/*.generated.ts row, ~:712) reads: "Translated-locale values (zh-CN / ja-JP / es-ES) are hand-written: editing one of those strings is fine, adding or dropping keys is drift." The dev followed the repo's contract. The en bundles and the source-hash tables were written by the generator alone, and no key was added or dropped. The dispatch's mechanism assumption 1 was also short: the dev's instrument over the built definitions found 15 strings, not the seat's 7.

Checklist

  • Shape. Draft, base main, first line Fixes #23802. The only other issue number, Setup copy, the producers outside domain:engine: ADR numbers and schema vocabulary leave the approval, security, automation, sharing and view-form descriptions admins read (split from #23802) #23829, sits in "belong to Setup copy, the producers outside domain:engine: ADR numbers and schema vocabulary leave the approval, security, automation, sharing and view-form descriptions admins read (split from #23802) #23829, which remains open", with no closing verb.
  • Scope. 27 files, all inside the claim's file surface: description and field-description strings, two new package tests, the three packages' bundles, one changeset. No field, index, permission or behaviour change. No content/docs/releases/, no unrelated file. metadata-core/package.json is untouched (fix(metadata-core): drop the optional vitest peer so npm 10 installs it again #23834 owned it).
  • Copy, read hunk by hunk. Each ADR number and decision id moved to a comment beside the string. The "lives in the docblock above" comments hold: each named ADR appears in the file's header docblock on the PR head (ADR-0010, ADR-0067, ADR-0030, ADR-0126, ADR-0018, ADR-0030 Layer 3). The HTTP Deliveries sentence ("made by webhooks and flows") matches the producers on origin/main: plugin-webhooks' auto-enqueuer and service-automation's HTTP nodes both call enqueueHttp. The zh-CN hunks carry the same meaning with the references dropped.
  • Changeset, sentence by sentence: the five object sentences match the diff; "Field help on Users, Organizations, Invitations and SSO Providers, and the metadata-storage and notification-delivery object descriptions, no longer carry design-record numbers" matches the sys_user, sys_organization, sys_invitation, sys_sso_provider, sys_metadata*, sys_metadata_activation and notification-delivery hunks; the locales follow in all three bundles of both packages; "Wording only". Clause-②: no on its own line.
  • Acceptance 1, in the dispatched form. A unit test in each package's own suite (platform-objects/src/apps/setup-copy-vocabulary.test.ts, service-messaging/src/objects/admin-copy-vocabulary.test.ts), no new check:* script or CI wiring. Its population covers every exported object schema, every leaf of the four objects bundles, the type-level metadataForms label and description, and the Setup app, nav and each locale's apps.setup. The dev's four ablation legs each turned the test red.
  • Contract faces. None hit. CI plus this in-seat read; no second agent.
  • Gates on the head. ci-failure.mjs --pr 23845: GREEN, 40 of 40, none failed. All 6 skips (Build Docs, Console Pin Gate, the dogfood matrix template, Dogfood Verify CLI, Packed-tarball smoke (opt-in), Temporal Conformance) are names in check-expected-skips.mjs's roster (script 8f5354b0c; the judge itself was not runnable from the shared checkout, which has no node_modules). Local reconciliation in the report: 66 derived, 65 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads, a prerequisite; CI is green).
  • Landing checks. check-governed-merges --pr 23845: NOT governed, 510 changed lines. mergeable_state clean; git merge-tree against origin/main (3c080a65c, after fix(metadata-core): drop the optional vitest peer so npm 10 installs it again #23834) is clean.

Out of scope, one line each:

Next: ready, then auto-merge through the queue.


Generated by Claude Code

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Setup copy: ADR numbers and schema vocabulary leave the object, type and navigation descriptions admins read

2 participants