60 lines
5.5 KiB
Markdown
60 lines
5.5 KiB
Markdown
# Decisions
|
||
|
||
Implementation decisions not spelled out in `memory-bank/implementation-plan.md`. Design decisions from plan §0.5 are logged here as they are implemented.
|
||
|
||
## Step 1.1
|
||
|
||
- **Repo lives on an NTFS drive (`C:\Projects\...`).** The original location (G:) is exFAT, which cannot hold symlinks, so pnpm could not link workspace packages. Do not move the repo back to an exFAT drive.
|
||
- **TypeScript is pinned to `~6.0`.** TypeScript 7 is the latest release, but `typescript-eslint` (needed in Step 1.2) only supports `<6.1`. Upgrade once typescript-eslint supports 7.
|
||
- **Packages export TypeScript source directly** (`main`/`types` point at `src/index.ts`). There is no build step for internal packages; Vite, Vitest and the server's TS runner consume the source. The base config uses `moduleResolution: "Bundler"` and `noEmit`.
|
||
- **Node 24** is the required runtime (`engines` + `.nvmrc`).
|
||
- **Line endings are LF** everywhere (`.gitattributes`), overriding the machine's global `core.autocrlf`, to match Prettier and the Linux CI runner.
|
||
|
||
## Step 1.2
|
||
|
||
- **ESLint 10 flat config** with `typescript-eslint` recommended (not type-aware, to keep lint fast) and `eslint-config-prettier`. `pnpm lint` runs ESLint then `prettier --check`.
|
||
- **Purity rule** for `packages/sim` and `packages/content`: `no-restricted-properties` bans `Math.random` and `Date.now`; `no-restricted-syntax` bans `new Date()` with no arguments (`new Date(x)` is allowed).
|
||
- **Prettier skips `memory-bank/`** so tooling never rewrites the design docs.
|
||
|
||
## Step 1.3
|
||
|
||
- **Vitest projects**: the root `vitest.config.ts` treats each `apps/*` and `packages/*` folder as a project, so `pnpm test` runs every package's tests. Packages can add their own `vitest.config.ts` when they need a different environment.
|
||
- **Tests live in each package's `test/` folder** and are included in that package's tsconfig, so `pnpm typecheck` covers them.
|
||
|
||
## Step 1.4
|
||
|
||
- **CI runs on Gitea Actions** (`.gitea/workflows/ci.yml`): install with a frozen lockfile, then typecheck, lint and test.
|
||
- **`.pnpm-store/` is ignored** by Prettier, ESLint and git. On the Gitea runner, pnpm puts its store inside the workspace, and `prettier --check` failed on the store's files (CI run #1).
|
||
|
||
## Step 1.5
|
||
|
||
- **One Postgres container, two databases.** `docker-compose.yml` runs a single `postgres:18` server on port 5432 (user/password `deadhead`). The default database `deadhead` is for development; `docker/postgres/init/01-create-test-db.sql` creates `deadhead_test` the first time the data volume is created. To recreate both from scratch, run `docker compose down -v`.
|
||
- **Env var names** in `.env.example`: `DATABASE_URL`, `TEST_DATABASE_URL`, `BETTER_AUTH_SECRET` and `BETTER_AUTH_URL` (Better Auth's own names), `PORT`, and `GAME_EPOCH_REAL_START` plus `GAME_EPOCH_EPHEMERIS_DATE` (decision 0.5.9). The game-clock speed is not an env var; it belongs in GameConfig (rule 0.1.5).
|
||
- **Epoch values in `.env.example` are placeholders.** The design docs do not fix an ephemeris date yet.
|
||
|
||
## Step 2.1
|
||
|
||
- **Ids are lowercase kebab-case strings** (`earth`, `bulk-hauler`, `long-haul`).
|
||
- **One landing-class enum** (`vacuum`, `atmospheric`, `hardened`) serves both a location's landing requirement and a ship's landing class. `hardened` is not used in the base game.
|
||
- **Location `body`** is an enum of the five astronomy bodies (`earth`, `moon`, `mars`, `ceres`, `jupiter`) so the sim can map each to a position source in Step 3.3.
|
||
- **Epoch fields are ISO 8601 UTC strings** (`epoch.realStart`, `epoch.ephemerisDate`), not `Date` objects, so content stays plain data.
|
||
- **`tutorialBoardSize`** is a GameConfig field in addition to `contractBoardSize`, because decision 0.5.21 sets the tutorial board's size separately.
|
||
- **XP per delivery inputs** are `base`, `perMillionKm` and `perCargoTier`. Step 3.16 decides how they combine.
|
||
- **`pilotLevelXpThresholds`** lists the _total_ XP needed for level 1, 2, 3, ...; it and the Long Haul cut-offs must be strictly increasing.
|
||
- **`tierPayMultiplier`** is one number per cargo type. Step 3.8 decides how it scales with tier.
|
||
- **Imports omit the `.ts` extension** (`moduleResolution: "Bundler"`).
|
||
|
||
## Step 2.2
|
||
|
||
- **Location ids:** `earth`, `moon`, `mars`, `ceres-station`, `jupiter-cloud-platform`.
|
||
- **Cargo flows** follow GDD §9: Earth and Mars produce standard and high-value goods and demand ore (heavy) and fuel (dangerous); the Moon produces standard and heavy; Ceres produces heavy; Jupiter produces dangerous (fuel). The outposts import high-value equipment.
|
||
- **Launch multipliers:** Earth 3, Jupiter Cloud Platform 2, Mars 1.5, Moon 0.5, Ceres 0.3.
|
||
- **Bay lease prices are first guesses** (Earth 5,000 up to Jupiter 15,000). Step 2.5 tunes the Earth price against the tutorial.
|
||
- **The cargo-id check uses a placeholder list** of the four cargo ids planned in Step 2.4 until the cargo data exists.
|
||
|
||
## Step 2.3
|
||
|
||
- **Ranges** (million km): Courier 5 (Moon only; Mars is ~55 at its closest), Freighter 650 (covers Ceres at its farthest, ~600, and Jupiter near its closest, ~590, per decision 0.5.25), Bulk Hauler 1,000 (Jupiter at its farthest, ~970). Step 3.7 checks these against real positions.
|
||
- **Speeds and overheads** aim at GDD §6 durations at compression 60: Courier 3M km/h with 2 h overhead (Earth→Moon ≈ 2 real minutes, mostly overhead), Freighter 2M km/h with 4 h (Earth→Mars ≈ 1–2 real hours), Bulk Hauler 1.2M km/h with 8 h.
|
||
- **Prices** (30,000 / 150,000 / 600,000), **capacities** (20 / 100 / 400 t), **fuel costs** (20 / 40 / 80 per million km) and **hull ratings** (1 / 2 / 3) are first guesses; Step 2.5 tunes the Courier price.
|