# AGENTS.md - Aeroflot.Flights.Web

## Read First

React 18 SSR app on Modern.js 2.70.8 with Rspack and Module Federation 2.3.3. It is deployed both as a standalone SSR app and as a remote frontend component for customer Web/PWA hosts.

Work in `src/`. Treat `ClientApp/` as legacy Angular 12 reference only unless the user explicitly asks otherwise.

Prefer small, local changes that match the existing architecture. Do not widen dependencies across layers, and do not introduce browser-only imports into SSR paths.

## Commands

```bash
pnpm install

pnpm dev          # Modern.js on :8081
pnpm dev:full     # Proxy on :8080; forwards API via curl

pnpm typecheck
pnpm lint
pnpm test
pnpm test:coverage
pnpm bundle-size      # remote gzip budget: <= 2000 kB
pnpm check-coverage   # line coverage gate: >= 65%

pnpm build:standalone # dist/standalone/
pnpm build:remote     # dist/remote/ with mf-manifest.json
pnpm build:both

pnpm test:e2e         # React app, baseURL http://localhost:8080
pnpm test:e2e:angular # Legacy Angular app, port 4203
```

## Critical Rules

- Components must be side-effect free: no `fetch` outside `useEffect`; use the API client from context.
- Use `React.lazy()` for dynamic imports. Wrap browser-only UI such as Leaflet in `ClientOnly`.
- SignalR must stay out of SSR bundles; import `@microsoft/signalr` dynamically only.
- Read env through `getEnv()` from `@/env/index.ts`; SSR injects `window.__ENV__`.
- Keep rendered state consistent with API responses; avoid stale state leaking into UI.
- Preserve SEO/accessibility requirements, including JSON-LD and OpenGraph where relevant.
- Keep layouts fluid and responsive across screen sizes.

## Agent Runtime Safety

- If a task asks for Pi Crew, use the Pi Crew `team` tool or the project slash prompt; do not silently continue as a normal parent Pi implementation session.
- Do not call unavailable abstract tools such as `glob`; use `rg --files`, `rg -n`, `find`, `sed`, `nl`, and `git grep`.
- Never repeat the same failed tool call or shell command more than once. Treat identical command, identical exit code, and identical/no output as a loop signal.
- If a command exits non-zero with no useful output, do not retry it unchanged. Inspect source/tests or change the hypothesis first.
- If a focused test fails, use the failure location to inspect and fix code/tests; do not repeatedly grep test output for unrelated terms.
- After two failed verification attempts without a code or test change, stop and report the blocker, current hypothesis, and next concrete fix.
- If five consecutive tool calls add no new information, stop and summarize what is known instead of continuing.

## Architecture

Top-level source areas:

- `src/routes/` - file-based routing and layouts.
- `src/features/` - feature modules: online board, schedule, flights map, popular requests.
- `src/ui/` - shared UI primitives only.
- `src/shared/` - API client, storage, hooks, SignalR helpers.
- `src/observability/` - logging, metrics, analytics.
- `src/i18n/` - i18n provider and translations.

Entry points:

- `src/routes/page.tsx` redirects to `/{lang}/onlineboard`.
- `src/routes/layout.tsx` owns global providers.
- `src/routes/[lang]/layout.tsx` owns locale-scoped i18n.

Module Federation:

- Remote name: `aeroflot_flights`.
- Exposes: `./OnlineBoard`, `./Schedule`, `./FlightsMap`, `./PopularRequests`.
- Remote build must emit `dist/remote/mf-manifest.json`, served as `/mf-manifest.json`.

## Layer Boundaries

ESLint enforces these boundaries:

- `features/` must not import `routes/` or `mf/`.
- `ui/` must not import `features/`, `routes/`, or `mf/`.
- `shared/` must not import `features/`, `routes/`, `mf/`, or `observability/`.
- `observability/` must not import `features/`, `routes/`, or `mf/`.

Restricted imports:

- Use `@/observability/metrics/otel` instead of importing OTel SDKs directly.
- Use `@/i18n/provider` instead of importing `react-i18next` directly.
- Use `@/shared/storage` instead of direct `localStorage` or `sessionStorage`.

## Progressive Detail

Reach for the sections below only when the task needs them.

### Contractual Requirements

- Modern.js SSR, React 18+, Module Federation 2.0 compatible output.
- `mf-manifest.json` must expose components and logic at `https://<domain>/mf-manifest.json`.
- Customer REST APIs use JSON payloads only.
- Target capacity: 100 RPS.
- Remote component must remain isolated from host components.
- Required analytics/monitoring integrations include Yandex.Metrica, CTM, Variocube, and Key-Astrom/Dynatrace.
- Frontend logs and system events must be exportable to customer aggregators.
- Implementation must follow customer mockups, design system, and standard remote module structure.

### Dev Server

- `pnpm dev` serves Modern.js SSR/HMR on port 8081.
- `pnpm dev:full` serves port 8080 and proxies:
  - `/api/*` and `/flights/*` to `https://flights.test.aeroflot.ru` via curl.
  - all other paths to Modern.js on 8081.

### Build And Deploy

- `dist/standalone/` is the Node SSR server, deployed with `Dockerfile.react`.
- `dist/remote/` is the static MF remote, deployed with `Dockerfile.remote`.
- CI/CD lives in `.github/workflows/ci.yml` and `.github/workflows/deploy.yml`.

### Current Constraints

- Modern.js 3.x upgrade is currently blocked by `@module-federation/modern-js` ESM incompatibilities.
- React Router v7 future flags are enabled to suppress deprecation warnings.

## Git And CI

- Do not add `Co-Authored-By` lines.
- Commit messages must be English, concise, and focused on why.
- Commit completed stable work autonomously. Ask before pushing, force-pushing, or destructive git operations.
- Use Gitea `tea` for workflow runs:
  - `tea run list --limit 5`
  - `tea run view <run-id>`
  - `tea run rerun <run-id>`
