Skip to content

Latest commit

 

History

History
167 lines (127 loc) · 9.96 KB

AGENTS.md

File metadata and controls

167 lines (127 loc) · 9.96 KB

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. Each one has one job.

engine-cyberia — content. It holds what exists and how it works: object layers, atlases, maps, instances, quests, actions, dialogue and stat rules. It holds no simulation state. When content changes, it tells the server to hot-reload (gRPC control, REST fallback).

cyberia-server — authority. It owns the state of the world and of every entity, and it has the final word. It loads content from the engine at boot and on hot-reload. One fixed tick runs the phases in order: input, lifecycle, skills, AI, movement, loot, portals, then replication.

cyberia-client — view and prediction. It holds a full copy of the state and writes only the entity it owns: the own player. It draws, plays audio and runs the UI. The UI is local: it reads local state and never waits for the socket.

Communication

Content — engine to both. The client reads content over HTTPS REST (cyberia-client/src/data/engine_client.c). The server reads it over gRPC, with REST as fallback (cyberia-server/engine_client/). The game server never serves content, and the engine never sees simulation state.

Game link — client and server only. One WebSocket, /ws, JSON envelope. The client pushes events: what the player did, never what it has. Each event carries frame, sequence and time. The server applies them in sequence order, replays item ops against its own items, and sends whole states. Each snapshot carries inputConsumedThrough, the highest sequence it consumed. The client applies its own events at once. At each tick it takes the newest snapshot, drops consumed events and replays the rest. There is no other correction.

The engine is not on the game link. A change to content reaches players only through a server hot-reload and the client's next REST read.

  • 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, economy, instance, object-layer, player, 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.