From ac35f4883d0706c494b74987e19ddb48078804af Mon Sep 17 00:00:00 2001 From: Zoey Rose Date: Sat, 8 Aug 2026 23:46:06 +0000 Subject: [PATCH] docs(agents): compact server guidance --- AGENTS.md | 284 ++++++++++++++++-------------------------------------- 1 file changed, 82 insertions(+), 202 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a1e1b11..65d0d17 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,204 +1,84 @@ # Atrinik Go server repository guide -These instructions apply to the entire `atrinik/server` repository. - -## Purpose and ownership - -- This repository is the fresh MIT-licensed authoritative Atrinik game server - implemented in Go. It is an independent implementation, not a port of - the [`server/` module of `atrinik/classic`](https://github.com/atrinik/classic/tree/main/server). -- Own simulation, authorization, sessions, persistence, native gameplay - services, compiled-content consumption, bounded expression evaluation, and - production server operation here. -- Preserve the gameplay and content decisions in their owning issues. A - technical replacement does not authorize redesigning progression, combat, - quests, maps, dialogue, economy, or presentation behavior. -- Use [atrinik/atrinik#168](https://github.com/atrinik/atrinik/issues/168) as - the cross-repository roadmap and the issue's owning milestone as the phase - gate. Keep cross-repository dependencies explicit in issues and pull - requests. - -## Repository boundaries - -- `atrinik/protocol` owns Game Protocol 1 Protobuf schemas, Buf policy, - transport/framing specifications, conformance fixtures, and generated Go and - Rust contracts. Consume a released or pinned generated Go package; do not - duplicate schemas, hand-edit generated code, or make internal Go structs the - wire contract. -- `atrinik/content-toolkit` owns authored-content parsing, catalogs, validation, - transactions, and compilation. Load only versioned, bounded compiled content - artifacts. Do not add legacy source-format parsers or execute source scripts - in the server. -- Content, resources, and sound keep their exact per-file licenses. Compiled - inputs are data, not MIT server source, and their required notices must - survive packaging. -- `atrinik/client`, `atrinik/editor`, and `atrinik/renderer` own presentation - and authoring. Do not add UI, rendering, editor, or client prediction logic - here. -- `atrinik/atrinik` owns checkout composition, profiles, isolated runtime - state, process supervision, and canonical/classic coexistence. Do not - recreate wrapper paths, locks, topology state, or launch orchestration. -- `atrinik/metaserver-worker` owns registration and discovery service - operation; it never receives gameplay authority. -- Do not introduce Go-to-Rust FFI, Git submodules, or a second owner for a - contract. Add a new parser, scheduler, persistence model, expression host, - or schema owner only through an explicit architecture issue. - -## Go architecture and deterministic simulation - -- Follow the architecture and package-dependency decision in - [server#3](https://github.com/atrinik/server/issues/3). Until it is approved, - keep bootstrap choices minimal and reversible rather than establishing a - competing layout. -- Use a deterministic single-owner simulation. Mutable world state belongs to - the simulation owner; transport, storage, and observability workers exchange - bounded typed commands/results and never retain mutable world objects. -- Use bounded region or service queues with defined overload, cancellation, - shutdown, and backpressure behavior. Do not start a goroutine per entity, - map object, timer, effect, quest, or connection-owned gameplay object. -- Inject clocks and seeded random sources. Define stable ordering for commands, - events, timers, iteration, and persistence. Never depend on Go map iteration, - wall-clock timing, scheduler order, pointer identity, or process-local enum - order for gameplay results. -- Use stable generational identities and explicit ownership. A stale identity - must fail without targeting a replacement object. -- Model effects as validate/preflight, commit, and cancel or rollback. Invalid, - cancelled, duplicate, stale, timed-out, or persistence-failed work must not - expose partial gameplay state. -- Keep domain rules independent of QUIC, generated Protobuf types, SQLite row - layouts, CEL implementation details, logging, and filesystem paths. Translate - at narrow adapters and keep package dependencies acyclic. -- Keep every queue, collection, payload, recursion/fan-out path, timer horizon, - and per-tick workload bounded. Limits and overload behavior are part of the - design and tests, not deployment folklore. - -## Protocol, authorization, and content - -- Decode Game Protocol 1 into temporary validated inputs, enforce protocol and - domain bounds plus current authorization/state, and only then submit an - internal command. A malformed or incomplete message cannot mutate live - state. -- Produce viewer-authorized projections from committed state. Never disclose a - hidden field and ask the client to hide it, accept client-supplied authority, - or infer identity from display text or filesystem paths. -- Obey the protocol repository's QUIC framing, stream roles, rate, queue, - deadline, close, and compatibility rules. Slow or hostile peers must consume - bounded resources and receive structured failures without secrets. -- Load a compiled content package into an immutable catalog identified by its - schema/version/digest. Persist mutable world state separately, retain the - associated content digest, and reject unsupported or corrupt combinations - before simulation starts. -- Treat content reload/version transitions as explicit transactions. Runtime - code cannot mutate authored catalogs or silently reinterpret saved state. - -## Persistence and runtime behavior - -- SQLite WAL is the initial persistence owner. Use one coordinated writer, - explicit transactional schema migrations, typed repositories, checkpoints, - backups, restore validation, content-version association, and failure - injection. Do not persist generated Protobuf messages or implementation - pointers as the domain model. -- Keep mutable state outside the source checkout and let the wrapper own its - isolation and locking. Never share one state directory between concurrent - servers or canonical/classic topologies. -- Implement quests, dialogue/interfaces, achievements, commands, commerce, - property/community systems, triggers, metrics, and gameplay behavior as - native Go services plus compiled typed data. -- There is no runtime Python compatibility layer or CPython plugin ABI. Do not - add Python execution, `.py` dispatch, embedded interpreters, or Python as a - production runtime dependency. -- CEL is allowed only through versioned, typed, deterministic, pure, and - resource-bounded environments over immutable inputs. CEL may compute an - approved condition or value; it cannot perform effects, access mutable Go - objects, filesystem/network/environment/process state, ambient time, or - ambient randomness. -- Starlark is not a baseline dependency. Do not add it before the evidence-based - go/no-go in [server#60](https://github.com/atrinik/server/issues/60). If that - issue approves a host, expose only immutable snapshots and typed command - results with explicit execution, memory, recursion, output, time, and - capability limits. - -## Testing, security, and validation - -- Make deterministic unit and replay tests the normal path. Add property tests - for invariants and transactional boundaries, race tests for concurrency, - fuzz tests for every untrusted decoder/evaluator/importer, and failure - injection for storage, cancellation, queue pressure, and shutdown. -- Cross-language behavior uses protocol-owned golden and negative fixtures. - Independently authored gameplay scenarios must cover success, rejection, - retry, duplicate, stale generation/revision, reconnect, save/reload, and - rollback without deriving GPL tests. -- Treat protocol frames, compiled content, CEL/Starlark input, configuration, - state import, and operator commands as untrusted boundaries. Reject malformed, - oversized, deeply nested, out-of-order, or impossible data before effects. -- Keep credentials, tokens, account data, network identities, and private - player state out of logs, metrics labels, traces, fixtures, panic output, and - snapshots. Bound observability cardinality. -- Once [server#1](https://github.com/atrinik/server/issues/1) bootstraps the Go - module and component scripts, the documented aggregate server validation must - include formatting, static analysis/vetting, all Go tests, race tests, - selected fuzz smoke tests, generated-contract drift where applicable, - dependency/license review, and `git diff --check`. CI's eventual required - aggregate check is `Server validation`. -- Today this seed repository has no Go module, build script, or server binary. - For guidance-only changes, inspect the changed Markdown and run - `git diff --check`; do not claim `go test`, wrapper builds, or runtime - topologies succeeded. Add exact component commands to the README/CI in the - bootstrap issue before requiring them here. -- When wrapper integration exists, handoffs use the thin wrapper's exact - profile/build/scenario/topology commands and a distinct named state. Until - then, report that wrapper/runtime validation is unavailable rather than - reconstructing component internals. - -## Milestone priorities - -- **M1 — Clean-room foundations:** complete repository/provenance policy, - architecture and behavior/state decisions, the Go bootstrap, and structured - observability. Keep later gameplay work behind stable foundations. -- **M2 — Contracts, content, and headless world:** build the deterministic - kernel, QUIC/session adapter, compiled catalog, entities/maps, SQLite, - accounts, actions/events/metrics, native quest/dialogue, bounded CEL, - commands, and deterministic test harness against protocol/toolkit contracts. -- **M3 — First playable replacement:** implement the smallest integrated - account-to-world slice with movement, inventory, combat/AI, social behavior, - native services, lighting, one compiled content chain, save/reconnect, and - zero Python or Starlark. -- **M4 — Shared editor and scalable presentation:** this repository has no - independent rendering/editor implementation lane. Supply only explicit - authoritative contracts or performance fixes required by M4 owners. -- **M5 — Gameplay and world migration:** migrate preserved feature designs and - the complete behavior manifest in parallel domain batches, decide Starlark - only at its formal gate, and prove zero runtime Python. -- **M6 — Production hardening and cutover:** implement only the approved state - policy/importer, reproducible operations, security/load/soak/fault gates, and - rehearsed cutover/rollback. Do not archive or bypass the classic fallback - before the program exit gate. - -Milestones are dependency gates, not permission to ignore an issue's explicit -prerequisites. Prototypes may begin early, but a phase closes only when its -cross-repository exit criteria pass. - -## Licensing, provenance, and delivery - -- New server source, tests, generators, and repository infrastructure are MIT. - Do not copy, adapt, or mechanically translate GPL legacy source or tests. -- Historical reuse is allowed only under the exhaustive approved-grantor - registry and proof rules in the current `atrinik/atrinik` root `AGENTS.md`. - A complete, non-shallow history audit must follow renames and moves, prove - sole original authorship by an approved grantor, resolve historical - identities, and exclude embedded third-party or conflicting material. - Mixed, incomplete, or uncertain evidence fails closed. -- Record eligible reuse in the destination pull request or a committed - provenance manifest: exact source repository/path/revision and full history, - identity evidence, destination, transformation, third-party review, - applicable grantor, and the exact wrapper commit containing the registry - entry. A grant never blanket-relicenses a repository, file, content pack, or - generated output. -- Keep one owning issue and milestone for material work. Use Conventional - Commits for commits and pull-request titles, update affected specifications - and fixtures with contract changes, and name cross-repository producer and - consumer dependencies. -- Update the wrapper supply-chain inventory whenever dependencies, toolchains, - package sources, Actions, images, licenses, or validation paths change. Pin - reproducible inputs and do not commit secrets, local state, generated runtime - data, or confidential/unreleased project information. +## Ownership and boundaries + +- This repository owns the fresh MIT authoritative Go server: deterministic + simulation, authorization, sessions, persistence, native gameplay services, + compiled-content consumption, bounded expression evaluation, and production + operation. It is an independent implementation, not a classic port. +- Preserve product behavior owned by issues; a technical replacement does not + authorize redesigning progression, combat, quests, maps, dialogue, economy, + or presentation. +- `atrinik/protocol` owns Game Protocol 1 schemas, framing specifications, + generated Go/Rust contracts, and conformance fixtures. Consume released + generated packages; never duplicate schemas or hand-edit generated code. +- `atrinik/content-toolkit` owns authored parsing/catalogs/compilation. Load + only bounded versioned artifacts; do not parse classic source formats or + execute source scripts here. Content/media keep their individual licenses. +- Client/editor/renderer own presentation and authoring. The wrapper owns + checkout composition, runtime state, locks, supervision, and classic/ + replacement coexistence. Do not recreate those concerns or add Go-to-Rust + FFI, submodules, or a second contract owner. + +## Deterministic simulation and state + +- Keep mutable world state under one simulation owner. Workers exchange bounded + typed commands/results and never retain mutable world objects. Do not spawn a + goroutine per entity, object, timer, effect, or gameplay action. +- Inject clocks and seeded randomness. Define stable ordering for commands, + events, timers, iteration, and persistence; never depend on Go map order, + scheduler timing, pointers, or process-local enum positions. +- Use stable generational identities. Model effects as validate/preflight, + commit, and cancel/rollback so invalid, stale, duplicate, cancelled, or + persistence-failed work cannot expose partial state. +- Keep domain rules independent of QUIC, Protobuf, SQLite rows, expression + engines, logging, and filesystem paths. Bound queues, payloads, collections, + recursion/fan-out, timer horizons, and per-tick work with tested overload and + shutdown behavior. +- SQLite WAL is the initial persistence owner: one coordinated writer, + transactional migrations, typed repositories, checkpoints/backups, restore + validation, content-version association, and failure injection. Never persist + wire messages or implementation pointers as the domain model. +- Keep mutable state outside source and under wrapper isolation. A content + transition is explicit and transactional; never mutate authored catalogs or + reinterpret saved state silently. + +## Protocol, authorization, and security + +- Decode into temporary bounded inputs, validate protocol/domain rules and + current authorization, then submit an internal command. Produce only + viewer-authorized projections; never send hidden facts and ask a client to + hide them. +- Treat frames, compiled content, expressions, configuration, state import, and + operator commands as untrusted. Reject malformed, oversized, deeply nested, + out-of-order, or impossible data before effects. Bound observability + cardinality and keep credentials, account/private state, tokens, and network + identities out of logs, traces, fixtures, panics, and snapshots. +- There is no Python runtime or CPython plugin ABI. CEL may run only in a + versioned, typed, pure, deterministic, resource-bounded environment over + immutable inputs. Starlark is not a baseline dependency and requires the + explicit decision in server issue #60. + +## Licensing, roadmap, and validation + +- New server work is MIT. Do not copy/adapt GPL implementation or tests. + Historical reuse follows local `PROVENANCE.md` and the canonical + `atrinik/atrinik/docs/PROVENANCE.md` registry; incomplete, mixed, or uncertain + evidence fails closed. +- `atrinik/atrinik#168` is the cross-repository roadmap; local issue acceptance + criteria and milestones own delivery. Do not duplicate the M1-M6 plan here. +- Run the real aggregate contract now present in this repository: + + ```sh + tools/validate.sh + git diff --check + ``` + + `Server validation` owns formatting/static analysis, tests/race coverage, + selected fuzz smoke tests, dependency/license checks, and other documented + gates. Add deterministic, property, replay, boundary, failure-injection, and + fuzz coverage appropriate to the changed trust boundary. +- Wrapper replacement build/runtime adapters are not available yet. Use + repository validation for this Go server and do not route it through classic + C code. Commits and pull-request titles use Conventional Commits; + semantic-release owns releases and tags.