# Repository Guidelines

## Scope

This repository contains the Vite and React single-page frontend for the
Agent-driven supply-network WebGIS. Runtime TypeScript lives under `src/`.
The application uses React 19, TypeScript, Tailwind CSS, MapLibre GL, SWR,
Vitest, and Playwright.

Keep this project browser-first. Do not add Next.js APIs, `"use client"`
directives, or general backend-for-frontend routes. Agent reasoning and tool
execution belong in `next-tjwater-agent`.

## Source Layout

- `src/app/` owns application startup, providers, and shell composition.
- `src/features/workbench/` owns supply sources, layers, SCADA overlays,
  scenarios, feature adapters, GeoServer configuration, and workbench
  interactions.
- `src/features/agent/` owns Agent protocol clients, sessions, typed frontend
  actions, validated UI envelopes, recommendations, and Agent panels.
- `src/features/map/core/` owns domain-neutral map controls, legends, notices,
  and reusable map presentation primitives.
- `src/shared/` owns reusable UI, AI presentation elements, runtime
  configuration, and feature-independent utilities.
- `src/mocks/` owns MSW handlers and fixtures.
- `src/test/` owns shared Vitest setup and repository-wide invariant tests.
- `tests/browser/` owns product-level Playwright regressions.
- `public/` contains static supply-network and SCADA assets plus the
  runtime-config placeholder.
- `server/` contains the same-origin Edge TTS adapter used by Vite and the
  production container.

Do not recreate a catch-all `src/lib/` directory. Put feature-independent
helpers in `src/shared/`; put supply-network and GeoServer logic in the
owning `workbench` module.

Do not create empty placeholder directories. Add a directory with its first
source file.

## Dependency Direction and Public APIs

Keep dependencies moving toward generic code:

```text
app       -> workbench, map/core, shared
workbench -> agent, map/core, shared
agent     -> map/core, shared
map/core  -> shared
shared    -> external packages only
```

- `src/app` may import the `workbench` and `map/core` public APIs plus
  shared startup configuration.
- `workbench` may import `agent`, `map/core`, and `shared`.
- `agent` may import generic `map/core` presentation helpers and `shared`,
  but it must not import `workbench`.
- `map/core` must not know supply layer IDs, SCADA models, workbench state, or
  Agent workflows.
- `shared` must not import from `app`, `features`, or `mocks`.
- Runtime feature code must not import from `app` or `mocks`.

Use a feature's `index.ts` as its public API for cross-feature imports. Add an
intentional public export when another feature needs a symbol. Use relative
imports within the same feature. Do not introduce cross-feature deep imports
or barrels for private implementation files.

## Component and Module Design

- Use TypeScript and React function components. Export explicit types at
  feature and adapter boundaries.
- Use two-space indentation and kebab-case filenames. Use PascalCase for
  components and types, camelCase for functions and values, and `useXxx` for
  hooks.
- Keep application and page components focused on composition. Extract state,
  effects, network flows, resize behavior, and map orchestration into focused
  hooks, controllers, or child components.
- Keep MapLibre sources, layers, camera helpers, feature queries, and event
  handling outside presentational components. Map mutations belong in typed
  controllers or map helpers.
- Keep Agent rendering schema-driven. Validate Agent output before it reaches
  React. Model map actions as typed data that can be previewed, confirmed,
  applied, and rolled back.
- Keep reusable UI free of supply-network terminology and workflow state. The
  owning feature decides business behavior.
- Prefer one source of truth. Search for an existing utility, config wrapper,
  style token, or domain type before adding another.

## Supply-Domain Boundary

This repository models a supply network. Pipes, junctions, valves, reservoirs,
tanks, pumps, pressure, flow, water age, demand, isolation, and continuity of
supply belong in `workbench`.

Do not introduce drainage-network layer IDs, assets, terminology, export
filenames, configuration prefixes, fixtures, or operating assumptions.
Drainage concepts such as conduits, orifices, outfalls, manholes, sewage,
stormwater, and overflow risk do not belong here.

`next-tjwater-drainage-frontend` may be consulted for generic architecture
patterns only. Never copy its domain constants, source catalogs, map styles,
icons, mocks, product copy, environment variables, or defaults into this
repository. The supply-domain invariant test in
`src/test/supply-domain.test.ts` must remain green.

## Runtime and Server Boundaries

Browser configuration is injected through `/runtime-config.js` and validated
in `src/shared/config/env.ts`. Use `TJWATER_*` variables. Do not add
`DRAINAGE_*`, `VITE_*`, or legacy `NEXT_PUBLIC_*` browser configuration.

Browser-safe GeoServer reads may happen directly when CORS is enabled. Agent
requests go to the configured Agent service. The local `server/` exception is
limited to the same-origin Edge TTS network adapter; do not turn it into a
general API layer or add free-form proxy routes.

## Tests

- Co-locate focused Vitest tests with the module under test using `*.test.ts`
  or `*.test.tsx`.
- Put repository-wide invariants and shared setup in `src/test/`.
- Put new product and interaction Playwright tests in `tests/browser/`.
  `src/app/app.e2e.ts` is retained migration coverage, not a location to copy.
- Name tests after behavior. Cover pure map calculations, adapters, protocol
  validation, and state transitions without requiring a browser when possible.
- Add focused Playwright coverage for visible behavior, responsive layout,
  runtime configuration, keyboard and pointer interaction, or map integration.

## Commands and Verification

Use `pnpm` from this repository.

```bash
pnpm dev          # start Vite on http://127.0.0.1:5173
pnpm lint         # run ESLint
pnpm typecheck    # run TypeScript without emitting files
pnpm test         # run Vitest
pnpm test:browser # run Playwright
pnpm build        # typecheck, build the SPA, and bundle the TTS adapter
```

Match verification to the change:

- Documentation-only changes: run `git diff --check` and verify referenced
  paths and commands.
- TypeScript logic or component changes: run `pnpm lint`, `pnpm typecheck`,
  and `pnpm test`.
- Visible UI, responsive, configuration, or map interaction changes: also run
  focused `pnpm test:browser` coverage.
- Dependency, Vite, container, runtime integration, or release changes: also
  run `pnpm build`.

Do not report a check as passing unless it ran in the current worktree. If a
required browser or external service is unavailable, report the skipped layer
and reason.

## Security and Repository Hygiene

Do not commit secrets, `.env.local`, generated `dist/` or `dist-server/`,
dependency folders, Playwright artifacts, session dumps, tokens, or logs. Keep
server-only targets and credentials in untracked environment files.

Treat Agent output, UI envelopes, feature identifiers, URLs, and runtime
configuration as untrusted input. Validate at system boundaries, keep
credentials out of browser-visible values, and use typed adapters instead of
free-form command or request construction.

Preserve unrelated work in a dirty checkout. Do not clean, reset, move, or
rewrite user changes while completing a scoped task.
