--- name: atrinik-server-runtime description: Run or diagnose isolated classic servers and supervised topologies through `./atrinik`. --- # Atrinik server runtime The wrapper owns builds, collection, state locks, supervision, logs, and cleanup. Never reconstruct its paths or invoke generated binaries. Classic preparation owns disposable `assets` staging. Immutable exact-profile `client-maps/*` and resources use authenticated QUIC by default; server-generated `data/*` transport files live only in the generation-named runtime-output directory below the exclusively leased state. Do not place copied asset inputs in state. `http_url` only names an optional external HTTP(S) origin; never restore a bundled HTTP listener. 1. Read the workspace and selected server/content/resource guides. 2. Inspect a coherent classic-derived profile and topology. 3. Give isolated automation generation-owned temporary state. Use a distinct named state or explicit default state only when persistence is required. Never replace source, share live state, or edit managed runtime files. ```sh ./atrinik build server --profile PROFILE --test ./atrinik topology show PROFILE --temporary-state --json ./atrinik up --name NAME --profile PROFILE --temporary-state ./atrinik ps NAME --json ./atrinik logs NAME server --follow ./atrinik down NAME ``` `--state NAME` selects a registered persistent state; `--default-state` explicitly selects the legacy managed default. The three selectors are mutually exclusive. A confirmed clean `down` removes temporary state only after expected service exit and exact process/state lease release; persisted clean proof makes interrupted finalization retryable. Use `down NAME --retain-state` and `state promote NAME SAVED_NAME` to preserve it without overwrite. Crash, unreachable, malformed, linked, busy, or uncertain state remains for diagnosis; inventory it with `cleanup --scope temporary-states --dry-run --json` and never apply cleanup without the matching preview. Do not reuse a topology name while its temporary state is retained or has an unfinished lifecycle; promote or explicitly reclaim that state first. `ps --json` reports generation-bound `live`, `exited`, `stale`, or `unreachable` liveness and exact runtime-generation, process-tree, state-policy owner/path/lifecycle, and port observations. A ready topology retains no repository-layout or mutable build-root lease. Cross-session `down` uses the matching filesystem control endpoint, never a PID from the caller's namespace. For `unreachable`, follow the reported safe action: wait for bounded guardian recovery and retry `ps` and `down`; preserve an exact retained lease for operator diagnosis. Never inspect `/proc`, signal the recorded PIDs, unlink control or lease files, or reuse the name as recovery. `logs` prefixes service output with the same state-policy context. Preserve that header with bounded diagnostic excerpts and handoffs. After `down`, retain the record for diagnosis or reclaim it only through the separate preview-first lifecycle: ```sh ./atrinik cleanup --scope topologies --older-than 7 --dry-run --json ./atrinik cleanup --scope topologies --older-than 7 --apply ``` This scope is excluded from defaults and `all`. It accepts only old `exited` or legacy `stale` marker-owned records with unreachable controls and released leases; it never acts as `down` or touches persistent state, scenarios, builds, profiles, or source. For a scope-owned topology, clean `down` is followed by the scope's fresh release preview and hash-bound apply. The exact stopped topology record remains under the separate cleanup lifecycle. Only current matching regular spec/status records with a control-requested clean shutdown and released runtime/state/port coordinates stop pinning the owning scope. Stale, historical, mismatched, live/unreachable, retained, or unrelated evidence blocks release. The wrapper uses a short generation-derived endpoint in the shared workspace and binds both process-tree and immutable runtime-bundle leases to the exact generation and file identities. Missing, replaced, linked, or malformed current generations, manifests, or lease files require diagnosis before use. Repair task-blocking local metadata under [local recovery](https://github.com/atrinik/atrinik/blob/476cf9dad436ce7b5fb89113c46014fcca3b8f77/docs/LOCAL_RECOVERY.md), preserving evidence and current ownership; do not rewrite a live generation. Never edit a published generation; rebuild the profile while it is live only to verify that its recorded manifest digest and runtime bytes remain unchanged. Let `up` allocate a port unless a distinct fixed port is required. Diagnose build, state, plugin, network, and gameplay failures separately. Use `atrinik-test-scenario` for accounts; never handcraft saves. Record actions and logs, stop the topology, release only its exact scope with a fresh preview when applicable, reset only scenario state, and run owner validation. Prove parallel startup with readiness/ownership transitions, never an elapsed-time threshold. An external exported client receives only the explicit host, UDP port and certificate fingerprint, never the private QUIC key or control endpoint. A server container requires its explicit UDP mapping at creation. Stop the client, then wrapper topology, then only the exact owned container. Follow docs/LINUX_EXECUTION.md for separate headless-server, native-client and persistent-state verification. For Docker-forwarded UDP, use `--server-listener all-ipv4` in both `topology show` and `up`/`dev up`; `dev restart` retains it. Keep host publication localhost-only and give clients the explicit reachable host, never wildcard `0.0.0.0`. Omission preserves loopback; listener options require a server service.