Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .changeset/translation-liveness-walk-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
'@objectstack/spec': patch
---

liveness ledger: `translation`'s `_note` WALK BOUNDARY sentence excepts `settingsCommon` and states that group's own boundary

The header said "every group is a z.record keyed by target names — the drill sees each
record's VALUE shape one level". Measured on this commit straight off
`translationDataShape()`, ten of the eleven groups are `z.record`s and `settingsCommon` is a
plain strictObject: a fixed shape whose one member `sourceLabels` is itself a fixed
strictObject keyed by the ADR-0010 resolution layers (`env`, `global`, `tenant`, `user`,
`default`) — a closed set, with the retired spellings (`org`, `workspace`, `system`,
`fallback`, `environment`) rejected and pointed at the layer each meant. Nothing about it is
keyed by target names, so the universal was false for one group, and false in the direction
that matters: the sentence is the file's declaration of how far down its rows reach.

The sentence now excepts `settingsCommon` and states what the boundary is for it: the
walk's one level lands on the named member `sourceLabels` (exactly what
`check:liveness --undrilled` prints for `translation/settingsCommon`), the layer keys
beneath it sit below the boundary and are read as one unit by `resolveSettingsSourceLabel`
and objectui's `useSettingsLabel`, and the blanket verdict over them is the declared kind —
`translation/settingsCommon` is already a row of `undrilled-containers.baseline.json`, so
no new pinned artifact is added. The `datasets` row's "WALK BOUNDARY as for every other
group here" inherited the same universal by reference and now cites the record groups only.

Published data, prose only: `liveness/` is in this package's `files` array, so these
ledgers ship in the npm tarball. No `status` value moves, no schema changes and no gate
verdict changes. The header's summary-count sentence (#15775) is untouched.
4 changes: 2 additions & 2 deletions packages/spec/liveness/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "translation",
"_note": "TranslationItemSchema (#3778 — one locale's translations, the SAME groups the file-authored bundles use). NO LONGER A PIPE: the schema was a z.preprocess wrapping the retired object-first-dialect guard, which the gate's walker could not see through until #4488 fixed unwrap() to take the OUT side of a transform-input pipe — `translation` was literally unwalkable before this ledger. #4001 closed the shape with `.strict()` and folded the guard's ten prescriptions into the unknown-key `guidance`, so the preprocess is gone and the registered schema is a plain strict object. Consumer chain: runtime-authored items sync into the i18n adapter's authored layer (packages/core/src/fallbacks/authored-translation-sync.ts — at kernel:ready, on metadata:reloaded, and on translation mutations; #2591 closed the publish dead-end), file bundles load via service-i18n; both merge into ONE tree read by the spec resolvers (packages/spec/src/system/i18n-resolver.ts), the REST localization layer (translateMetaItem/translateMetaTypes), objectui's client resolvers (useObjectLabel/useSettingsLabel), and plugin-audit's summary localizer. WALK BOUNDARY: every group is a z.record keyed by target names — the drill sees each record's VALUE shape one level; the deeper per-key conventions (objects.<n>.fields.<f>.label, settings.<ns>.keys.<k>.options.<v>, …) are governed by the resolvers cited per row, not by ledger rows. Note also the sync merges the RAW stored payload (authored-translation-sync.ts:155, not a schema re-parse), so the declared groups below are the CONTRACT while undeclared keys technically flow through on rows already stored — the resolvers read only the declared conventions. Since #4001 no NEW row can acquire one: the metadata door rejects an undeclared key instead of stripping it, so that residue is a finite set that only shrinks. Every group but `flows` is live — `flows` is the one that is `planned`, and `datasets` was seeded LIVE and DRILLED by #14253 with its reader (`translateDataset`) in the same change. A BOUNDARY and not a total, deliberately: the per-prop rows below carry the verdicts, the generated `state-counts.md` carries this type's totals (#7377), and `props` holds the groups PLUS `locale` and the item-identity keys `name`/`label` — so no total taken over `props` is a total of groups, which is how both totals this sentence has carried came to be wrong. ⚠️ It first read \"10 of 11 groups live; the one dead group (`validationMessages`) is pointed at by #3778's own legacy-key migration table, making it a shipped false signpost\" — describing a group REMOVED in 17.0.0 (#4667), i.e. prose outliving its subject in the header of the very file whose rows warn about that; corrected 2026-09-02 (#14253) to \"11 of 12 groups live; the twelfth, `datasets`, …\", which matched no reading of `props` at all — `datasets` is one of the groups, never a twelfth. Corrected again 2026-09-06 (#15775) by deleting the integers rather than re-deriving them, on #7377's precedent for this ledger family's other hand-maintained counts. Seeded 2026-08-01 (#4488). 2026-08-28 (#13003): all nine `path:NNN` citations in this file were re-anchored to their consuming symbols; EIGHT of the nine were wrong and every one of those was IN RANGE (the exception is `locale`, whose range still lands inside its reader). This ledger carried the batch's heaviest load of the OTHER silent class as well — nine further positions written as bare `:NNN` suffixes with no path in front of them, which `PATH_RE` never matches, so they degraded to prose that no check has ever resolved, bounded or key-checked.",
"_note": "TranslationItemSchema (#3778 — one locale's translations, the SAME groups the file-authored bundles use). NO LONGER A PIPE: the schema was a z.preprocess wrapping the retired object-first-dialect guard, which the gate's walker could not see through until #4488 fixed unwrap() to take the OUT side of a transform-input pipe — `translation` was literally unwalkable before this ledger. #4001 closed the shape with `.strict()` and folded the guard's ten prescriptions into the unknown-key `guidance`, so the preprocess is gone and the registered schema is a plain strict object. Consumer chain: runtime-authored items sync into the i18n adapter's authored layer (packages/core/src/fallbacks/authored-translation-sync.ts — at kernel:ready, on metadata:reloaded, and on translation mutations; #2591 closed the publish dead-end), file bundles load via service-i18n; both merge into ONE tree read by the spec resolvers (packages/spec/src/system/i18n-resolver.ts), the REST localization layer (translateMetaItem/translateMetaTypes), objectui's client resolvers (useObjectLabel/useSettingsLabel), and plugin-audit's summary localizer. WALK BOUNDARY: every group but `settingsCommon` is a z.record keyed by target names — the drill sees each record's VALUE shape one level; the deeper per-key conventions (objects.<n>.fields.<f>.label, settings.<ns>.keys.<k>.options.<v>, …) are governed by the resolvers cited per row, not by ledger rows. `settingsCommon` is a fixed strictObject with no target names, so the drill's one level lands on its own named member `sourceLabels` — itself a fixed strictObject whose keys are the ADR-0010 resolution layers (`env`, `global`, `tenant`, `user`, `default`), a closed set the schema holds closed: the retired spellings (`org`/`workspace`, `system`, `fallback`, `environment`) are rejected with a pointer to the layer each meant, never accepted as a layer. Those layer keys sit below the boundary: they are read as one unit by `resolveSettingsSourceLabel` (packages/spec/src/system/i18n-resolver.ts) and objectui's `useSettingsLabel().sourceLabel`, and the blanket verdict `settingsCommon` carries over them is the DECLARED kind — `translation/settingsCommon` is a row of scripts/liveness/undrilled-containers.baseline.json, the same standing as the record groups whose value shapes are not drilled. Note also the sync merges the RAW stored payload (authored-translation-sync.ts:155, not a schema re-parse), so the declared groups below are the CONTRACT while undeclared keys technically flow through on rows already stored — the resolvers read only the declared conventions. Since #4001 no NEW row can acquire one: the metadata door rejects an undeclared key instead of stripping it, so that residue is a finite set that only shrinks. Every group but `flows` is live — `flows` is the one that is `planned`, and `datasets` was seeded LIVE and DRILLED by #14253 with its reader (`translateDataset`) in the same change. A BOUNDARY and not a total, deliberately: the per-prop rows below carry the verdicts, the generated `state-counts.md` carries this type's totals (#7377), and `props` holds the groups PLUS `locale` and the item-identity keys `name`/`label` — so no total taken over `props` is a total of groups, which is how both totals this sentence has carried came to be wrong. ⚠️ It first read \"10 of 11 groups live; the one dead group (`validationMessages`) is pointed at by #3778's own legacy-key migration table, making it a shipped false signpost\" — describing a group REMOVED in 17.0.0 (#4667), i.e. prose outliving its subject in the header of the very file whose rows warn about that; corrected 2026-09-02 (#14253) to \"11 of 12 groups live; the twelfth, `datasets`, …\", which matched no reading of `props` at all — `datasets` is one of the groups, never a twelfth. Corrected again 2026-09-06 (#15775) by deleting the integers rather than re-deriving them, on #7377's precedent for this ledger family's other hand-maintained counts. Seeded 2026-08-01 (#4488). 2026-08-28 (#13003): all nine `path:NNN` citations in this file were re-anchored to their consuming symbols; EIGHT of the nine were wrong and every one of those was IN RANGE (the exception is `locale`, whose range still lands inside its reader). This ledger carried the batch's heaviest load of the OTHER silent class as well — nine further positions written as bare `:NNN` suffixes with no path in front of them, which `PATH_RE` never matches, so they degraded to prose that no check has ever resolved, bounded or key-checked.",
"props": {
"name": {
"status": "live",
Expand Down Expand Up @@ -58,7 +58,7 @@
"status": "live",
"verifiedAt": "2026-09-02",
"evidence": "packages/spec/src/system/i18n-resolver.ts#lookupDatasetAttr (`datasets.<name>.label` / `.description`); packages/spec/src/system/i18n-resolver.ts#lookupDatasetMemberLabel (`datasets.<name>.dimensions.<d>.label` and `.measures.<m>.label`); packages/spec/src/system/i18n-resolver.ts#translateDataset (registered in METADATA_DOCUMENT_TRANSLATORS, which is what TRANSLATABLE_METADATA_TYPES is derived from, so packages/rest/src/rest-server.ts#translateMetaItem localizes a served dataset with nothing else to remember, #3786)",
"note": "Seeded 2026-09-02 (#14253) LIVE, with its reader in the same change — not declared first and wired later. A dataset reads like a back-office definition, but a measure label is drawn ON THE DASHBOARD, under every metric tile and on every chart axis; before this `dataset` was neither in TRANSLATABLE_METADATA_TYPES nor addressed by any group, so a translated dashboard rendered Chinese tile titles with `Untouched > 14 days` directly beneath them. Top-level rather than nested under `dashboards` because a dataset is the ONE definition every presentation binds to by reference (ADR-0021 D1): the same measure is drawn by N widgets across M dashboards, and a dataset no dashboard references would otherwise be unaddressable. WALK BOUNDARY as for every other group here — the drill sees this record's VALUE shape one level; the per-key conventions below it (dimensions.<d>.label, measures.<m>.label) are governed by the resolvers cited above. Key face measured against DatasetSchema: a dimension and a measure each declare `label` and nothing else display-shaped, which `dataset.zod.ts` states at the authoring site too ('its author-facing text is `label`. `description` is declared on the DATASET itself'), so `description` lives on the dataset and nowhere below it.",
"note": "Seeded 2026-09-02 (#14253) LIVE, with its reader in the same change — not declared first and wired later. A dataset reads like a back-office definition, but a measure label is drawn ON THE DASHBOARD, under every metric tile and on every chart axis; before this `dataset` was neither in TRANSLATABLE_METADATA_TYPES nor addressed by any group, so a translated dashboard rendered Chinese tile titles with `Untouched > 14 days` directly beneath them. Top-level rather than nested under `dashboards` because a dataset is the ONE definition every presentation binds to by reference (ADR-0021 D1): the same measure is drawn by N widgets across M dashboards, and a dataset no dashboard references would otherwise be unaddressable. WALK BOUNDARY as for the other RECORD groups here (the header names the one group that is not a record): the drill sees this record's VALUE shape one level; the per-key conventions below it (dimensions.<d>.label, measures.<m>.label) are governed by the resolvers cited above. Key face measured against DatasetSchema: a dimension and a measure each declare `label` and nothing else display-shaped, which `dataset.zod.ts` states at the authoring site too ('its author-facing text is `label`. `description` is declared on the DATASET itself'), so `description` lives on the dataset and nowhere below it.",
"children": {
"label": {
"status": "live",
Expand Down
Loading