Schema documentation invariants
This document is the normative authoring contract for a codebot that creates or
changes localized Libertas schema documentation. It applies to every authored
schema-visible package, function, named type, parameter, field, Enumeration
member, Union variant, inline value, List container, and List item. It also
applies to custom document-property values and package StringResources.
These are codebot authoring and review requirements. Generated document JSON permits empty strings so parsers can represent compiler-generated nodes and older or incomplete source. That structural allowance is not permission for a codebot to omit documentation from an authored public declaration.
The only ordinary exception is a compiler-generated TypeScript discriminator
field whose document text the parser intentionally suppresses. Non-schema
implementation details do not need schema documentation. Hidden, ReadOnly,
protocol, persistent-data, and chart-related nodes are not exceptions: their
meaning can still be used by validation, accessibility, localization, tools,
management interfaces, or a future presentation.
Source and output invariants
- Source comments are authoritative. Never patch generated schema or document JSON to improve wording.
- Give every authored document node at least two ordinary lines: a concise natural label followed by a complete plain-language description. Do not rely on a parser fallback derived from a native identifier.
- Rust package text uses inner rustdoc (
//!) at the start ofsrc/lib.rs. Rust declarations use outer rustdoc (///). - TypeScript package text uses leading triple-slash comments (
///) on the selected entry module. TypeScript declarations use JSDoc (/** ... */). - Ordinary
//comments are not localized. Use them, a README, or developer documentation for engineering details that must not appear in the user document. - Update source documentation in the same change as the behavior, meaning, choices, results, constraints, or presentation it describes.
- Inspect the generated default-locale document as an output. Fix the owning source comment when a label, description, extension, or List half lands on the wrong node.
The final document has one package object, function documents in List, named
type documents in Types, nested field documents in each node's List, and
Enumeration members in Enum. A field document's numeric Type member is its
schema-node identifier; it is not prose and is never authored or translated.
Documentation traversal stops at a named type reference. Consequently, the
use-site field or parameter and the referenced named type must each make sense
on their own. One never substitutes for the other.
Universal user-language invariant
Write for the people who use the capability, including nontechnical home, commercial, research, engineering, and healthcare users. Use specialist domain terms when that audience genuinely uses them, and explain unfamiliar terms when the surrounding context does not make them clear.
A label must:
- be a short, natural name or action phrase;
- distinguish the node from its siblings;
- work when read aloud or shown without its parent; and
- not be a source identifier, version token, full sentence, or keyword list.
A description must add meaning beyond the label and declared type. It must say what the person chooses, enters, observes, receives, or can accomplish. When it describes behavior, use active voice and identify the actor, action, object, scope, material condition, and modality. Preserve distinctions such as “can,” “must,” and “automatically.”
All localized prose must:
- use concrete domain nouns and verbs rather than vague words such as “data,” “value,” “item,” “configuration,” or “information” by themselves;
- explain an important empty, unavailable, zero, false,
None, orUnknownmeaning when a person could otherwise misinterpret it; - remain understandable without relying on order, screen position, color, icon, shape, animation, or a particular gesture;
- avoid instructions tied to one client, such as “click the button” or “tap the row,” unless the behavior itself exists only on that client;
- use explicit nouns instead of an ambiguous “it,” “this,” or “they”;
- avoid unexplained acronyms, keyword stuffing, unsupported claims, and lists of capabilities the App does not provide; and
- be complete enough to translate without guessing an actor, scope, condition, or consequence.
Do not expose internal vocabulary in localized prose. In particular, do not describe something to a user as a function, field, type, struct, table, enum, Union, variant, schema, payload, protocol, endpoint, request, response, runtime, discriminator, index, FQN, Avro value, wire value, or implementation version. Do not expose native casing, storage encoding, Libertas Schema Paths, integer codes, byte layouts, or transport mechanics. Preserve required engineering facts in an ordinary source comment or developer document instead.
Apply this rule both when authoring source comments and when translating their localized text. Write natural, idiomatic language for the intended audience; keep it technology-neutral by describing the capability rather than its implementation. An App's “weather endpoint,” for example, is a “weather service” to its users. Prefer the specific purpose or the natural equivalent of “service” in the target language. This is a wording choice, not a mechanical word replacement: retain specialist terms when they describe the user's domain and their precise meaning matters. Preserve every material meaning, choice, control, automatic behavior, result, warning, condition, prerequisite, and limit. This guidance changes prose only; identifiers, structural keys, and message placeholders retain their exact spelling and syntax.
Domain references and discoverability
Document the names people use to identify a supported capability. Where relevant, connect formal domain references, document or form numbers, standard abbreviations, and common names in natural descriptive prose. For example, a tax topic can identify the forms and statutory provisions it covers, while an equipment topic can identify the industry standard it implements. These are user-domain references, distinct from internal identifiers and wire codes. Preserve their exact meaning during translation and explain unfamiliar abbreviations. Keep labels concise; put this context in descriptions.
State the actual purpose, supported scope, and material conditions. A reference to a subject does not establish that every case within it is supported. For links that share one request but bind different topics or records, document the individual topic or selected choice as well as the common operation, so the destination is understandable from its own documented meaning and data. When an Enumeration member identifies a navigation destination, its extracted member description owns the destination’s domain references, abbreviations, and common names. For example, a qualified business income topic can associate Section 199A, Form 8995/8995-A, and QBI deduction with that supported topic. The client supplies the descriptions of the actual bound members; a generic request description does not replace them. Maintain this information in its owning source documentation when behavior changes; generated documents and private code comments are not substitutes.
Node-specific invariants
Package
The package label is the recognizable product, service, or capability name, not the package identifier. Its description explains the overall outcome, intended setting or audience, major capabilities, and material prerequisites or limits. Avoid internal architecture and unsupported marketing claims.
Function
The function label names the activity a person can configure or use. Its description is the complete discovery description and must additionally follow the developer function-comment guide, including the seven completeness categories, explicit actors, and final developer attribution.
Plaza creates exactly one discovery embedding per public function from that function's display name and description. Package, argument, type, protocol, chart, attribute, and generated appendix text is not added. Excellent type and field documentation therefore never repairs an incomplete function comment. Developer attribution belongs only in function descriptions; do not append it to package, type, field, member, or extension text.
Named type
Describe the real-world concept represented by one value and why a person sees or supplies it. Do not say that it is a struct, table, grouping, payload, or a container of fields. A reusable named type must make sense independently of every place that references it.
Parameter and field
Give every parameter and field a contextual natural label. For an input, explain what the user chooses or enters and the effect or scope of that choice. For output or read-only information, explain what the App reports, records, or calculates and when it is meaningful.
Match the wording to the type's use.
For ordinary optional text stored as "", say “Leave it empty if absent,” and
explain any consequence of leaving it empty, such as using another name or
leaving an activity ungrouped. Do not say “Leave it undefined” when the answer
is an empty String. For a genuinely nullable answer, explain what absence means
and how it differs from a present empty answer or zero. AI-import instructions
must use the same meaning under the
blank-value conversion contract.
An output description explains the reported result and its availability rather
than telling the person to enter it. A non-user-facing schema field still needs
domain documentation: describe what the App records and the meaning of missing
or empty content. Keep mapping code, storage encodings, and other engineering
details in ordinary // comments.
Additional field rules:
- A Boolean label states the positive choice or state. Its description makes
the
trueandfalseconsequences unambiguous when they matter; “Enabled” by itself is not enough. - For a nullable value, distinguish “not supplied” or “unavailable” from zero, false, and an empty collection where that affects meaning.
- For a number, date, time, duration, or physical quantity, describe the domain
meaning and scope. Do not explain its integer width, epoch, raw date encoding,
or storage unit as implementation mechanics. Declare machine-readable unit
and format metadata with the appropriate schema annotation.
The platform supplies AI value-representation hints
from that metadata; do not duplicate those hints in source comments. Once a
PhysicalUnitis declared, the comment never names the unit again (no "in gallons" or "(percent)"). Clients already display the declared unit with the value under the presentation contract (physical units:50withpercentshows as50%), so a comment naming it would repeat it on screen. - For a Libertas system object, name its actual role, such as “Rain gauge,” “Patient,” “Delivery vehicle,” or “Sprinkler valve.” Never call it a device ID, user ID, endpoint ID, or plain integer. Keep the Libertas system-object type intact so clients can resolve its localized identity.
- For free text, describe what content is appropriate and any material use or visibility. Never present a secret as ordinary documented input.
- A use-site field retains its own documentation even when its named type is thoroughly documented.
Enumeration and bitflags
The Enumeration type describes the decision, state, or classification as a
whole. Every member has a natural label and a description of its observable
meaning or consequence. This includes None, Unknown, and zero-valued
members. Never expose the native constant name or numeric code.
A Bitflags catalog follows the same rules, but each nonzero member describes one independently selectable option. Do not phrase its type as one mutually exclusive choice.
The parsers' public positional @LibertasEnum(A, B, C) and
#[libertas_enum(A, B, C)] compatibility forms fabricate member nodes without
a source-document location for each member. A codebot therefore must not
generate those forms: they cannot satisfy this all-member documentation
invariant. Use a native numeric enum whose declaration and every member can be
documented. Existing positional catalogs remain parseable, but parser support
does not waive the codebot authoring rule.
Union and variant
The Union type describes the family of possible actions, events, states, or results. Every variant has a standalone natural label plus a description of the observable action or state, its trigger or scope, and its important consequence. Do not label variants “Request,” “Response,” “V1,” or by their discriminator tokens. Document every inline field inside a variant by the ordinary field rules.
TypeScript may obtain final variant text from a discriminator member, the Union branch, or the variant's named payload type. Choose one authoritative source for the intended result. If more than one source contains prose, keep the text semantically identical; never depend on precedence to hide contradictory wording. Rust takes the variant's own rustdoc.
List container and item
Every List has two complete document sections separated by a line containing at least four hyphens:
- Above
----, use a plural label and explain the collection's purpose, meaningful ordering, limits, or selection behavior. - Below
----, use a singular label and explain what one entry represents and how a person recognizes or uses it.
Author both halves even when the item is a separately documented named type. Custom properties above the divider belong to the List container; properties below it belong to the List item.
Hidden, interaction-context, and chart data
Document hidden and read-only values truthfully without revealing a secret. Explain their domain purpose, such as associating a follow-up action with the same inspection, rather than describing them as a cookie, token, cursor, or transaction mechanism.
Chart documentation describes the domain relationship and the meaning of each
visible quantity or category. It must remain useful to a screen reader and must
not depend on axis position, color, shape, rendering library, or client-computed
geometry. Visible human text uses a localized Enumeration, FormattedText, or
the appropriate Libertas system-object type when applicable. A plain String
is reserved for genuine literal domain or user-authored text, not a fixed
English vocabulary.
Exact source-document syntax
The first ordinary line becomes DisplayName for a package, function, or named
type, and Name for a field, item, member, or variant. Remaining ordinary lines
become Description. For reliable cross-language output, always provide both a
label line and at least one description line.
Long descriptions use HTML-style flowing prose. A single logical line break in
Description is source wrapping and is canonicalized to exactly one space. A
run of two or more logical line breaks is canonicalized to one LF so it remains
one intentional paragraph break. CRLF counts as one logical line break, as do a
lone CR or LF; horizontal whitespace around a break does not change the rule.
Codebots may wrap a long source sentence across adjacent rustdoc/JSDoc lines,
but must leave a blank documentation line only when one paragraph break is
intended. This normalization applies to Description, not custom-property or
StringResources values.
TypeScript function parameters may use @param name documentation. The parser
merges that text over documentation attached directly to the parameter, so use
one authoritative location or keep both semantically identical. Rust parameter
rustdoc and schema attributes are written on the typed parameter inside the
exported function signature.
TypeScript example
/// Greenhouse climate care
/// Helps growers monitor rooms and maintain suitable plant conditions.
/// @LibertasDefaultLocale("en-US")
/**
* Fan behavior
* Describes how ventilation responds to the selected temperature.
*/
export enum FanBehavior {
/**
* Automatic ventilation
* The greenhouse starts and stops the fan according to room temperature.
*/
Automatic,
/**
* Fan remains off
* The greenhouse does not start the fan automatically.
*/
Off,
}
/**
* Growing-room settings
* Describes the conditions the grower chooses for one room.
*/
export interface RoomSettings {
/**
* Room thermostat
* The grower chooses the thermostat that measures this growing room.
*/
thermostat: LibertasDevice;
/**
* Notes
* The grower records a short note shown with this room.
* [DefaultText]
* Check seedlings each morning
*/
notes: string;
/**
* Alert recipients
* Lists the people who receive temperature warnings for this room.
* ----
* Alert recipient
* Identifies one person who receives this room's warnings.
*/
recipients: LibertasUser[];
}
/**
* Care for a growing room
* The greenhouse monitors one room and warns the selected people when its
* temperature leaves the grower's preferred range. The grower can change that
* range and the fan behavior at any time. Developed by Example Developer
* (example_developer).
* [DefaultText]
* Seedling room care
*/
export function careForRoom(
/**
* Growing-room choices
* The grower chooses the room, warning recipients, and starting notes.
*/
settings: RoomSettings,
): void {
void settings;
}
Rust example
//! Greenhouse climate care
//! Helps growers monitor rooms and maintain suitable plant conditions.
//! #[libertas_default_locale("en-US")]
/// Growing-room settings
/// Describes the conditions the grower chooses for one room.
#[derive(LibertasExport, LibertasAvroDecode)]
pub struct RoomSettings {
/// Room thermostat
/// The grower chooses the thermostat that measures this growing room.
pub thermostat: LibertasDevice,
/// Notes
/// The grower records a short note shown with this room.
/// [DefaultText]
/// Check seedlings each morning
pub notes: String,
/// Alert recipients
/// Lists the people who receive temperature warnings for this room.
/// ----
/// Alert recipient
/// Identifies one person who receives this room's warnings.
pub recipients: Vec<LibertasUser>,
}
/// Care for a growing room
/// The greenhouse monitors one room and warns the selected people when its
/// temperature leaves the grower's preferred range. The grower can change that
/// range and the fan behavior at any time. Developed by Example Developer
/// (example_developer).
/// [DefaultText]
/// Seedling room care
#[libertas_export]
pub fn care_for_room(
/// Growing-room choices
/// The grower chooses the room, warning recipients, and starting notes.
settings: RoomSettings,
) {
let _ = settings;
}
Examples use a placeholder developer profile. A codebot must substitute the current Plaza account and display name under the function-comment contract.
Custom document properties
A custom property, also called a document extension, uses this exact form:
[PropertyName]
Property value starts on the next line.
It continues until another property marker or the end of this document section.
Rules:
- The case-sensitive
[PropertyName]marker is the only content on its line. - Put extensions after the ordinary label and description.
- Put all ordinary text and extension blocks before the first
@Libertas...schema tag in TypeScript JSDoc. The TypeScript document parser stops collecting document text at that first tag. This ordering is also safe in Rust rustdoc. - Multiple extensions are allowed. Never repeat a property name in one section.
- Every value is a string. Leading and trailing blank space is removed while internal newlines are preserved.
- The property is flattened beside the owner's ordinary document members; it
is not nested inside an
Extensionsobject. - Property names and structural keys are stable and are never translated. Property values are localized.
- On a List, the
----divider controls property ownership as well as ordinary text: properties above it belong to the container and properties below it belong to the item. - Unknown valid properties are preserved and translated, but Libertas gives them no generic display or behavior. Use one only when a documented consumer contract defines its semantics. Never invent an extension from its name.
The names DisplayName, Description, List, StringResources, Strings,
Enum, and DocumentVersion are globally reserved. A name that collides with
a structural key at its owning level, including Locale, Types, Name, or
Type, is also reserved. Strings is prohibited; document format 0.0.2 has
one package-owned StringResources map and no function- or type-owned string
table. See the reserved property names and
single package catalog contract.
Standard properties
[TrueText] and [FalseText] are optional localized Boolean field labels.
Each supplied value is one non-empty line. They label true and false
respectively; omitted labels use localized Yes and No. Either property selects
an explicit choice control. Labels do
not supply defaults, change Boolean values, or cause submission. Use ordinary
document localization and fallback.
/// Accept this invitation?
/// Choose whether to accept or decline.
/// [TrueText]
/// Accept
/// [FalseText]
/// Decline
pub accept_invitation: bool,
Without a schema Default, a required Boolean starts unanswered. Both choices
are unselected; the editor holds an undefined value and refuses submission until
one is chosen. It never encodes undefined as false or null. A nullable Boolean's
explicit null remains distinct from the true/false choices; editable nullable
Booleans always offer a third clearing choice. Its caption uses NullText or
localized None. CopyFrom and EditRequest preserve supplied values.
A non-nullable Boolean uses an on/off switch only when it has an explicit Boolean Default and neither custom label is supplied. Otherwise it uses the two-choice control, including when a default preselects an answer. This decision follows metadata, not whether the user has already answered. Fixed and ReadOnly retain their existing restrictions on editing; no new schema attribute or opcode is added.
[DefaultText] supplies one non-empty localized line of initial text on an
effective String field, an EndpointServer field, or a function. On a
function it is the initial task name. It is real, safe content suitable for
the locale and context, never a placeholder instruction, sentinel, resource
key, source identifier, or schema Default. It does not emit or replace the
Default schema attribute. Omit it when the ordinary fallback already gives
exactly the intended value, or no truthful general value exists. Never
fabricate user-specific identity, clinical, financial, or security content.
[NullText] supplies one non-empty localized line for the explicit null of a
nullable field: the null branch of its
Nullable choice and its displayed null.
[SetText] supplies one non-empty localized line for the value branch. An
editable Nullable must declare [NullText], and [SetText] wherever the
control draws a value answer (a Number, String, Bytes, date or time, Table or List), even when the intended text
equals the fallback; the general rule to omit a property matching its fallback
does not apply to them. A nullable Boolean (TrueText, FalseText, NullText) and a
picker (NullText, then its members) never show [SetText]. A client falls back
to localized None and Specify only when a label is missing, and a non-editable
Nullable needs neither: a Nullable is editable when a Request variant or a
function's configuration reaches it without passing through a ReadOnly, Hidden
or Fixed node (Nullable choices, under the
required answer-label rule). Both change only labels:
they neither supply a value nor label false, zero, a present empty string or
collection, an unanswered required field, or a selected Nil Union branch.
Write them as the two answers the person chooses between; SetText is the
lead-in to the value entered right after it, such as “Died in 2026 on” before a
date.
/// Delivery confirmed?
/// Leave this unanswered until delivery is confirmed or declined.
/// [NullText]
/// Awaiting confirmation
pub delivery_confirmed: Option<bool>,
/// Real estate professional status (Pub 925)
/// Choose whether you qualify under section 469(c)(7); each rental still records participation.
/// [NullText]
/// Not a real estate professional
/// [SetText]
/// Real estate professional
pub real_estate_professional: Option<ProfessionalRentals>,
Choose concise, useful, editable initial names for tasks and Endpoint servers.
Their ordinary localized labels already provide naming fallbacks; declare
DefaultText only when the intended initial name differs from that fallback.
No standard property substitutes for the owner's ordinary label and description.
Persisted or user-assigned text has absolute priority and is immutable to
programmatic defaulting. Clients must not replace it during locale, document,
or schema refresh, migration, upgrade, or any later default application. This
includes a deliberately empty saved value or task name. The remaining priority
chain applies only when no persisted value exists and the client is
constructing a new value. For a new String or Endpoint-server presentation
value left to ordinary initialization by the
shared copy rules,
an applicable schema Fixed/Default value has first initialization
priority, localized DefaultText is next, and the ordinary empty or localized
field-label fallback is last. For a new blank task name, localized
DefaultText has first initialization priority, then the localized
function DisplayName, then the native function name.
Answer labels in AI descriptions
The answer labels a field document declares reach the model with the values they name. AI Import result schemas and Hub tool parameter and result descriptions append one line after the node's value-representation hints:
Answer labels: true: <TrueText>; false: <FalseText>; null: <NullText>; a value: <SetText>
Each part appears only when its property is declared, in this order; with none
declared the line is omitted. Only declared labels are sent, never a fallback
such as Yes, No, None, or Specify. The labels are the document locale's text;
the line's own words are fixed English, like the hints. A label changes no
value: the model still reads and returns JSON true, false, null, or the
value itself, and conversion is unchanged. In
AI Search, a Boolean or null
row value whose field declares the matching label is sent as that label.
StringResources prose
StringResources is one package-owned table shared by every function and type.
Stable keys are identifiers and are never translated. See the
single package catalog contract. They are normally not
substitutes for localized prose. The task-access approval UI is the explicit
exception: it always shows each raw function Permissions key or AccessHost
key as the request summary, then separately shows that App package's localized
same-key value as the explanation. Two Apps may request the same permission for
different reasons, so each App owns and supplies its own explanation. See
function permission reasons and
network access reasons. Every
default-locale value and every translated value must be natural user-facing
text and, when formatted, a complete LMF1 message rather than a fragment meant
to be concatenated.
- A permission or network-access reason identifies the App action or service involved, what access is needed, and the user benefit. “Network access required” is not sufficient.
- A concrete
AccessHostreason explains in ordinary terms why the named service is contacted. Reasons for{network_access_local}and{network_access_external}explain why broad local or external connectivity is necessary; the reserved key does not excuse vague prose. - An error message says what happened and, when possible, what the person can do next. Do not expose stack traces, codes, or diagnostics as the explanation.
- A notification or status message names its actor, object, scope, and material condition. Do not assemble grammar from separately translated fragments.
- Persistent record identity uses the declared fixed-width binary key codec. Human-readable names may use the package's localized formatted resources; never replace a key with rendered text or make its identity depend on locale.
- Translation preserves every LMF1 argument and its structure under the translation document contract.
Localized templates stay in the package StringResources catalog. Changing wording does not rename stored keys. Retained legacy data-name tuples follow the message-format compatibility rule.
Translation invariant
Translate all user text, and nothing structural, under the translation document contract, which owns what a translation changes and preserves. See the schema document translation guide for the complete translation workflow.
Codebot workflow
- Inventory every schema-visible declaration and each document node it emits, including both List halves and every Enumeration or Union member.
- Separate user meaning from engineering notes. Put user meaning in extracted rustdoc/JSDoc and preserve engineering facts in ordinary comments or developer documentation.
- Write a standalone natural label and complete description for every authored node. Apply the node-specific rules above.
- Apply the separate function-comment discovery and attribution checklist to every public function.
- Add only documented custom properties, on the correct owner and List side.
Add
DefaultTextonly when a useful initial value differs from the ordinary fallback. Give every editable NullableNullText, andSetTextwhere its control draws a value answer, even when the text equals the fallback (standard properties). - Write complete, specific default-locale
StringResourcesvalues and verify every referenced permission or host reason exists. - Generate and inspect the default document. Confirm ownership, flattening, labels, descriptions, extensions, and intentionally empty generated nodes.
- Run the language checker and Studio schema validation. Treat failures as source defects; never patch generated JSON.
Review checklist
- Every authored package, function, type, parameter, field, List half, Enumeration member, Union variant, and inline value has a non-empty natural label and description.
- Each label is concise, sibling-distinguishable, meaningful aloud, and not a source name, version, sentence, or keyword list.
- Each description adds purpose or meaning and names actor, action, object, scope, condition, and modality wherever behavior is involved.
- Input text explains what the user chooses and its effect; result text explains what is shown, recorded, calculated, or delivered.
- Empty, unavailable, zero, false,
None, andUnknownmeanings are clear where material. - Every Enumeration member and Union variant stands alone. Every List has a
plural container and singular item on the correct sides of
----. - No localized prose leaks source names, protocol roles, transport/storage mechanics, or visual-only cues. Domain terminology is audience-appropriate.
- Hidden and interaction-context values have truthful, non-secret domain descriptions.
- Every custom property is defined by a consuming contract, placed on the right
owner, and follows the same prose rules.
DefaultText,TrueText,FalseText,NullText, andSetTextvalues are non-empty single lines. Omit properties whose intended text exactly matches the ordinary localized fallback, except theNullTextandSetTextan editable Nullable must declare; never fabricate personal or sensitive content to fill a default. - Initial task and Endpoint server names are useful and editable; provide
DefaultTextonly when the ordinary localized naming fallback differs. StringResourcesmessages and reasons are truthful, specific, complete, and preserve LMF1 semantics.- Every function separately passes the function-comment completeness, discovery, and attribution checklist.
- The generated default document was inspected and no generated schema or document JSON was edited by hand.