# AGENTS.md This is a StartOS service-package repository — it builds a `.s9pk` for StartOS. Develop it inside a StartOS packaging workspace created by `start-cli s9pk init-workspace`, which provides the packaging guide and agent context one level up. If you're reading this in a bare clone with no workspace, the full guide is at . **Start every task at the recipe index** — `../start-technologies/projects/start-sdk/docs/src/recipes.md` (or ). It maps an intent ("prompt the user to create admin credentials", "expose a web UI") to the constructs, the reference pages, and a named production package to copy. Find the recipe before you read this package's neighbours: a package you reach by grepping may be non-conformant, and the recipe outranks it. Freshly scaffolded? Work the [New Package Checklist](../start-technologies/projects/start-sdk/docs/src/new-package-checklist.md) (or ) from top to bottom. It is a guide page, not a file in this repo — read it, don't copy it in. Keep `README.md` (technical reference for an AI support or administering agent) and `instructions.md` (end-user docs) in sync with your changes. **Bugs and feature requests are issues on this repo** (self-hosted Gitea, not GitHub) — file them as you find them. Don't record work in the repo instead: no `TODO.md`, no `NOTES.md`, no `PLAN.md`. What you verified, tried, and decided belongs in the commit message and the PR body. ## This repo - **Station Master is a git submodule (`station-master/`), not vendored source.** It tracks [Jesse's own game repo](https://draco.local:53871/Jesse.Markowitz/station-master), self-hosted, pinned to a tag. See `UPDATING.md` for how the pin is bumped — the `Dockerfile`, `main.ts`, and the manifest should never need to change for an ordinary version bump. - **Built from source, not a published image.** The `Dockerfile` is entirely this repo's own: a `node:*-slim` builder stage runs the submodule's `npm run build:web` to produce the static client, then a runtime stage copies only `package.json`, `src/`, and the built `dist/` — no `node_modules`, since `src/server/index.ts` has zero runtime dependencies (see the submodule's own `TODO.md` for why) and Node's native TypeScript type-stripping means it needs no compile step either. - **The join secret (D14 in the game's `docs/architecture/multiplayer.md`) is this package's one piece of state beyond the game data itself.** `startos/fileModels/store.json.ts` holds it, seeded on install (`startos/init/generateJoinSecret.ts`) since the server refuses to start without one, and rotated by the **Get Join Secret** action (`startos/actions/getJoinSecret.ts`) — the same action handles first retrieval and rotation, per `recipe-admin-credentials.md`. - **One volume, one interface, no dependencies.** Everything the server persists — `store.json` and every game's own save data — lives on the `data` volume; the single `ui` interface carries the browser client, the lobby/intent HTTP API, and the SSE game stream from one port, which is what keeps players reachable from different addresses in the same game (`docs/architecture/deployment.md` §3 in the game repo).