## Use ASD-STE100 Simplified Technical English
Write comments in simplified technical English.

Key rules:
- Use the approved words of ASD-STE100 when possible.
- Use one word for one idea. Do not use two words for the same thing.
- Write short sentences. Use 20 words or less for instructions.
- Use active voice. Write "Turn the switch", not "The switch must be turned"
- Write short paragraphs. Keep one topic in each paragraph.
- No filler.

The goal is easy reading.

Report back to the user following the same rules.

## Brief comments — no archaeology

Comments state the live invariant in ≤1 line. The reader needs current behavior, nothing more.

- Banned content: bug postmortems, "we tried X but Y broke", "previously", "used to", "added because of", historical justification, restoration sagas.
- Test: "If I delete this comment, will a reader misunderstand the code?" No → delete. Yes → minimum text, present tense.
- Decision rationale and bug-fix narration go in the commit message that introduced the change — there it's dated and attributable; on the line it's stale weight forever.
- Use `TODO:` only for concrete, actionable follow-ups.

## Consistency guardrails

- Keep one source of truth for config, deploy IDs, runtime selection, startup order, and generated assets.
- Reuse existing helpers, conventions, and resolution logic instead of introducing parallel implementations.
- Do not duplicate parsing, environment resolution, or path normalization.
- Keep generated artifacts read-only outputs; never hand-edit them.
- No dead code, no legacy code, and no legacy concepts.
- Keep responsibilities explicit and avoid introducing abstractions without a concrete ownership boundary.

## Host, LXD, and orchestration safety

- Treat every host-level change as idempotent, reversible, and explicit.
- Validate target paths, permissions, ownership, mounts, users, groups, namespaces, and volumes before mutating.
- Never assume host resources already exist.
- Prefer dry-run, guarded cleanup, and rollback paths over destructive operations.
- Protect host-mounted volumes and VM bootstrap flows from partial configuration.
- Make orchestration safe to interrupt and safe to rerun.

## Testing and verification

- When changing orchestration, bootstrap, config loading, or runtime startup order, add or update focused tests for parsing, validation, and selection logic.
- For live-service tests, document the required runtime environment and keep execution deterministic.
- Prefer small, targeted verification over broad manual validation.
- Verify changed behavior at the closest layer that owns it.

Tests live at `test/<domain>/<level>/`: the domain owns the behavior, the level says which boundary is exercised.

- Domains: `underpost`, `object-layer`, `item-ledger`, `cyberia`, `cryptokoyn`, `ecosystem`. A test of a relationship between two domains belongs to `ecosystem`, never to one side of it.
- Levels: `unit` (everything in memory), `integration` (one real boundary), `contract` (an interface between owners), `e2e` (a whole workflow), `audit` (platform invariants). MongoDB and the blockchain are boundaries, never directories of their own.
- Execution order and coverage scope live in `src/server/build/testing.js`. Never encode order in a directory name.
- Run what a change breaks: `node bin test --changed`. Run one selection: `node bin test <domain>[:<level>]`. `node bin test --list` prints what a selector resolves to.

## Cyberia

Cyberia is one product on this platform. Everything in this section applies to
Cyberia only, not to the rest of the repo.

### Architecture boundaries

Three processes:

| process | role | talks to |
|---|---|---|
| **cyberia-client** | game client, game canvas | game server (WebSocket), engine (REST) |
| **cyberia-server** | authoritative simulation | client (WebSocket), engine (gRPC + REST) |
| **engine-cyberia** | external content authority (assets, config data, asset data) | serves both; triggers server hot-reload (gRPC control, REST fallback) |

- Keep authoritative simulation out of the cyberia-client.
- Keep content-authority and persistence concerns out of cyberia-server.
- Preserve these boundaries when introducing new flows, APIs, or shared helpers.

### This repo owns the Cyberia manifests

`manifests/` in cyberia-client and cyberia-server is generated here. Their
AGENTS.md says an external system writes it. That system is this repo.

- `src/cli/run.js` → the `instance-build-manifest` runner reads the deploy's
  `conf.instances.json` and writes `<project>/manifests/deployments/<id>-<env>/`.
- Change the generator or its input. Never the generated file.
- A manifest bug is a generator bug. Fix it here, then rerun the runner.

### Content comes from cyberia-content

`cyberia-content` creates the content: foundation, instances, sagas, the
procedural templates, the semantic generator and validation. It builds the content
artifact, which is data. This repo consumes that artifact. `cyberia-deployment`
records the deployed artifact in `content-lock.json`.

- `./cyberia-content` and `./cyberia-deployment` are checkouts in the engine
  workspace. `CYBERIA_CONTENT_ROOT` and `CYBERIA_DEPLOYMENT_ROOT` override them.
- `src/projects/cyberia/content/content-artifact.js` resolves both roots and is the only
  reader of the artifact. Resolve them only where an operation needs content.
- Content defines what exists and how it functions. Studio adds render and
  placement only. An import never overwrites them.
- Genesis Templates, Palette Templates and the item baseline of a new item are
  content. The Procedural Engine reads them from the artifact; never hard-code them.
- `cyberia-content` is not a package dependency of the product. Never add it to
  `catalog-cyberia.js`.
- `src/projects/cyberia` has one directory per capability: `catalog`, `content`, `instance`,
  `object-layer`, `procedural`, `runtime`, `saga`, `stack`, `stats`. Its root holds only the
  modules the platform loads by name: `catalog-cyberia.js`, `compose-stack.js`,
  `instance-data.js` and the `<api>.extension.js` modules.
- Add no content, prompts or semantic generator code here.
- `cyberia-content/src/schema/runtime-contract.json` is generated by
  `node bin/cyberia stat-contract`. Change `SharedDefaultsCyberia.js`, then rerun it.

### Documentation

- `src/client/public/docs/cyberia/` — Cyberia architecture, server, client, CLI, action, quest, economy and roadmap.
- `src/client/public/docs/object-layer/` — Object Layer protocol, identity model, lifecycle and runtime semantics. Cyberia consumes them; it defines none.
- `src/client/public/docs/item-ledger/` — on-chain registration, ownership and the `ObjectLayerToken` contract.

## Documentation

All authored documentation lives in one tree, `src/client/public/docs/`. The path is the identity:
`<domain>/<category>/<slug>.md`.

- Domains: `ecosystem`, `object-layer`, `item-ledger`, `cyberia`, `cryptokoyn`, `nexodev`, `underpost`.
- Categories: `overview`, `explanation`, `how-to`, `reference`. `underpost` uses `engineering-journal`, `lab-notes`, `adr`. `ecosystem` uses `architecture`.
- One topic per file. One `#` title per file. Lowercase, hyphenated filenames.
- A domain declares itself once, in the front matter of its overview (`domain`, `identity`, `maturity`, `order`).
- Link to another document by its relative path (`../reference/cyberia-cli.md#anchor`). Link to source by code span, never by link.
- Navigation is generated from the tree. Do not add "related documents" lists.
- Every domain has exactly one `/docs` view: `DOCS_VIEWS` of `src/server/build/docs.js` names the application that navigates it.
- `npx vitest run --project ecosystem:contract test/ecosystem/contract/documentation-architecture.test.js` is the quality gate: broken links, unknown categories, duplicate identities and titles fail it.
- `nexodev/reference/underpost-cli.md` is generated by `node bin/deploy cli-docs`. Never hand-edit it.
- `engine-private/` is private. Do not assume it exists locally; treat references to it as external/private context.

## One theme per commit
One commit = one logical theme. No bundling unrelated changes.

- Before `git commit`: scan staged diff. ≥2 themes → unstage, commit each theme separately.
- Each commit stages the minimum file set needed for that theme. No drive-by edits, no "while I'm here" cleanups.
- Themes that touch a shared file (`src/api.js`, `src/db/mongo/MongooseDB.js`, `src/projects/cyberia/instance-data.js`): land the feature commits first, then one final "wire X through the runtime" glue commit. Don't merge themes just to avoid the glue commit.
- Commit subject names ONE concern. If you need "and" or "+" to describe it, it's two commits.

