Worldlets GitHub issue
- Minimal worldlet
- Records
- Object records
- Compact form
- Whole-hash form
- Class definitions
- Bare hashes
- Files
- Temporal mode
- A complete example
vibecode
{"vibecode": { "doc": "worldlet", "role": "ground-up redesign of the worldlet format; the object-description system at the heart of this spec is the universal way the entire Puck ecoverse serializes objects to JSON, not just a Mikobase format", "status": "active_design; nothing_below_is_settled; previous_version_preserved_at_history.md", "audience": "Miko and Claude collaborating on the design", "previous_version": "history.md", "scope": "ecoverse_wide; applies_to_puck_protocol_messages_caspianj_class_literals_mikobase_records_anywhere_objects_ship_as_json" }}
This file is being designed from the ground up. The previous specification is preserved at history.md for reference, but should be treated as historical — do not cite it as authority during this redesign.
The scope is bigger than the file name suggests. The object-description system at the heart of the worldlet format — how a hash carries class identity so it can be rehydrated into a live object — is the universal way the entire Puck ecoverse will serialize objects to JSON. That includes Puck protocol messages, CaspianJ class literals, Mikobase records, anywhere else an object crosses a JSON boundary. Worldlets are the place this format gets pinned down; the rest of the ecoverse inherits it.
Minimal worldlet GitHub issue
vibecode
{"vibecode": { "section": "minimal_worldlet", "role": "shows the smallest valid worldlet; only the format declaration is required today", "format_key_shape": "name_slash_version_string" }}
The smallest possible worldlet is the format declaration alone:
{
"format": "worldlet/1.0"
}
format is a single string of the shape "<name>/<version>". The name identifies the document as a worldlet; the version is the spec version this document conforms to.
Nothing else is required to be a valid worldlet today.
Records GitHub issue
vibecode
{"vibecode": { "section": "records", "role": "introduces the records top-level key; records are a dict keyed by arbitrary strings; values can be any JSON type but hashes always represent objects", "key_shape": "any_unique_string; format_does_not_dictate_generation_scheme", "value_shape": "any_json_value; hashes_always_represent_objects_per_their_shape", "required": false }}
Records go under a top-level records key. The key is a dict; each entry's key is the record's ID and the value is the record itself.
{
"format": "worldlet/1.0",
"records": {
"1": "a",
"2": true
}
}
Two notable shifts from the previous spec:
- Keys are arbitrary strings. The worldlet format does not decide how you generate record keys — UUIDs, sequencer integers, short random strings, anything unique works. The example above uses
"1"and"2"because they are short and readable; that does not make them sequencer IDs. - Allowed value shapes. A record value can be any JSON value. Every value is an object: scalars and arrays carry implicit class identity (no declaration needed); hashes need a way to declare their class, and that class is determined by the hash's shape — see Object records, Compact form, and Bare hashes.
records itself remains optional; a worldlet with no records is still valid.
Object records GitHub issue
vibecode
{"vibecode": { "section": "object_records", "role": "introduces the universal object shape — a hash that declares its class so it can be rehydrated into a live object on the other side; this is the wrapping that makes a hash a valid record value", "object_shape": "class_uns_string_plus_bucket_hash", "wire_singular_vs_runtime_array": "class (singular) is the wire/storage form per standard-fields.md; classes (plural) is the runtime class stack, distinct concept", "scope_note": "the object shape is ecoverse_wide; this section happens to be the place it gets pinned down", "reference_example": "worldlet.json in this directory is the by-example source of truth" }}
Every record value is already an object. Scalars and arrays have implicit class identity and don't need any declaration — they go in as bare JSON. Hashes need a way to declare their class so the importer knows how to rehydrate them; this section covers the explicit hash form. The shape:
{
"class": "puck.uno/color",
"bucket": {"hex": "#aabbcc"}
}
Two fields:
class— a single UNS class name.classis one of the reserved pass-through fields defined in standard-fields.md; it's the canonical way an object declares its identity anywhere in the ecoverse.bucket— a hash holding the object's data. (Per the bucket invariants in the cheat sheet: always a hash, never a scalar/array/null.)
A color record inside a worldlet:
{
"format": "worldlet/1.0",
"records": {
"a": {
"class": "puck.uno/color",
"bucket": {"hex": "#aabbcc"}
}
}
}
This is the "additional structure" the Records section deferred. A bare hash isn't a valid record value because it has no class identity; wrapping it as {class, bucket} gives it the identity needed to round-trip as a live object.
The {class, bucket} shape is the universal object-description format for the entire Puck ecoverse, not just worldlet records — it shows up anywhere an object ships as JSON.
class (singular, wire) is not the same thing as classes (plural, runtime). On the wire, an object declares exactly one class via class. At runtime, the engine maintains a class stack — referred to as the object's classes — that starts with the wire class and can grow via .classes.add (see base-class-use.md). Dispatch walks the runtime classes stack; serialization writes only class.
The fuller reference example for this section is worldlet.json in this directory — a complete worldlet covering class definitions and instances across several classes.
Compact form GitHub issue
vibecode
{"vibecode": { "section": "compact_form", "role": "shorthand for objects whose data can ride on a single value field; trades the bucket wrapping for a bare value when the class knows how to interpret it", "availability": "opt_in_per_class; class must explicitly define how to interpret value; classes without that definition can only be used in long form" }}
For small values, the long form gets noisy:
{
"class": "puck.uno/color",
"bucket": {"hex": "#aabbcc"}
}
A compact form trims it to a bare value:
{
"class": "puck.uno/color",
"value": "#aabbcc"
}
In a worldlet:
{
"format": "worldlet/1.0",
"records": {
"a": {
"class": "puck.uno/color",
"value": "#aabbcc"
}
}
}
The difference from the long form is value instead of bucket. value can hold any JSON type, though convention is to keep it short (typically a string). Compact form is opt-in: a class must explicitly define how to interpret value. Classes that don't define that handling can only be used in long form. For classes that do support it, the implementation is usually trivial. If your data wants more structure than a short scalar, reach for the long form regardless.
Whole-hash form GitHub issue
vibecode
{"vibecode": { "section": "whole_hash_form", "role": "third object form; the class receives the entire record hash as its content, with class as the only reserved marker; the natural fit for class definitions themselves", "availability": "opt_in_per_class; class must explicitly accept the whole-hash form" }}
A class can also opt to receive the entire record hash as its content, with class as the only reserved marker. Everything else in the hash becomes the class's data; no value key, no bucket wrapping.
The natural fit is class definitions themselves — a class definition has multiple top-level fields (name, inherits, fields, methods, etc.) and would read poorly forced into a single value. The minimum class definition:
{
"format": "worldlet/1.0",
"records": {
"a": {
"class": "puck.uno/class"
}
}
}
That's a record of class puck.uno/class (the meta-class for class definitions) with no further content — an empty class definition. A richer class definition would carry additional sibling fields alongside class, all interpreted by puck.uno/class itself.
Like the compact form, the whole-hash form is opt-in: a class must explicitly accept it. Classes that don't can only be used in long form (or compact form, if they support that instead).
worldlet.json uses whole-hash form for every class definition (records a–f): class: "puck.uno/class" plus sibling name, inherits, fields, methods, and uniques fields.
The bare hashes pattern is a special case of this shape — omit class entirely and the default class (puck.uno/hash) takes over, also via whole-hash interpretation.
Class definitions GitHub issue
vibecode
{"vibecode": { "section": "class_definitions", "role": "shows what a class definition looks like in the worldlet format; a class definition is a whole-hash record of class puck.uno/class with name and fields as sibling top-level keys", "meta_class": "puck.uno/class", "name_field": "carries_the_class_UNS_independent_of_the_record_storage_key", "field_conventions": "see_class-definition.md_for_per-field_settings_pending_rework_with_new_spec" }}
A class definition is a whole-hash record of class puck.uno/class. The class's own UNS lives in a name sibling field — distinct from the record's storage key.
Standalone form:
{
"class": "puck.uno/class",
"name": "foo.com/bar",
"inherits": ["blah.com/bear"],
"fields": {
"name": {
"class": "hash",
"of": "string",
"default": {"collapse": true},
"required": true,
"fields": {
"surname": {"required": true},
"middle": {},
"given": {}
}
},
"dob": {"class": "timestamp"}
}
}
Same definition inside a worldlet record:
{
"format": "worldlet/1.0",
"records": {
"abc": {
"class": "puck.uno/class",
"name": "foo.com/bar",
"inherits": ["blah.com/bear"],
"fields": {
"name": {
"class": "hash",
"of": "string",
"default": {"collapse": true},
"required": true,
"fields": {
"surname": {"required": true},
"middle": {},
"given": {}
}
},
"dob": {"class": "timestamp"}
}
}
}
}
inherits is internally an array of UNS class names. Both forms are accepted as input:
"inherits": "blah.com/bear"
"inherits": ["blah.com/bear"]
The string form is shorthand for a one-element array — same semantics, less noise when there's only one parent. The previous spec only accepted the string form; the new spec keeps it working while adding the array form, which enables multiple parents at the schema level.
Mechanics of multi-parent resolution (order, conflicts) are pending — only the shape has been pinned down so far.
The record key ("abc" above) is just the storage handle; the class's identity as referenced by other records is the name field ("foo.com/bar"). This is a meaningful shift from the previous spec, where the class's UNS came from the dict key of an enclosing classes object. In the new design, class definitions are ordinary records with arbitrary storage keys; the name field carries the semantic identity.
Class-level multi-field unique constraints go in a uniques array. Each entry is itself an array of field names whose combined values must be unique across all records of the class:
"uniques": [
["person", "episode"]
]
The shape is an array of arrays so a class can declare multiple independent constraints: [["a", "b"], ["c", "d"]] means "(a, b) is unique" AND "(c, d) is unique" — two separate rules.
Field-definition shape (class, required, default, of, nested fields for hashes, etc.) is shown in use throughout worldlet.json records a-f. A consolidated constraint catalog hasn't been written yet for the new spec; the by-example reference is the source until it lands.
Bare hashes GitHub issue
vibecode
{"vibecode": { "section": "bare_hashes", "role": "explains that a hash with no class declaration defaults to an instance of puck.uno/hash; documents the three equivalent forms of an empty hash record and the preferred form for record values", "default_class": "puck.uno/hash", "preferred_form_for_records": "bucket-only ({\"bucket\": {}}); bare {} is valid but discouraged" }}
The simplest way to make a hash object is the empty hash itself:
{}
This is equivalent to:
{"bucket": {}}
Which is equivalent to the fully explicit form:
{"class": "puck.uno/hash", "bucket": {}}
All three are empty instances of puck.uno/hash — the default class for any hash that doesn't declare its own.
Preferred form for record values: {"bucket": {}}. Bare {} is valid but discouraged — a lone empty hash sitting next to other records reads ambiguously. The bucket key makes the record's intent explicit without much extra noise.
Discouraged:
{
"format": "worldlet/1.0",
"records": {
"a": {
"class": "puck.uno/color",
"value": "#aabbcc"
},
"b": {}
}
}
Preferred:
{
"format": "worldlet/1.0",
"records": {
"a": {
"class": "puck.uno/color",
"value": "#aabbcc"
},
"b": {"bucket": {}}
}
}
Files GitHub issue
vibecode
{"vibecode": { "section": "files", "role": "top-level files dict carrying binary file metadata; binary content lives in the file_chunks sibling", "required_fields": ["sha256", "mime"], "optional_fields": ["created_at"], "key_shape": "any_unique_string; convention_is_uuid_v4", "records_reference_files_via": "puck.uno/dbfile_field_class_holding_the_file_key_as_a_bare_string" }}
Worldlets can carry attached binary files in a top-level files dict, parallel to records. Each file's binary content is split across one or more chunks in a sibling file_chunks dict; the metadata (identity, integrity hash, MIME info) lives in files.
{
"format": "worldlet/1.0",
"files": {
"d1e2f3a4-0001-0001-0001-000000000001": {
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime": {"type": "image/png", "encoding": "base64"}
}
},
"file_chunks": {
"c1d2e3f4-0001-0001-0001-000000000001": {
"file": "d1e2f3a4-0001-0001-0001-000000000001",
"index": 0,
"last": true,
"data": "iVBORw0KGgo..."
}
}
}
Two required fields on every file record:
sha256— SHA-256 hex digest of the assembled file content. Integrity check: decoding the chunks per the file'smime.encodingand concatenating inindexorder must produce content whose SHA-256 matches this string. A file record withoutsha256is rejected by the importer.mime— a hash withtype(the MIME type, e.g."image/png","text/plain; charset=utf-8") andencoding(how chunkdatais encoded for transport — typically"base64"for binary content). A file record withoutmimeis rejected by the importer.
An optional created_at field can carry an ISO 8601 timestamp for the file's origin time:
"files": {
"d1e2f3a4-0001-0001-0001-000000000001": {
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"created_at": "2364-01-01T00:00:00Z",
"mime": {"type": "image/png", "encoding": "base64"}
}
}
files keys follow the same any-unique-string rule as record keys (UUID v4 conventional but not required — see Conflict policy in the historical spec for the rationale, pending reformulation).
File chunks GitHub issue
vibecode
{"vibecode": { "section": "file_chunks", "role": "top-level file_chunks dict holding the binary content of files in pieces; reassembled in index order to reconstruct each file", "key_shape": "any_unique_string; convention_is_uuid_v4", "completeness_marker": "exactly_one_chunk_per_file_carries_last_true", "encoding": "per_parent_files_mime_encoding" }}
Each entry in file_chunks carries one slice of one file's binary content:
file— the key of the parent record in thefilesdict.index— zero-based chunk position. Chunks reassemble in ascendingindexorder.last—trueon exactly one chunk per file: the final piece. Its presence is positive confirmation the file finished writing. A file whose chunks include nolast: trueentry is incomplete and the importer rejects it.data— chunk content, encoded per the parent file'smime.encoding.
Empty files are represented by a single chunk with data: "" and last: true.
Records that reference files GitHub issue
vibecode
{"vibecode": { "section": "records_that_reference_files", "role": "shows how a record bucket points at an attached file by storing the file's key as a bare string under a puck.uno/dbfile field", "reference_form": "bare_key_string_no_wrapper", "field_class": "puck.uno/dbfile" }}
A record references a file by storing the file's key (the parent dict key in files) in a bucket field. Two equivalent forms are accepted.
Schema-declared (bare key string). The field's declared class is puck.uno/dbfile; the value is just the file's key:
{
"class": "starfleet.com/officer",
"bucket": {
"name": {"surname": "Data"},
"rank": "Lieutenant Commander",
"serial": "SC-499-235",
"photo": "d1e2f3a4-0001-0001-0001-000000000001"
}
}
The puck.uno/dbfile field class on photo is what tells the engine the value is a file reference rather than an opaque string. The field-class constraint catalog hasn't been re-homed yet; the worldlet.json examples are the canonical reference in the meantime.
Inline-typed (compact-form object). The value carries its own class identity via the universal {class, value} compact form:
{
"class": "starfleet.com/officer",
"bucket": {
"name": {"surname": "Data"},
"rank": "Lieutenant Commander",
"serial": "SC-499-235",
"photo": {"class": "puck.uno/reference/file", "value": "d1e2f3a4-0001-0001-0001-000000000001"}
}
}
The field doesn't need a pre-declared file-reference class — the value identifies itself as a puck.uno/reference/file. This form is useful when the surrounding schema is loose or absent, or when a bucket field can hold values of multiple classes and each value declares its own type.
Both forms resolve to the same file. The schema-declared form is terser when the field is always a file reference; the inline-typed form travels with its own type when schema declaration isn't available.
Temporal mode GitHub issue
vibecode
{"vibecode": { "section": "temporal_mode", "role": "describes the temporal worldlet shape; records carry only identity stubs and per-version state lives under a top-level history dict; this is the same worldlet format as the non-temporal shape, distinguished by the presence of history", "discrimination": "structural; presence of history at top level signals temporal", "history_entry_shape": "flat_hash_combining_object_form_compact_or_long_with_metadata_identity_and_timestamp" }}
A worldlet can be in non-temporal mode (the default) or temporal mode. The same format: "worldlet/1.0" covers both — the shape differs in whether per-version history is carried separately from current state.
The non-temporal form already shown above carries each record's current state directly under records:
{
"format": "worldlet/1.0",
"records": {
"a": {"class": "puck.uno/color", "value": "#aabbcc"}
}
}
The temporal form pulls state out of records and into a separate top-level history dict. Each entry under records becomes an identity stub; the real content lives in history entries that reference the identity:
{
"format": "worldlet/1.0",
"records": {
"a": {}
},
"history": {
"123": {
"identity": "a",
"timestamp": "2026-05-28T07:30:00Z",
"class": "puck.uno/color",
"value": "#aabbcc"
}
}
}
What changes:
recordsentries become identity stubs. Each entry just declares that the record exists; the current state is reconstructed from history.- A top-level
historydict appears. Keyed by history-entry IDs (arbitrary strings, same rule as record keys); each entry combines object form with version metadata. - A history entry is a flat hash carrying both an object (in compact form above —
class+value) and two metadata fields:identityreferencing the record key inrecords, andtimestampfor when this version was written.
Timestamps are ISO 8601 strings with an explicit UTC offset — e.g. "2026-05-28T07:30:00Z" or "2026-05-28T03:30:00-04:00". The Z form (zero offset) is preferred for wire format because it avoids the per-host local-zone interpretation that bare 2026-05-28T07:30:00 would invite. The full per-component rules live with the puck.uno/time class spec — see time.md. UTC offsets only; named IANA zones (America/New_York, etc.) are out of scope per the time-class spec.
A complete example GitHub issue
vibecode
{"vibecode": { "section": "complete_example", "role": "the complete example IS [worldlet.json](worldlet.json) in this directory; the markdown source uses an Orlando file-include directive to pull the file's contents into the rendered page on demand, so the example shown stays in lockstep with the canonical source", "include_mechanism": "<!-- file: PATH --> directive — Orlando reads PATH (relative to this markdown file's directory) and inlines its contents as a fenced code block; see orlando/lua/orlando/page.lua process_file_includes", "canonical_source": "worldlet.json in this directory; covers class definitions for person/officer/starship/planet/voyage/assignment, instances of each, attached files, nested methods, references between records" }}
The complete example is worldlet.json in this directory — the reference-by-example for the entire format. It carries six class definitions (person, officer, starship, planet, voyage, assignment), sixteen instances across those classes, two attached files with chunks, an inline-object photo field on Picard, nested methods on officer, and a class-level multi-field unique constraint on voyage.
Rather than duplicate the file in the spec (and risk it drifting out of sync), this section uses Orlando's file-include directive (<!-- file: worldlet.json -->) to pull the file in on demand and render it as a JSON code block. What you see below is the file's current contents.
{
"comment": "Reference-by-example worldlet for the Puck object format. Class definitions (records a-f) use the whole-hash form that puck.uno/class opts into \u2014 class identity at the record's top level alongside the definition's properties. Instance records (g-v) use the explicit {bucket, stack} shape from the objects spec. Comments on each record say what to notice. The 'files' / 'file_chunks' dicts use the file-record shape from the worldlets spec, not the object shape.",
"format": "worldlet/1.0",
"records": {
"a": {
"comment": "Class definition in whole-hash form: class='puck.uno/class' plus the definition's properties (name, description, fields) at the record's top level \u2014 the shorthand puck.uno/class opts into. The 'name' field shows the hash-of-typed-sub-fields shape with 'of' setting the default sub-field class, 'default' applying sub-field-wide settings, and 'fields' overriding per sub-field.",
"class": "puck.uno/class",
"name": "starfleet.com/person",
"description": "A person.",
"fields": {
"name": {
"class": "hash",
"of": "string",
"required": true,
"default": {
"collapse": true
},
"description": "Surname + given + optional middle name.",
"fields": {
"surname": {
"required": true
},
"given": {},
"middle": {}
}
},
"dob": {
"class": "timestamp"
}
}
},
"b": {
"comment": "Class definition with inherits (single-parent here; array form accepts multiple), a methods block, params as a hash of option-hashes (not a positional array), and two method-body forms: Caspian source strings (salute, tea_earl_grey_hot) plus the nested-method namespace beverage.nested.{tea_earl_grey_hot, coffee_black}.",
"class": "puck.uno/class",
"name": "starfleet.com/officer",
"description": "A commissioned Starfleet officer.",
"inherits": [
"starfleet.com/person"
],
"fields": {
"rank": {
"class": "string",
"required": true
},
"serial": {
"class": "string",
"required": true,
"unique": true
},
"active": {
"class": "boolean",
"default": true
}
},
"methods": {
"beverage": {
"nested": {
"tea_earl_grey_hot": {
"description": "Picard's preferred way to interface with a replicator.",
"params": {
"variety": {
"class": "string",
"required": true,
"description": "What kind of tea to order."
},
"temperature": {
"class": "string",
"required": true,
"description": "Serving temperature (typically 'hot')."
}
},
"returns": {
"class": "string",
"description": "Beverage description, or null if the replicator refuses."
},
"body": "if ($variety == 'coffee')\n puts 'Replicator: That order requires Captain Janeway.'\n return (null)\nend\n\nputs 'Tea. ' + $variety + '. ' + $temperature + '.'\nputs '*replicator hums in satisfaction*'\nreturn ('A steaming cup of ' + $variety + ' appears.')"
},
"coffee_black": {
"description": "Janeway's preferred way to interface with a replicator. Strictly black; rejects modifiers.",
"params": {
"style": {
"class": "string",
"required": true,
"description": "Coffee style. Janeway accepts only 'black'."
},
"temperature": {
"class": "string",
"default": "hot",
"description": "Serving temperature. Defaults to 'hot' because Janeway."
}
},
"returns": {
"class": "string",
"description": "Beverage description, or null if the replicator refuses."
},
"body": "if ($style != 'black')\n puts 'Replicator: The captain takes it black.'\n return (null)\nend\n\nputs 'Coffee. ' + $style + '. ' + $temperature + '.'\nputs '*Janeway sighs contentedly*'\nreturn ('A steaming cup of coffee appears.')"
}
}
},
"salute": {
"description": "Render a verbal salute from this officer toward someone of a given rank.",
"params": {
"name": {
"class": "string",
"required": true,
"description": "Name of the person being saluted."
},
"rank": {
"class": "string",
"required": true,
"description": "Rank of the person being saluted."
},
"attention": {
"class": "boolean",
"default": false,
"description": "Call attention before the salute."
},
"style": {
"class": "string",
"one_of": [
"formal",
"casual"
],
"default": "formal"
},
"props": {
"splat": true,
"description": "Any extra context the renderer may use."
}
},
"returns": {
"class": "string",
"description": "The rendered salute line."
},
"body": "puts $rank + ' ' + $name + ', sir!'"
}
}
},
"c": {
"comment": "Class definition with field-level uniqueness (unique: true on registry) and a method body in CaspJ tree form rather than Caspian source string.",
"class": "puck.uno/class",
"name": "starfleet.com/starship",
"description": "A Starfleet starship.",
"fields": {
"registry": {
"class": "string",
"required": true,
"unique": true,
"description": "Hull registry (e.g. NCC-1701)."
},
"name": {
"class": "string",
"required": true,
"description": "Display name (Enterprise, Defiant)."
},
"classification": {
"class": "string",
"required": true,
"description": "Spaceframe class (Constitution, Galaxy, Sovereign)."
},
"launched": {
"class": "timestamp",
"description": "Commissioning date."
},
"active": {
"class": "boolean",
"default": true,
"description": "Currently in service."
}
},
"methods": {
"hail": {
"description": "Open a channel to the target.",
"params": {
"target": {
"class": "string",
"required": true,
"description": "Target UNS (ship, station, or planet)."
},
"priority": {
"class": "string",
"one_of": [
"routine",
"priority",
"emergency"
],
"default": "routine"
},
"subject": {
"class": "string",
"description": "Optional subject line for the hail."
}
},
"returns": {
"class": "boolean",
"description": "True iff the channel opened."
},
"body": [
[
{
"bwc": "puts"
},
[
{
"value": "Hailing "
},
"+",
{
"var": "target"
}
]
]
]
}
}
},
"d": {
"comment": "Class definition with a one_of enum constraint on classification and a method body that reads instance variables via {ivar: ...} in its CaspJ tree.",
"class": "puck.uno/class",
"name": "federation.com/planet",
"description": "A planet recognized by the Federation cartographic registry.",
"fields": {
"name": {
"class": "string",
"required": true,
"description": "Common name (Earth, Vulcan, Risa)."
},
"designation": {
"class": "string",
"required": true,
"unique": true,
"description": "Astronomical designation (Sol III, 40 Eridani A II)."
},
"system": {
"class": "string",
"required": true,
"description": "Parent star system."
},
"classification": {
"class": "string",
"one_of": [
"M",
"L",
"K",
"Y",
"D",
"J",
"T"
],
"description": "Habitability class."
},
"federation_member": {
"class": "boolean",
"default": false,
"description": "Member of the United Federation of Planets."
}
},
"methods": {
"describe": {
"description": "Return a one-line summary of the planet.",
"params": {},
"returns": {
"class": "string"
},
"body": [
[
{
"bwc": "puts"
},
[
{
"ivar": "name"
},
"+",
[
{
"value": " ("
},
"+",
[
{
"ivar": "designation"
},
"+",
{
"value": ")"
}
]
]
]
]
]
}
}
},
"e": {
"comment": "Class definition with a class-level multi-field unique constraint via the 'uniques' array. Each inner array is a tuple whose combined values must be unique across all records of the class; here (ship, voyage_number).",
"class": "puck.uno/class",
"name": "starfleet.com/voyage",
"description": "A discrete deployment of a Starfleet ship.",
"fields": {
"ship": {
"class": "string",
"required": true,
"description": "Registry of the ship on this voyage."
},
"voyage_number": {
"class": "number",
"required": true,
"description": "Sequential number within the ship's history."
},
"start_date": {
"class": "timestamp",
"required": true
},
"end_date": {
"class": "timestamp",
"description": "Absent while the voyage is still under way."
},
"mission_type": {
"class": "string",
"one_of": [
"exploration",
"diplomatic",
"patrol",
"rescue",
"combat"
],
"default": "exploration"
}
},
"uniques": [
[
"ship",
"voyage_number"
]
]
},
"f": {
"comment": "Class definition with reference fields (class puck.uno/reference + target UNS \u2014 typed pointers between record kinds) and the deliberately-preserved 'unqiues' typo.",
"class": "puck.uno/class",
"name": "starfleet.com/assignment",
"fields": {
"person": {
"class": "puck.uno/reference",
"target": "starfleet.com/person",
"required": true
},
"starship": {
"class": "puck.uno/reference",
"target": "starfleet.com/starship",
"required": true
},
"status": {
"class": "string",
"required": true
}
},
"unqiues": [
[
"person",
"starship"
]
]
},
"g": {
"comment": "Instance record in the {bucket, stack} shape: instance data in bucket, class identity (starfleet.com/officer) in the stack's 'a' platter under shadow. The 'photo' field is itself an inline object using the same {bucket, stack} shape \u2014 a puck.uno/reference/file value pointing at the photo file in the worldlet's files dict.",
"bucket": {
"name": {
"surname": "Picard",
"given": "Jean-Luc"
},
"dob": "2305-07-13T00:00:00Z",
"rank": "Captain",
"serial": "SP-937-215",
"active": true,
"photo": {
"bucket": {
"value": "f1a2b3c4-0001-0001-0001-000000000001"
},
"stack": {
"shadow": {},
"a": {
"class": "puck.uno/reference/file"
}
}
}
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/officer"
}
}
},
"h": {
"comment": "Same instance shape as Picard, with a 'middle' field present on the name hash.",
"bucket": {
"name": {
"surname": "Riker",
"given": "William",
"middle": "Thomas"
},
"dob": "2335-08-19T00:00:00Z",
"rank": "Commander",
"serial": "SC-231-427",
"active": true,
"photo": "f1a2b3c4-0002-0002-0002-000000000002"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/officer"
}
}
},
"i": {
"comment": "Same instance shape; only 'surname' on the name hash (given and middle are absent since they aren't required on the person class).",
"bucket": {
"name": {
"surname": "Data"
},
"dob": "2338-02-02T00:00:00Z",
"rank": "Lieutenant Commander",
"serial": "SC-499-235",
"active": true,
"photo": "f1a2b3c4-0003-0003-0003-000000000003"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/officer"
}
}
},
"j": {
"comment": "Standard officer instance.",
"bucket": {
"name": {
"surname": "Janeway",
"given": "Kathryn"
},
"dob": "2335-05-20T00:00:00Z",
"rank": "Captain",
"serial": "SC-957-398",
"active": true,
"photo": "f1a2b3c4-0004-0004-0004-000000000004"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/officer"
}
}
},
"k": {
"comment": "Starship instance.",
"bucket": {
"registry": "NCC-1701-D",
"name": "Enterprise",
"classification": "Galaxy",
"launched": "2363-10-04T00:00:00Z",
"active": true
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/starship"
}
}
},
"l": {
"comment": "Another starship \u2014 no notable structural variation.",
"bucket": {
"registry": "NX-74205",
"name": "Defiant",
"classification": "Defiant",
"launched": "2370-01-01T00:00:00Z",
"active": true
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/starship"
}
}
},
"m": {
"comment": "Standard instance: bucket holds the ship data; the 'a' platter in the stack carries the class identity (starfleet.com/starship). This is the canonical shape for any instance record under the new spec.",
"bucket": {
"registry": "NCC-74656",
"name": "Voyager",
"classification": "Intrepid",
"launched": "2371-01-01T00:00:00Z",
"active": true
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/starship"
}
}
},
"n": {
"comment": "Planet instance. The 'classification' value is one of the strings declared in the planet class's one_of enum.",
"bucket": {
"name": "Earth",
"designation": "Sol III",
"system": "Sol",
"classification": "M",
"federation_member": true
},
"stack": {
"shadow": {},
"a": {
"class": "federation.com/planet"
}
}
},
"o": {
"comment": "Another planet; same one_of constraint applies.",
"bucket": {
"name": "Vulcan",
"designation": "40 Eridani A II",
"system": "40 Eridani A",
"classification": "M",
"federation_member": true
},
"stack": {
"shadow": {},
"a": {
"class": "federation.com/planet"
}
}
},
"p": {
"comment": "Another planet.",
"bucket": {
"name": "Risa",
"designation": "Epsilon Ceti B II",
"system": "Epsilon Ceti B",
"classification": "M",
"federation_member": true
},
"stack": {
"shadow": {},
"a": {
"class": "federation.com/planet"
}
}
},
"q": {
"comment": "Voyage instance \u2014 pairs with r to demonstrate the multi-field unique constraint declared on the voyage class. Here (ship='NCC-1701-D', voyage_number=1).",
"bucket": {
"ship": "NCC-1701-D",
"voyage_number": 1,
"start_date": "2364-10-04T00:00:00Z",
"mission_type": "exploration"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/voyage"
}
}
},
"r": {
"comment": "Second voyage record with voyage_number=1 again. Allowed because it pairs with a different ship (NCC-74656); the uniqueness is on the tuple, not on voyage_number alone.",
"bucket": {
"ship": "NCC-74656",
"voyage_number": 1,
"start_date": "2371-01-01T00:00:00Z",
"mission_type": "exploration"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/voyage"
}
}
},
"s": {
"comment": "Assignment instance. The 'person' and 'starship' field values are puck.uno/reference strings keyed to other records in this worldlet ('g' = Picard, 'k' = Enterprise-D).",
"bucket": {
"person": "g",
"starship": "k",
"status": "commanding officer"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/assignment"
}
}
},
"t": {
"comment": "Another assignment \u2014 same shape.",
"bucket": {
"person": "h",
"starship": "k",
"status": "first officer"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/assignment"
}
}
},
"u": {
"comment": "Another assignment.",
"bucket": {
"person": "i",
"starship": "k",
"status": "operations officer"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/assignment"
}
}
},
"v": {
"comment": "Final assignment. Note the targets are 'j' and 'm' \u2014 Janeway commanding Voyager.",
"bucket": {
"person": "j",
"starship": "m",
"status": "commanding officer"
},
"stack": {
"shadow": {},
"a": {
"class": "starfleet.com/assignment"
}
}
}
},
"files": {
"f1a2b3c4-0001-0001-0001-000000000001": {
"comment": "files dict entry. Required fields: 'sha256' (SHA-256 hex digest of the assembled content, for integrity) and 'mime' (a hash with 'type' and 'encoding'). PNG image with base64-encoded chunks.",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime": {
"type": "image/png",
"encoding": "base64"
}
},
"f1a2b3c4-0002-0002-0002-000000000002": {
"comment": "Another PNG file; same shape.",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime": {
"type": "image/png",
"encoding": "base64"
}
},
"f1a2b3c4-0003-0003-0003-000000000003": {
"comment": "Another PNG file; same shape.",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime": {
"type": "image/png",
"encoding": "base64"
}
},
"f1a2b3c4-0004-0004-0004-000000000004": {
"comment": "Another PNG file; same shape.",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime": {
"type": "image/png",
"encoding": "base64"
}
},
"f1a2b3c4-0005-0005-0005-000000000005": {
"comment": "Two variations from the photo files above: optional 'created_at' timestamp, and mime.encoding='utf-8' (chunk data holds raw text directly, not base64). Also: this file is standalone \u2014 no record references it. Files don't have to be attached to records.",
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"created_at": "2364-01-04T11:00:00Z",
"mime": {
"type": "text/plain",
"encoding": "utf-8"
}
}
},
"file_chunks": {
"c1d2e3f4-0001-0001-0001-000000000001": {
"comment": "file_chunks dict entry. 'file' is the parent file's key; 'index' is the 0-based chunk position (chunks reassemble in ascending index order); 'last': true marks the final chunk (exactly one per file \u2014 positive confirmation the file finished writing); 'data' carries the chunk content encoded per the parent file's mime.encoding (base64 here).",
"file": "f1a2b3c4-0001-0001-0001-000000000001",
"index": 0,
"last": true,
"data": "iVBORw0KGgoAAAANSUhEUgAAA..."
},
"c1d2e3f4-0002-0002-0002-000000000002": {
"file": "f1a2b3c4-0002-0002-0002-000000000002",
"index": 0,
"last": true,
"data": "iVBORw0KGgoAAAANSUhEUgAAB..."
},
"c1d2e3f4-0003-0003-0003-000000000003": {
"file": "f1a2b3c4-0003-0003-0003-000000000003",
"index": 0,
"last": true,
"data": "iVBORw0KGgoAAAANSUhEUgAAC..."
},
"c1d2e3f4-0004-0004-0004-000000000004": {
"file": "f1a2b3c4-0004-0004-0004-000000000004",
"index": 0,
"last": true,
"data": "iVBORw0KGgoAAAANSUhEUgAAD..."
},
"c1d2e3f4-0005-0005-0005-000000000005": {
"comment": "Same chunk shape, but 'data' is raw utf-8 text instead of base64, per the parent file's mime.encoding='utf-8'. Single-chunk file \u2014 index 0, last true.",
"file": "f1a2b3c4-0005-0005-0005-000000000005",
"index": 0,
"last": true,
"data": "Stardate 41174.3. The Enterprise is en route to Deneb IV..."
}
}
}