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
35 changes: 35 additions & 0 deletions .changeset/liveness-previews-count-as-consumers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
"@objectstack/spec": patch
---

docs(liveness): designer previews count as consumers — re-grade four docs-shaped rows dead → live and write the principle into the ledger methodology (#7131)

The ledger said `job.label`, `job.description`, `translation.label` and
`translation.name` had **no runtime consumer**. objectui's metadata-admin
previews had been rendering all four to a human the whole time:
`JobPreview.tsx` takes `label`/`description` off the job draft and renders them
as the preview card's title and subtitle, and `TranslationPreview.tsx` takes
`label` — falling back to the body `name` — and renders it as the item's title.

Per the maintainer ruling of 2026-08-10, a designer preview that renders a key
to a human **is** a runtime consumer, so the four rows re-grade to `live` with
realm-marked, commit-pinned objectui evidence, and each carries a `producer`
naming the `registerMetadataPreview` call and the surface that resolves it — a
preview no registry ever hands a draft to is a read point that never runs.

Nothing about enforce-or-remove moves: all four keys remain docs-shaped,
deliberately KEPT under the ADR-0033 exemption, and still not `authorWarn`'d.
`job.label` is `live` because a human sees it in the designer; the scheduler
still stores name and schedule only, and the row now says so explicitly.

The README gains the methodology section the ruling asked for, so the next sweep
asks the question mechanically instead of rediscovering it: enumerate a type's
registered preview read points **before** writing "no runtime consumer", and
record their absence when there are none. It divides against the existing
"an authoring/preview renderer is NOT a runtime consumer" section on what the
property claims rather than on what the surface is — for a **display** key the
render is the whole of the declared effect, while for a **behavioural** key a
panel echoing the value back still proves nothing. The 2026-07 sweep's ten
corrections are explicitly not reopened.

Ledger and documentation only; no schema, no runtime behaviour.
59 changes: 59 additions & 0 deletions packages/spec/liveness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ means "the realms named in the evidence", never "everywhere".

### ⚠️ An authoring/preview renderer is NOT a runtime consumer

> **Scope narrowed 2026-08-10 (#7131) — read the next section with this one.** What
> follows holds for a property that claims to **do** something: gate, bind, route,
> filter, enforce. It does *not* settle a property whose declared effect is simply
> to **be shown**, where the render is not a stand-in for the behaviour but *is* the
> behaviour. None of the thirteen re-verifications below is reopened by that split —
> all thirteen are behavioural keys.

`live` means **authoring the property changes runtime behaviour**. A Studio
`*.form.ts` input or a `metadata-admin/previews/*Preview.tsx` panel merely
*echoes back what the author typed* — it proves the property round-trips, never
Expand Down Expand Up @@ -281,6 +288,58 @@ enforced" warning for a month while it worked, which is an invitation to skip a
shipped feature. Erring toward `dead` is the right default *and* a debt to
re-verify.

### Designer previews count as consumers (maintainer ruling, 2026-08-10, #7131)

The section above is the *over-claim* guard. It also produced an under-claim, and
the maintainer settled it directly:

> **Maintainer ruling (2026-08-10, directed in session `session_01BPWqbmEFU8gJepBJTHESXd`): previews count as consumers.**
>
> A designer preview that renders a key to a human is a runtime consumer — the ledger's "no runtime consumer" verdict must include metadata-admin preview read points. The affected docs-shaped rows (`job.label`/`job.description`, `translation.label`/`.name`) re-grade from dead to live, and the ledger methodology note records the principle so the next sweep asks the question mechanically.

**The mechanical rule, for the next sweep.** Before writing `"no runtime
consumer"` — or any wording that means it — **enumerate the metadata-admin preview
read points** for the type, in objectui, and say what you found. The population is
small, enumerable, and registered by type name, so this is a lookup and not a
search:

```bash
# 1. does this type have a preview at all?
git -C ../objectui grep -n "registerMetadataPreview('<type>'" origin/main
# 2. what does that preview read off the draft?
git -C ../objectui show origin/main:packages/app-shell/src/views/metadata-admin/previews/<X>Preview.tsx \
| grep -n 'd\.<key>'
```

An absent preview is a finding to record, not a step to skip — "the type has no
registered preview" is exactly the sentence a later sweep needs, and it is the one
`translation.label`'s superseded *"no runtime consumer **in this repo**"* was
missing. That hedge was never false; the cross-repo look simply was not taken,
which is the blind spot `evidenceScope` (#4895) exists to expose.

**Why this does not contradict the section above.** The two rules divide on what
the property claims, not on what the surface is:

| The property's declared effect | Does a preview render settle it? |
|---|---|
| **Display** — docs-shaped annotation, `label` / `description` / a title fallback | **Yes.** Being shown to a human is the whole of the claimed effect. There is no second layer where the "real" consumer would live, so the preview is not standing in for anything. |
| **Behaviour** — gates, bindings, routes, filters, permissions | **No.** The 2026-07 sweep's verdict stands unchanged: 10 of 13 preview-cited entries were wrong. A panel echoing `shortcut` back is not a keybinding, and echoing `permissions` back is not a gate. |

So the failure the section above records — a preview citation used as evidence
that *something acts on* the value — is untouched. What is corrected is the
opposite move: taking a preview's **absence from the search** as proof that
*nothing reads* the value, for a key whose only job was ever to be read by a
person.

**What `live` does and does not mean on a re-graded row.** `job.label` is `live`
because a human sees it in the designer; the scheduler still stores name/schedule
only, and the row says so. A re-grade is **not** an ADR-0033 change: these four
rows are docs-shaped, deliberately KEPT, and still not `authorWarn`'d — nothing
about enforce-or-remove moves. Cite the preview the way any cross-repo evidence is
cited: realm marker, pinned objectui commit, and a `producer` naming the
`registerMetadataPreview` call plus the surface that resolves it — a preview no
registry hands a draft to is a read point that never runs.

### How to verify a claim without fooling yourself

Three false conclusions were published during this sweep, all from the same
Expand Down
18 changes: 12 additions & 6 deletions packages/spec/liveness/job.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@
"note": "scheduling identity; a job without one is skipped loudly."
},
"label": {
"status": "dead",
"verifiedAt": "2026-08-02",
"note": "display metadata; no runtime consumer (sys_job stores name/schedule only). Docs-shaped annotation, deliberately KEPT and not authorWarn'd — the hook.label/description precedent, exempt from enforce-or-remove (ADR-0033)."
"status": "live",
"verifiedAt": "2026-08-10",
"evidenceScope": "cross-repo",
"evidence": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/JobPreview.tsx:257 takes `label` off the job draft with the job's own `name` as fallback, and packages/app-shell/src/views/metadata-admin/previews/JobPreview.tsx:313 renders it as the preview card's title",
"producer": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/index.ts:62 registers JobPreview against the `job` metadata type, and packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx:949 resolves that registration and hands the component the draft being edited — the read point is reachable, not merely present",
"note": "display metadata, and it IS displayed: the metadata-admin job preview shows it as the card title, falling back to the job `name` when unset. RE-GRADED dead → live 2026-08-10 (#7131) under the maintainer ruling that a designer preview rendering a key to a human is a runtime consumer — see README, 'Designer previews count as consumers'. The superseded wording, 'no runtime consumer (sys_job stores name/schedule only)', was true about the SCHEDULER and false as a whole-system claim: for a docs-shaped key the display IS the runtime effect, so sys_job was never the surface that could falsify it. UNCHANGED by the re-grade: still docs-shaped annotation, deliberately KEPT and not authorWarn'd — the hook.label/description precedent, exempt from enforce-or-remove (ADR-0033). `live` here does not mean the scheduler acquired a use for it."
},
"description": {
"status": "dead",
"verifiedAt": "2026-08-02",
"note": "same as `label`: docs-shaped, deliberately kept, no warning."
"status": "live",
"verifiedAt": "2026-08-10",
"evidenceScope": "cross-repo",
"evidence": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/JobPreview.tsx:258 takes `description` off the job draft, and packages/app-shell/src/views/metadata-admin/previews/JobPreview.tsx:316 renders it beneath the title whenever it is non-empty",
"producer": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/index.ts:62 registers JobPreview against the `job` metadata type, and packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx:949 resolves that registration and hands the component the draft being edited",
"note": "same as `label`: docs-shaped, deliberately kept, no warning — and displayed under the title in the same preview card. Re-graded dead → live with `label` on 2026-08-10 (#7131), same ruling, same ADR-0033 KEPT status."
},
"schedule": {
"status": "live",
Expand Down
18 changes: 12 additions & 6 deletions packages/spec/liveness/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
"_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. 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. Seeded 2026-08-01 (#4488).",
"props": {
"name": {
"status": "dead",
"verifiedAt": "2026-08-01",
"note": "Item identity, declared in #4001 and dead as a BODY key — which is the honest reading of a copy nobody reads. The row's `name` column is the live one: the metadata door takes it from the URL (`saveMetaItem({ name })`, rest-server.ts:3903), and `authored-translation-sync` reads `row.name` as the locale fallback for pre-#3778 rows (:140-148) while explicitly destructuring the body copy back out before merging (:154-159). Declared anyway, and deliberately not authorWarn'd, for two reasons: the platform's own create seed sends it (`metadata-create-seeds.ts`, whose stated contract is that EVERY seed carries placeholder identity), so a warning would fire on our own shape; and `translation` being the one registered type of 25 without a `name` is exactly the irregularity an AI author trips on. Undeclared it was silently stripped, which is how the seed gate — the canonical 'designer create shape ≠ spec' guard — passed for years while two thirds of the seed it validated was being thrown away."
"status": "live",
"verifiedAt": "2026-08-10",
"evidenceScope": "cross-repo",
"evidence": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/TranslationPreview.tsx:67 falls back to the draft's BODY `name` when `label` is unset, and packages/app-shell/src/views/metadata-admin/previews/TranslationPreview.tsx:100 renders the result as the preview card's title",
"producer": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/index.ts:50 registers TranslationPreview against the `translation` metadata type, and packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx:949 resolves that registration and hands the component the draft being edited",
"note": "Item identity, declared in #4001. RE-GRADED dead → live 2026-08-10 (#7131), and the re-grade supersedes exactly ONE clause of the old note: 'dead as a BODY key — the honest reading of a copy nobody reads'. The body copy has a measured reader — objectui's metadata-admin translation preview uses it as the display fallback when `label` is unset — so under the maintainer ruling that a designer preview rendering a key to a human is a runtime consumer (see README, 'Designer previews count as consumers') the copy is read. THE REST OF THIS ROW STANDS UNCHANGED AND IS THE SUBSTANCE, including its door/row-column analysis: the row's `name` column is the live one on the SYNC path, and the body copy is still not what the sync reads — the preview reads it, the sync does not. The metadata door takes it from the URL (`saveMetaItem({ name })`, rest-server.ts:3903), and `authored-translation-sync` reads `row.name` as the locale fallback for pre-#3778 rows (:140-148) while explicitly destructuring the body copy back out before merging (:154-159). Declared anyway, and deliberately not authorWarn'd, for two reasons: the platform's own create seed sends it (`metadata-create-seeds.ts`, whose stated contract is that EVERY seed carries placeholder identity), so a warning would fire on our own shape; and `translation` being the one registered type of 25 without a `name` is exactly the irregularity an AI author trips on. Undeclared it was silently stripped, which is how the seed gate — the canonical 'designer create shape ≠ spec' guard — passed for years while two thirds of the seed it validated was being thrown away."
},
"label": {
"status": "dead",
"verifiedAt": "2026-08-01",
"note": "Display metadata with no runtime consumer in this repo. Not authorWarn'd: the README's rule is that pure display annotation (`description`, `tags`, `icon`) must not warn, and the `job.label` precedent is exactly this — docs-shaped, deliberately kept, ADR-0033 exempt from enforce-or-remove. Shipped with `name` in the create seed for the same reason."
"status": "live",
"verifiedAt": "2026-08-10",
"evidenceScope": "cross-repo",
"evidence": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/TranslationPreview.tsx:67 takes `label` off the translation draft as the first choice of the display chain, and packages/app-shell/src/views/metadata-admin/previews/TranslationPreview.tsx:100 renders the result as the preview card's title",
"producer": "objectui @aeb8424b: packages/app-shell/src/views/metadata-admin/previews/index.ts:50 registers TranslationPreview against the `translation` metadata type, and packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx:949 resolves that registration and hands the component the draft being edited",
"note": "Display metadata — and the display exists, one repo over: the metadata-admin translation preview renders it as the item's title. RE-GRADED dead → live 2026-08-10 (#7131) under the maintainer ruling that a designer preview rendering a key to a human is a runtime consumer — see README, 'Designer previews count as consumers'. Read the superseded wording carefully: 'no runtime consumer IN THIS REPO' was literally accurate and remains so — what changed is that the cross-repo look was finally taken, which is exactly the blind spot `evidenceScope` exists to make visible (#4895). UNCHANGED: not authorWarn'd — the README's rule is that pure display annotation (`description`, `tags`, `icon`) must not warn, and the `job.label` precedent is exactly this — docs-shaped, deliberately kept, ADR-0033 exempt from enforce-or-remove. Shipped with `name` in the create seed for the same reason."
},
"locale": {
"status": "live",
Expand Down
Loading