# Agent Operating Rules — read this before every phase

> **You are an autonomous engineer working one phase of the Balinyaar build.** This file is the
> contract for *how* you work. Every `backend-phase-N.md` / `frontend-phase-N-bM.md` links here and
> assumes you have read it. Do not skip it. Do not be lazy. Build production-quality, scalable,
> maintainable code — not a demo.

---

## 0. The golden behaviours

1. **No laziness, ever.** Implement the whole phase scope. No `// TODO: implement later`, no stubbed
   handlers that return fake data *unless the phase explicitly says "mock this behind a seam"*, no
   "left as an exercise". If you mock something, you mock it **behind a dependency-injected interface**
   and you record it in the mock registry (§7) — that is the *only* sanctioned form of "not real yet".
2. **Read before you write.** Complete the **Required reading** list in your phase file *first*. The
   business rules are decisions, not guesses — the product docs are the source of truth. Inferring a
   rule from code instead of reading the doc is a defect.
3. **Don't duplicate prior work.** Each phase lists **"What already exists"** with links to the prior
   phases that built it. Extend it; never re-create it. If you need to change something a prior phase
   built, change it in place and note it in your report.
4. **Stay in your project.** Backend phases touch `server/` (+ `dev/contracts`, `dev/shared-working-context/backend`). Frontend phases touch `client/` (+ `dev/shared-working-context/frontend`). Do **not** edit the other side's app code — coordinate through contracts and the handoff (§6).
5. **Match the surrounding style.** Mirror existing patterns; introduce no new ones without reason.
   The per-project `CLAUDE.md` (and server `CONVENTIONS.md`) are non-negotiable — follow them exactly.
6. **Leave the tree green.** Your phase is not done until the project's own quality gate passes
   (§4) and the Definition of Done ([definition-of-done.md](definition-of-done.md)) is fully met.
7. **Think about the future.** Every decision should consider scalability and maintenance: indexing,
   pagination, caching, idempotency, re-render cost, bundle size, the seam that lets a mock become real.
   See the conventions checklists ([backend](backend-conventions-checklist.md) ·
   [frontend](frontend-conventions-checklist.md)).

---

## 1. The canonical sources of truth (know where each rule lives)

| You need… | Read |
| --- | --- |
| Repo-wide rules, two-project layout | root [`CLAUDE.md`](../../../CLAUDE.md) |
| Backend engineering rules | [`server/CLAUDE.md`](../../../server/CLAUDE.md) + [`server/CONVENTIONS.md`](../../../server/CONVENTIONS.md) |
| Frontend engineering rules | [`client/CLAUDE.md`](../../../client/CLAUDE.md) |
| Frontend design/brand rules | the **frontend-designer** skill (invoke it for any UI work) |
| Product / business / data-model / payments truth | [`product/`](../../../product/) (start at `product/index.md`) |
| The whole build plan + order | [`dev/phases/README.md`](../README.md) |
| Cross-project API/flow contracts | [`dev/contracts/`](../../contracts/README.md) |
| What the other agent has handed you | [`dev/shared-working-context/`](../../shared-working-context/README.md) |

**Precedence when two sources seem to conflict:** product docs (business truth) → the relevant
`CLAUDE.md`/`CONVENTIONS.md` (engineering truth) → this file → the phase file's specifics. If a real
conflict remains, do the safe thing, implement it, and flag it in your report — never silently guess
on money, auth, tenancy, or clinical-data rules.

---

## 2. Phase lifecycle (do these in order)

1. **Orient.** Read this file, your phase file end-to-end, and the **Required reading** it lists.
   Skim the prior-phase reports in `dev/shared-working-context/reports/` for what changed recently.
2. **Plan.** Restate the scope to yourself; list the entities/endpoints/screens you will build and the
   order. Identify every external dependency you must mock and the seam it sits behind.
3. **Build.** Implement the full scope following the project conventions and the checklists. Wire mocks
   behind DI. Keep commits/changes coherent.
4. **Self-verify.** Run the project's quality gate (§4) and the phase's **"How to test"** steps. Fix
   everything. Re-read your own diff as a reviewer would.
5. **Document & hand off.** Update the project docs (§5), write the contract(s) (§6, backend), write
   the phase report and update the mock registry (§7), write the handoff note (§6), and save memory (§8).
6. **Declare done** only when the Definition of Done is fully satisfied.

---

## 3. Best-practice mandate (this is graded, not optional)

**Backend** (full list in [backend-conventions-checklist.md](backend-conventions-checklist.md)):
Clean-Architecture boundaries (Domain → Application → Infrastructure → API; dependencies point inward);
CQRS via `martinothamar/Mediator` (`ISender`/`ICommand`/`IQuery`, `internal sealed` handlers,
`OperationResult` for expected failures — never throw); `AsNoTracking()` + `Select()` projection on
every read; pagination on every list; one `IEntityTypeConfiguration<T>` per entity; soft-delete query
filters; audit fields via the SaveChanges interceptor; **caching** read-heavy/config data behind the
cache seam; **idempotency + (where stated) Redis distributed locks** on the money path; **money is IRR
`BIGINT`, no floats, ever**; validate at the boundary with FluentValidation; `CancellationToken`
through every async call; zero new build warnings; no dead code; comment the *why*.

**Frontend** (full list in [frontend-conventions-checklist.md](frontend-conventions-checklist.md)):
Respect the RSC/client boundary; **fetch only through `clientFetch`/`serverFetch`** in
`services/{domain}`; use **TanStack Query with sensible `queryKey`s, `staleTime`, and cache
invalidation** so you never re-fetch data you already have; prevent needless re-renders (stable
references, `select`, colocated state, memo only where it pays); **MUI primitives stay MUI** (Button,
Avatar, Paper… — never re-implement a root component), but **compose shareable mid-level components at
the right shared level** (not buried in a page) when they'll be reused; every user-visible string is an
i18n key in **both** `en.json` and `fa.json`; colours from `tokens.css`; RTL-correct; `npm run check`
green; no dead code.

If a phase's work could be done quickly-but-wrong or properly-but-slower, **do it properly.**

---

## 4. The quality gate (run before declaring done)

- **Backend:** `dotnet build Baya.sln` (zero new warnings) **and** `dotnet test Baya.sln` (all pass).
  Add the handler/integration tests your phase introduces. A reachable SQL Server is required to run.
- **Frontend:** `npm run check` (type + lint) **and** `npm run test:ci` if you touched/added a shared
  component. Keep `en.json`/`fa.json` in sync.

A phase that doesn't pass its own gate is **not done**, regardless of how complete the code looks.

---

## 5. Update the project documents (in the same change)

Keep the docs honest — stale instructions are worse than none. When your phase changes how something
works or what the architecture is:

- **Architecture map:** if you add/rename/remove a project, layer, route group, provider, domain folder,
  or a cross-boundary seam, update the canonical map in the **same** change — server: the *Project map*
  in `server/CLAUDE.md`; client: the *Project Structure* tree in `client/CLAUDE.md`; repo-level: the
  *Repository layout* in root `CLAUDE.md`.
- **Product docs:** if you discover or decide a business rule that the `product/` docs don't yet
  capture (or that drifts from them), update the relevant `product/**.md` (and regenerate the HTML view
  per `product/CLAUDE.md` guidance if you changed Markdown). Do not invent rules — record decisions.
- **Conventions:** if you establish a new reusable pattern (a seam, a base class, a hook family), add a
  short note to the relevant `CLAUDE.md`/`CONVENTIONS.md` so the next phase reuses it.

Do **not** re-introduce removed starter/template scaffolding while editing docs.

---

## 6. Contracts & the parallel-agent handoff (how the two sides stay in sync)

Backend and frontend phases are designed to run **as two independent agents in parallel**. They never
edit the same files. They coordinate through two folders:

- **`dev/contracts/`** — *backend-owned, frontend-read.* When a backend phase ships an API, it writes
  the contract: a per-domain doc under `dev/contracts/domains/<domain>.md` (request/response shapes,
  routes, status codes, enums, examples) **and** ensures the server's `swagger.json` snapshot is
  published per `dev/contracts/openapi/README.md`. Follow the envelope/format rules in
  `dev/contracts/conventions/`. The frontend treats these as the source of truth for types — it does
  **not** guess shapes.
- **`dev/shared-working-context/`** — *the running handoff.* Strict lane ownership so parallel agents
  never collide:
  - **Backend writes only:** `shared-working-context/backend/STATUS.md` (append your phase summary),
    `shared-working-context/backend/handoff/after-backend-phase-N.md` (one new file per phase — what
    the frontend can now build, which endpoints/contracts are live, what's mocked), and your report +
    the mock registry in `shared-working-context/reports/`.
  - **Frontend writes only:** `shared-working-context/frontend/STATUS.md`, and
    `shared-working-context/frontend/requests/for-backend.md` (append contract gaps / shape requests —
    the backend agent reads this, you never edit backend files), and your frontend report in
    `shared-working-context/reports/`.
  - **Never edit a file the other lane owns.** If the frontend needs a contract change, it *requests*
    it; the backend *delivers* it in a subsequent change. This is what makes parallel runs safe.

When mock data is needed on the frontend before its backend phase is merged, build it behind the same
`services/{domain}` seam (a mock `clientApi`) and record it in your frontend report so it's swapped out
cleanly once the real endpoint lands.

---

## 7. The mock / integration report (mandatory, saved to a file — not just chat)

Every phase that mocks or defers an external service **must**:

1. Put the mock behind a **DI-registered interface** (a "seam") with a real-shaped contract, so the real
   implementation is a drop-in later. Mock and real both implement the same interface; selection is by
   configuration/registration, never by `if (mock)` scattered in handlers.
2. Append an entry to **`dev/shared-working-context/reports/mocks-registry.md`** with: the seam
   (interface name + file), what is faked, why, the config keys it reads, and **step-by-step how to make
   it real** (which provider, which package, which settings, which methods to implement, what to test).
3. Write a **per-phase report** at `dev/shared-working-context/reports/<backend|frontend>-phase-N-report.md`
   covering: *what was built*, *what is now testable and exactly how*, *what is mocked / waiting on a real
   service*, *contracts produced/consumed*, *follow-ups for later phases*. (See
   [reports/README.md](../../shared-working-context/reports/README.md) for the template.)

Services that will be mocked across the chain and the seam each lives behind (define once, reuse):
SMS/OTP delivery (`ISmsSender`), object storage / MinIO/S3 (`IObjectStorage`), cache/Redis
(`ICacheService`), distributed locks/Redis (`IDistributedLock`), search/Elasticsearch (`INurseSearch`),
PSP card gateway (`IPaymentProvider`), settlement-sharing/تسهیم (`ISettlementSplitProvider`), BNPL
(`IBnplProvider`), bank transfer PAYA/SATNA (`IBankTransferProvider`), webhook verification
(`IWebhookVerifier`), Shahkar (`IShahkarVerifier`), identity KYC/liveness (`IIdentityKycProvider`),
credential/license check (`ICredentialVerifier`), IBAN ownership (`IBankAccountOwnershipVerifier`),
geocoding/maps (`IGeocoder`), مودیان e-invoicing (`IMoadianClient`), AI review moderation
(`IReviewModerationService`), field encryption/KMS (`IFieldEncryptor`), notification dispatch
(`INotificationDispatcher`). The exact phase that *introduces* each seam is in the roadmap; later phases
*reuse* the seam, they do not redefine it.

---

## 8. Write memory & context when done

After the work passes its gate, record what a future agent would need and could not cheaply re-derive:

- **Persistent memory** (the Claude memory dir, per the repo's memory instructions): save/update a
  `project`-type memory note for any non-obvious decision, new seam, or gotcha this phase introduced,
  and add a one-line pointer to `MEMORY.md`. Don't record what the code/docs already make obvious.
- **Working context:** the handoff note (§6) and the phase report (§7) — these are the durable record
  the *other* agent and the *next* phase rely on.

---

## 9. When you're genuinely blocked

Some things are intentionally out of scope and must be **mocked, not invented**: real PSP/BNPL
connections, the Shahkar/MoH/INO/criminal-record vendors, MinIO/S3 credentials, the مودیان enrollment.
If you reach one, implement the seam + a faithful mock + the registry entry, and move on — do not stall
and do not fabricate a real integration. If a *business* rule is truly undecided (the product docs say
"open question"), pick the safe default, implement it config-drivenly where possible, and flag it in
your report for the human to confirm. Never block the chain on an external unknown.
