ui-test workflow gains a `!**/*.md` negation so commits touching only markdown (READMEs, PLAN.md updates, topic docs) no longer kick off the full Go + Vitest + Playwright pipeline. Mixed commits keep triggering because at least one positive path (`ui/**`, `gateway/**`, …) still matches. Project CLAUDE.md adds a per-stage CI gate section so the local Gitea Actions runner is exercised at the close of every stage from any PLAN.md, with the push step pre-authorised. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
8.3 KiB
Galaxy Game — Project Conventions
This repository hosts the Galaxy Game project.
Sources of truth
docs/ARCHITECTURE.md— global architecture, security model, cross-service contracts, and project-wide rules.docs/FUNCTIONAL.md— per-domain user stories that describe what each user-visible operation does, with the exact gateway and backend logic for it. Starting point for any change request that touches behaviour.docs/FUNCTIONAL_ru.md— Russian translation ofdocs/FUNCTIONAL.md, maintained as a convenience for the project owner. Not a source of truth — when the two files disagree, the English version wins. Every point edit applied todocs/FUNCTIONAL.mdmust also be mirrored intodocs/FUNCTIONAL_ru.mdin the same patch (translate the changed paragraphs only, do not re-translate the whole file). A full re-translation only happens on explicit owner request.docs/TESTING.md— testing layers (unit / integration), the integration runbook, and the principles every test must follow (no-op observability for testcontainers,t.Fatalon infrastructure breakages, label-driven preclean). Read before adding tests or modifying the integration harness.galaxy/<service>/README.md— service conventions, layout, configuration, and operations for an implemented or planned service.galaxy/<service>/openapi.yamland*.protofiles — exact wire contracts for REST and gRPC surfaces.
Planning of service implementation and Implementing Plan
galaxy/<service>/PLAN.md— staged implementation plan for the service. May be already complete and resides for historical reasons.galaxy/<service>/docs/— live topic-based documentation that's deeper than what fits inREADME.md(per-feature design notes, protocol specs, runbooks). Not stage-by-stage history.
Per-stage CI gate
Every completed stage from any PLAN.md (per-service or ui/PLAN.md)
must be exercised on the local Gitea Actions runner before being
declared done. The runbook lives in tools/local-ci/README.md; the
short version is:
- Commit the stage changes.
make -C tools/local-ci push— pushesHEADto the local Gitea instance and triggers every workflow that matches the changed paths.- Poll the latest run via the API snippet in
ui/docs/testing.md(or the Gitea UI onhttp://localhost:3000) until it leavesrunning. Inspect the log on failure. - Only after the run is
successmay the stage be marked done in the correspondingPLAN.md.
This applies even when the local unit-test suite is green — workflow-only failures (path filters, action-version mismatches, missing secrets, runner-only environment differences) are cheap to catch here and expensive to catch on a remote PR. The push step is implicitly authorised: do not ask for confirmation on every stage.
If tools/local-ci is not running, bring it up first
(make -C tools/local-ci up); do not skip this gate. The single
exception is when the user explicitly waives it for a stage.
Decisions during stage implementation
Stages from PLAN.md produce decisions. Those decisions never live in a
separate per-decision history file. Instead, every non-obvious decision is
baked back into the live state in three places:
- The plan itself. Update the relevant stage's text, acceptance criteria, or targeted tests so it reflects what was decided. If earlier already-implemented stages need to follow the new agreement, correct their code, tests, and live docs in the same patch.
- Later, not-yet-implemented stages. When a decision affects later stages — scope, dependencies, deliverables, or tests — update those stages now, do not leave the future to re-derive them.
- Live documentation. Module
README.md, projectdocs/ARCHITECTURE.md,docs/FUNCTIONAL.md(with itsdocs/FUNCTIONAL_ru.mdmirror), the affected serviceopenapi.yamlor*.proto, and any topic doc undergalaxy/<service>/docs/that the decision touches.README.mdandARCHITECTURE.mdalways describe current state, not the history of how it was reached.
Scope of PLAN.md changes
The existing codebase of galaxy/<service> may be modified or extended when a
plan stage requires it. All such changes must be covered by new or updated tests
and reflected in documentation when they affect documented behavior.
Pre-production migration rule
The platform is not yet in production. Schema changes for backend go
into the existing backend/internal/postgres/migrations/00001_init.sql
file rather than into new 00002_*-prefixed files. Local databases and
integration test harnesses are recreated from scratch on every pull.
This rule is removed before the first production deployment. From
that point on every schema change becomes a new migration file with a
monotonically increasing prefix, and 00001_init.sql becomes immutable
history. See backend/internal/postgres/migrations/README.md for
details.
Documentation discipline
- Code and docs are kept in sync. If an implementation changes behavior
described in a
.mdor.yamlfile, update that file in the same patch. - If existing docs are incomplete or wrong for behavior you are already touching, fix them in the same patch.
- Do not silently remove commitments from
galaxy/<service>/README.mdorgalaxy/<service>/docs/*.md. When a rule changes, either update it in place with the new agreement, or move the section to a more appropriate doc with a reference kept. - Cross-module impact: if a new agreement requires changes in
already-implemented modules, make those changes — code, tests, docs — in
the same patch, and record the new rule in
docs/ARCHITECTURE.md.
Documentation synchronisation
The same behaviour is described in several parallel sources: code,
docs/ARCHITECTURE.md, docs/FUNCTIONAL.md (with its Russian mirror
docs/FUNCTIONAL_ru.md), the affected service README.md, the
relevant openapi.yaml or *.proto, and the topic-based docs under
galaxy/<service>/docs/. They must never disagree.
- Any patch that changes user-visible behaviour, an API contract, or a cross-service flow updates every affected source in the same change set — never one source in this patch and another later.
- Before declaring a change complete, read the relevant sections of
docs/ARCHITECTURE.md,docs/FUNCTIONAL.md, the affected service README, the relevantopenapi.yamlor*.proto, and the implementing code; confirm they describe the same behaviour. - When two sources disagree about existing behaviour, do not pick one silently. Decide which one is authoritative, fix the contradiction in the same patch, and call out the change in the response. If the resolution is non-obvious, escalate to the user before proceeding.
- When touching code, also re-read inline package and Go Doc Comments in the affected packages and update them when they no longer match the code.
- When
docs/FUNCTIONAL.mdchanges, mirror the same change intodocs/FUNCTIONAL_ru.md(translate only the touched paragraphs). Skipping the mirror is treated as an incomplete patch.
Code compactness
- Prefer compact code over speculative universality. Three similar occurrences are not yet a pattern — wait for the third real caller before extracting an abstraction.
- Do not add seams, hooks, or configuration knobs for hypothetical
future requirements. If the next stage of
PLAN.mdwill need something, the next stage will add it. - A bug fix does not need surrounding cleanup; a one-shot operation does not need a helper function; a single concrete value does not need a parameter.
- When the plan can be satisfied by reusing an existing function or type, do that instead of introducing a new one.
- This rule is about scope, not laziness — well-named identifiers, precise types, and full test coverage stay non-negotiable.
Dependencies
- Before adding a new module, check its upstream repository for the latest stable version and use that.
- When a well-maintained library clearly outperforms stdlib for a concrete need, do not adopt it silently — propose a short list of 1+ candidates for the user to pick. Default remains stdlib.
Language
- All code, comments, identifiers, commit messages, docs, and filenames are written in English.
- User-facing chat responses follow the Russian-translation rule from the
user-level
CLAUDE.md.