docs(site): edit rules for clarity + cross-links; migrate off rules.txt
Build · Site / build (push) Successful in 8s
Tests · Go / test (push) Successful in 2m27s
Tests · UI / test (push) Waiting to run
Tests · Integration / integration (pull_request) Successful in 1m45s
Build · Site / build (pull_request) Successful in 9s
Tests · Go / test (pull_request) Successful in 3m14s
Tests · UI / test (pull_request) Successful in 3m14s

Editorial pass over site/ru/rules.md (on top of the verbatim port):
- moved the lore intro to the RU home page, rewritten in a modern voice;
- fixed typos, replaced the TODO/WTF cargo-tech note and the abandoned
  (---ссылка---) marker with the verified mechanic and a real cross-link,
  dropped the report TODO row;
- wove organic intra-page cross-links (#combat, #movement, #victory, ...);
- documented engine nuances verified against the code: ore auto-farming
  and the capital / "запасы промышленности" store (industry capped at
  population); cargo lost with ships destroyed in battle; and that a
  losing race's colonists at a neutral planet are NOT lost — they stay
  aboard (this corrects the audit note, verified in route.go).

Migration: delete game/rules.txt (its content now lives, authoritative,
in site/ru/rules.md) and repoint every reference to it (ui/frontend code
comments + tests, ui/docs, tools, ui/PLAN.md links). Record the
RU-authoritative rule in site/README.md and CLAUDE.md. The English
site/rules.md mirror follows in a separate stage.
This commit is contained in:
Ilia Denisov
2026-05-31 15:56:00 +02:00
parent d3770e7f77
commit 140ee8e0ee
18 changed files with 56 additions and 1511 deletions
+5 -5
View File
@@ -1982,7 +1982,7 @@ Artifacts (Pass B — feature):
preserves camera centre + zoom across route-driven remounts
inside the same game id.
- Topic doc `ui/docs/cargo-routes-ux.md` quotes
[`rules.txt`](../game/rules.txt) (lines 808843) and maps
[`site/ru/rules.md`](../site/ru/rules.md) (lines 808843) and maps
semantics to UI; `ui/docs/renderer.md` documents the pick-mode
contract; `ui/docs/calc-bridge.md` records the Phase 16 reach
waiver (inline TS rather than a calc bridge for one
@@ -2075,7 +2075,7 @@ Artifacts:
rewritten from the Phase 10 stub: empty form for the Create flow
(name plus the five fields Drive, Armament, Weapons, Shields,
Cargo) and read-only view + Delete affordance for an existing
class. Validation rules from [`rules.txt`](../game/rules.txt) live
class. Validation rules from [`site/ru/rules.md`](../site/ru/rules.md) live
in `lib/util/ship-class-validation.ts` (TS port of
`pkg/calc/validator.go.ValidateShipTypeValues`): each of drive /
weapons / shields / cargo is 0 or ≥ 1; armament is a non-negative
@@ -2098,7 +2098,7 @@ Dependencies: Phase 14.
Acceptance criteria:
- the user can create, list, view, and delete ship classes;
- field validation matches [`rules.txt`](../game/rules.txt)
- field validation matches [`site/ru/rules.md`](../site/ru/rules.md)
constraints with disabled Submit + tooltip when invalid;
- double-tapping a row in the ship-classes table opens its
designer (read-only view of the existing class);
@@ -2463,7 +2463,7 @@ Acceptance criteria:
- the planet production picker (Phase 15) lists the user's sciences
in the Research sub-row and lets the user select one for research
production;
- name validation matches [`rules.txt`](../game/rules.txt)
- name validation matches [`site/ru/rules.md`](../site/ru/rules.md)
constraints (length, allowed characters, special characters not
at start/end, no triple repeats).
@@ -2563,7 +2563,7 @@ Targeted tests:
Status: done (local-ci run 2).
Goal: present every section of the current turn's report as readable
panels, mirroring the structure documented in [`rules.txt`](../game/rules.txt) and
panels, mirroring the structure documented in [`site/ru/rules.md`](../site/ru/rules.md) and
`docs/FUNCTIONAL.md` §6.4.
Artifacts:
+1 -1
View File
@@ -136,7 +136,7 @@ new one); Create is disabled while the name is invalid or duplicate
(reusing `lib/util/ship-class-validation.ts`). Create reuses the existing
`createShipClass` order-draft flow, so the optimistic overlay reflects
the change immediately. Ship classes are immutable after creation (per
`game/rules.txt`), so there is no edit — only Create-new. Delete-class
`site/ru/rules.md`), so there is no edit — only Create-new. Delete-class
lives in the ship-classes table (`lib/active-view/table-ship-classes.svelte`),
not the calculator.
+1 -2
View File
@@ -5,8 +5,7 @@ subsection (a single-row dropdown + contextual actions after
F8-05), the map-driven destination pick, and the optimistic
overlay that keeps the inspector and the map in lock-step with
the local order draft. The engine semantics are quoted from
[`game/rules.txt`](../../game/rules.txt) section "Грузовые маршруты"
(lines 808843); this file is the source of truth for how the UI
[`site/ru/rules.md`](../../site/ru/rules.md#routes) section "Грузовые маршруты"; this file is the source of truth for how the UI
surfaces those rules.
## Engine semantics in one paragraph
+2 -2
View File
@@ -29,8 +29,8 @@ sequence.
The designer presents the four proportions as percentages
(`step="0.1"`, range `[0, 100]`) so the player can type and reason
about whole-number splits — closer to how `game/rules.txt` describes
sciences (`game/rules.txt:345-362`: "10 parts Drive, 5 parts
about whole-number splits — closer to how `site/ru/rules.md` describes
sciences (`site/ru/rules.md` #sciences: "10 parts Drive, 5 parts
Weapons, 30 parts Shields, 0 parts Cargo, …"). The wire shape is
still fractions; conversion happens inside `validateScience` only on
Save (`value / 100` for each of the four).
+2 -2
View File
@@ -268,7 +268,7 @@ export interface ReportLocalFleet {
* table uses.
*
* `relation` reflects the local player's stance TOWARD this race,
* not the other way around (`rules.txt` line 1162). Per the engine
* not the other way around (`site/ru/rules.md` #report). Per the engine
* (`controller/race.go.UpdateRelation`) the relation is stored
* unilaterally — race A can be at war with race B while race B is
* at peace with race A.
@@ -508,7 +508,7 @@ export interface GameReport {
/**
* myVotes is the local player's total vote weight in the current
* report, read from `Report.votes` (the engine assigns one vote
* per 1000 population, see `rules.txt:1060`). Zero when the
* per 1000 population, see `site/ru/rules.md` #victory). Zero when the
* report has not been produced yet.
*/
myVotes: number;
@@ -8,7 +8,7 @@ immediately and the auto-sync pipeline drives the server in the
background.
The alliance graph and the 2/3 victory check are NOT computed
here: `rules.txt` keeps each race's outgoing vote target private
here: `site/ru/rules.md` keeps each race's outgoing vote target private
(only the votes a race RECEIVED in the last tally and the local
player's own pick are observable), and the acceptance criterion
"vote counts match server state byte-for-byte" rules out
@@ -10,7 +10,7 @@
// `OrderCommand` payload always carries the canonical `[0, 1]`
// summing to `1.0` shape the FBS encoder ships on the wire.
//
// Engine rules (from `pkg/calc/validator.go` and `game/rules.txt`):
// Engine rules (from `pkg/calc/validator.go` and `site/ru/rules.md`):
//
// - drive, weapons, shields, cargo: float in `[0, 1]`;
// - the four values sum to `1.0` (the engine accepts a small
@@ -6,7 +6,7 @@
// to gate auto-sync, so the local invariants match the engine's
// (`game/internal/controller/ship_class.go.ShipClassCreate`).
//
// Engine rules (from `pkg/calc/validator.go` and `game/rules.txt`):
// Engine rules (from `pkg/calc/validator.go` and `site/ru/rules.md`):
//
// - drive, weapons, shields, cargo: float, equal to 0 or >= 1;
// - armament: integer, >= 0;
+1 -1
View File
@@ -330,7 +330,7 @@ export class OrderDraftStore {
* tracks a single war/peace stance per opponent, so a newer
* entry supersedes any prior `setDiplomaticStance` for the
* same other race.
* - `setVoteRecipient` collapses singleton: per `rules.txt`
* - `setVoteRecipient` collapses singleton: per `site/ru/rules.md`
* each race controls a single vote slot, so a newer entry
* supersedes any prior `setVoteRecipient` regardless of the
* acceptor.
+1 -1
View File
@@ -463,7 +463,7 @@ export interface SetDiplomaticStanceCommand {
* to a race. Mirrors the engine `CommandRaceVote`
* (`pkg/schema/fbs/order.fbs`,
* `game/internal/controller/command.go.RaceVote`). The engine
* tallies votes at turn cutoff (`rules.txt` "Процесс голосования");
* tallies votes at turn cutoff (`site/ru/rules.md` "Процесс голосования");
* between turns the player can change their pick freely. The
* acceptor may be the local race itself — the engine treats
* self-vote as the neutral default and re-applies it whenever a
+1 -1
View File
@@ -112,7 +112,7 @@ describe("validateScience", () => {
expect(result.reason).toBe("sum_not_hundred");
});
test("accepts the canonical First Step fixture from rules.txt", () => {
test("accepts the canonical First Step fixture from site/ru/rules.md", () => {
// 10 Drive + 5 Weapons + 30 Shields + 0 Cargo, normalised:
// 10/45 ≈ 22.222… %, 5/45 ≈ 11.111… %, 30/45 ≈ 66.666… %,
// 0/45 = 0 %. Snapped to one decimal at input time:
@@ -138,7 +138,7 @@ describe("validateShipClass", () => {
expect(result.reason).toBe("all_zero");
});
test("accepts the canonical Cruiser fixture from rules.txt", () => {
test("accepts the canonical Cruiser fixture from site/ru/rules.md", () => {
const result = validateShipClass(
draft({
name: "Cruiser",