The Cyberia content: the foundation, the instances, the sagas, the semantic generator and the versioned content artifact the engine consumes.
This repository creates content. The engine imports, materializes, releases and deploys it.
cyberia-content ──validate──► build ──► dist/ (the content artifact: data and its manifest)
│
engine: this checkout (CYBERIA_CONTENT_ROOT) or a packed copy of it
│
cyberia instance --import · content import · content-release
| Path | Holds |
|---|---|
src/content/foundation/ |
The functional blueprint: world, environment, items, characters, maps, quests, actions |
src/content/instances/ |
Instance backups, one directory per instance code, as the engine exports it |
src/content/sagas/ |
Saga packages, one file per saga code |
src/content/procedural/ |
Genesis Templates and Palette Templates: where a procedural generation starts |
src/schema/ |
The definition schema and the runtime contract (generated by the engine) |
src/validation/ |
Content rules and the canonical JSON form |
src/procedural.js |
Reads the procedural templates and checks them against the foundation |
src/compiler.js |
Definitions to runtime documents: one list per document family |
src/generator/ |
Semantic generation: prompts, stages, the saga package, the Gemini client |
src/packaging/ |
The artifact: build, manifest and digests |
npm install
node bin/cyberia-content.js <command>| Command | Does |
|---|---|
validate [--fix] |
Validate canonical form, foundation, sagas and instances; --fix rewrites form |
saga generate |
Compose a saga with Google Gemini and write its package |
saga instance <saga-code> [--force] [--dry-run] |
Write the instance backup of a saga |
build |
Write dist/ from the committed content |
pack |
Build and pack artifacts/cyberia-content-<version>.tgz |
--env-file <path> reads the environment from a file. ./.env is read when it exists.
cyberia-content.config.js configures this checkout. Every command and test reads it.
| Field | Holds |
|---|---|
ignoreSagas |
Saga codes every process skips, as if their package does not exist. dist/ omits them |
Remove a saga code from ignoreSagas when its package is valid.
The foundation defines what exists and how it functions. Studio adds only how it looks (render) and where it is (placement).
A definition id is <kind>.<slug>, for example biome.violet-strata. One JSON file holds one
definition, at <category>/<id>.json. Every definition has a name, a description and a role.
| Kinds | Define |
|---|---|
region, biome, faction, origin, material |
The world. Only the foundation defines them |
floor, tree, vegetation, rock, prop, structure, ruin, portal |
Environment: each one is an Object Layer item and an entity |
weapon, armor, skin, projectile, currency, resource, consumable, relic, technology, implant, tool |
Carried items |
character |
Loadout, carried items, the spawned entity and a greeting |
ability, effect |
What items do: a runtime skill handler and its effects |
map |
A place of one biome, and its composition: each entity and how many |
quest |
Provider, steps, objectives, rewards and talk |
action |
What a provider offers: shop, recipes and storage |
An item or environment definition carries an objectLayer block: the item type, the activable
flag and the stats. Its item label is its slug. Its artBrief tells an artist what to draw. It holds
no pixels, frames, atlases or CIDs.
A consumable heals its resistance stat as life and carries no other stat. An ability with the
zero-waste-auto-consume-heal logic lets its holder consume one unit by itself, once the missing
life takes the whole heal. The ability names no summons: it summons the consumable that carries
it, and only a consumable may carry it. Its optional loot names the pickup behavior of the item as
world loot (consume-on-pickup-heal); the compiler writes it as a loot entity-type default.
Without it, a world pickup of the item grants it.
A biome carries a palette: #rrggbb colors by role (base, shadow, highlight, outline,
and optionally accent and special). The Studio paints with it; it is guidance, never render.
A map composes entities its biome holds. The compiled map holds none: Studio places each one and tracks the composition against the context index. A quest provider and each talk target stand behind an action of the same set.
foundation.json holds the schemaVersion of the definition format and the baseline: the
definition each runtime entity type resolves against when a world authors none (entities), and
the item whose activable flag and stats a new item of each type starts from (items).
The engine generates candidate renders from these templates. They are where a generation starts, never a render, and they define no item.
A Genesis Template, procedural/genesis-templates/<itemType>.<slug>.json, is a reusable visual
start for one item type:
| Field | Holds |
|---|---|
canvas |
Width and height in cells |
directions |
One region map per direction code: one string per row, one letter per cell |
legend |
The region id each letter marks; . marks no region |
roles |
The palette roles: the regions and the shadow, base and highlight tones of each |
outline |
The outline color |
frameDurationMs |
The frame duration of a render that starts from the template |
A role with artDirection takes the colors the art direction of an item names.
A Palette Template, procedural/palettes/<itemType>.<slug>.json, gives a base color to roles of its
item type: the roles of a Genesis Template, outline and accent. It has a family, the foundation
biomes it suits (biomeTags, by slug) and its constraints: the least OKLab distance between the
outline and the contrastRoles. The engine derives the shadow and highlight of each role and checks
the contrast.
A new item of a type takes its function from baseline.items, its look from a Genesis Template and
its colors from a palette. A human then finishes it in the Object Layer Studio.
src/compiler.js turns definitions into runtime documents, one list per family, in import order:
| Family | Documents |
|---|---|
object-layers |
One Object Layer item per labeled definition, without render |
entity-type-defaults |
One per entity definition: live, dead, drop and inventory items, behavior |
skills |
One per item whose abilities name a runtime handler |
maps |
One per map: code, name, description and biome tags; no entities |
quests |
Steps, objectives and rewards by item label; source map and cell null |
dialogues |
Item flavor text, character greetings and quest talk |
actions |
Shop, recipes, storage and quest talk codes; source map and cell null |
The same compiler compiles the foundation and each saga. It also derives the context index the Studio reads: every definition of the foundation and the sagas, its source, the item label and the map entity it answers to, and every reference in both directions with the field that makes it.
The generator composes a saga over the foundation. Gemini reuses foundation definitions and adds only what the saga lacks, in the definition model of the foundation.
theme (from --prompt, or synthesized from the lore)
│
▼
Google Gemini, six bounded stages, each one returning definitions
│ 1 composition → saga identity, the foundation ids it uses, new definitions
│ 2 maps → maps of foundation biomes, and what each one composes
│ 3 quests → quests over characters and items
│ 4 dialogues → greetings of new characters and the talk of quests
│ 5 actions → what each quest provider and talk target offers
│ 6 abilities → abilities of new items, reused or defined
▼
normalize → validate → src/content/sagas/<saga-code>.json
The composition stage reads a compact index of the foundation. Each later stage reads the full definitions of what the saga uses. The model follows these rules, and normalization enforces them:
- Reuse a foundation definition by its exact id. Never define a duplicate.
- Never define a region, biome, faction, origin or material.
- Use only the skill handlers of the runtime contract.
- Write no coordinates, cells, grids, portal endpoints, pixels, frames, atlases or CIDs.
An invalid package is written for a human to fix. The command then fails with its findings.
# A lore-grounded saga. The world foundation is the lore unless --lore-path names a document.
node bin/cyberia-content.js saga generate
# A given theme, validated but not written
node bin/cyberia-content.js saga generate --prompt "A relay keeper in the ash wastes" --dry-runGEMINI_API_KEY must be in the environment. Steer a synthesized theme with --space-context
(physical, mixed, hyperspace), --tone (adventure, politics, tragic, comedy),
--faction-context (foundation confederations that drive the saga, for example nova,zenith),
--character-context (name pools) and --cultural-exposure (cosmopolitan, local).
| Field | Holds |
|---|---|
schemaVersion |
Version of the package format |
foundationVersion |
The content version the saga was composed against |
saga |
code, name, description |
references |
Every foundation id the definitions name |
definitions |
The new definitions, maps, quests and actions, in the foundation model |
The build compiles a package with the compiler of the foundation. The saga adds its own documents
of every family, its CyberiaSaga record and the shell of its instance.
saga instance <saga-code> writes src/content/instances/<saga-code>/ from the saga package
alone, in the layout of an engine instance export. The same package always writes the same bytes.
The engine imports it with cyberia instance <saga-code> --import.
| Holds | From |
|---|---|
| The instance and its conf | The saga code. The conf names every entity-type default of the backup |
| Maps | Every saga map, with no entities |
| Entity-type defaults | Every saga entity, and every foundation entity a saga map composes |
| Quests, actions | Every saga quest and action, with no source |
| Object Layer items | Every item the defaults, actions and quests name, or a skill summons; no render |
| Skills, dialogues, the saga | The skills of those items, their lines and the action talk, the CyberiaSaga |
The command refuses an instance directory that exists: it holds the render and placement of
Studio. --force replaces it. An engine export keeps only the quests and actions Studio placed.
An instance with object-layers/ is a complete snapshot: object-layers/<itemId>.json is the
definition the item ran when the engine exported it, and an import binds the item to it again.
Quests and actions name items by item id. In a snapshot, a quest or an action may also pin an item
(objectLayerCid), but only to the definition the snapshot binds it to. validate reports any
other pin.
src/schema/runtime-contract.json holds the runtime vocabulary content uses: item types, entity
types, stat bounds, skill handlers, quest step types and the item dialogue prefix. The engine owns
that vocabulary and generates the file with node bin/cyberia stat-contract. Never edit it.
The artifact is data: dist/ and its manifest. It holds no code; the consumer verifies it.
| Path | Holds |
|---|---|
dist/manifest.json |
Identity and the digest of every file |
dist/context.json |
The context index of the Studio |
dist/foundation/<family>.json |
The compiled foundation, one file per document family |
dist/foundation/baseline.json |
The entity-type defaults a world resolves against |
dist/foundation/item-baseline.json |
The item label a new item of each type takes its function from |
dist/procedural/genesis-templates.json |
Every Genesis Template |
dist/procedural/palettes.json |
The palette families, in order, and every Palette Template |
dist/sagas/<code>/<family>.json |
Each compiled saga, one file per document family |
dist/sagas/<code>/saga.json |
Its CyberiaSaga record |
dist/sagas/<code>/instance.json |
The shell of its instance |
dist/instances/<code>/ |
Each instance backup |
The manifest names repository, contentVersion, sourceRevision, schemaVersion,
contentDigest, build, instances, sagas and files. The content digest is the sha256 of one
<path> <sha256> line per file, in path order. The same commit always builds the same bytes.
The engine reads the artifact of this checkout in development: run build after each commit.
pack writes the same artifact as artifacts/cyberia-content-<version>.tgz; the engine reads an
extracted copy the same way. A registry, an OCI image or a release asset can carry that tarball
later without a change to the artifact.
- Change content, run
validate, and commit. The build refuses uncommitted content. - Increment
versioninpackage.jsonand commit. A released version never changes. - Run
build. The engine reads the new artifact from this checkout. - In the engine,
cyberia release lockpins this revision and the artifact inunderpost.lock.jsonof the deployment: repository, revision, version and digest. - A deploy fetches that exact revision, builds it again with
npm ci,npm testandnpm pack, and fails unless the result matches the lock.
A source channel selects only the repository a deploy fetches the revision from: this repository,
or cyberia-content-private. A release from either channel is a production release. A deploy
never pushes to either repository.