# 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` 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/.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/-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.