add build development phases

This commit is contained in:
hamid
2026-06-28 21:59:59 +03:30
parent 1df3cd9f64
commit 53a40dc51d
52 changed files with 12379 additions and 0 deletions
+204
View File
@@ -0,0 +1,204 @@
# 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.
@@ -0,0 +1,59 @@
# Backend conventions checklist (quick reference)
The authoritative rules are [`server/CLAUDE.md`](../../../server/CLAUDE.md) and
[`server/CONVENTIONS.md`](../../../server/CONVENTIONS.md). This is a tick-list to keep handy while you
build. If anything here seems to conflict with those files, **those files win**.
## Architecture
- [ ] Clean Architecture respected: Domain → Application → Infrastructure → API; **dependencies point
inward**. Domain references nothing; Application references only Domain; Infrastructure/API
implement Application contracts. Never reference Infrastructure/API from Domain/Application.
- [ ] New cross-layer dependency or project/folder ⇒ update the **Project map** in `server/CLAUDE.md`.
- [ ] New infrastructure is registered via a `ServiceConfiguration/` extension method called from
`Program.cs` — never inline in `Program.cs`.
## CQRS / features
- [ ] Feature lives in `Baya.Application/Features/<Area>/{Commands|Queries}/<Name>/`.
- [ ] Requests are `record`; handlers are `internal sealed`; one handler per request.
- [ ] **Never throw for expected failures** — return `OperationResult.SuccessResult/FailureResult/NotFoundResult`.
- [ ] Contracts the handler needs are interfaces in `Application/Contracts/`, implemented in Infrastructure.
- [ ] Input-bearing commands have a FluentValidation validator (picked up by `ValidateCommandBehavior`).
## Persistence (EF Core)
- [ ] Read queries use `AsNoTracking()` **and** project with `.Select(...)` to a DTO — never hydrate
entities to map them. Mapping (Mapster) happens in the handler after the query.
- [ ] Every unbounded list is **paginated** (`Skip`/`Take`); no unbounded `ToListAsync()`.
- [ ] Access the DB via `IUnitOfWork` in handlers; commit once per command (`CommitAsync`).
- [ ] One `IEntityTypeConfiguration<T>` per entity in `Persistence/Configuration/<Area>Config/`.
- [ ] Soft-deletable entities declare a global query filter (`!IsDeleted` / `deleted_at IS NULL`).
- [ ] Audit fields (`CreatedAt/ModifiedAt/CreatedById/ModifiedById`) are set by the SaveChanges
interceptor via `ICurrentUser` — handlers don't pass them.
- [ ] Encrypted PII columns (phone, national_id, IBAN, addresses, clinical notes) go through the field
encryptor seam — never stored or logged in plaintext.
## Performance, caching, money, idempotency
- [ ] Read-heavy/config/reference data is cached behind the cache seam with sensible invalidation;
`platform_configs` values are read through the typed config accessor (cached), not hardcoded.
- [ ] **Money is IRR `BIGINT` — no floats, anywhere.** Toman conversion happens only inside a provider
adapter at its boundary. The three booking amounts always satisfy
`gross = commission + payout`.
- [ ] Money-path writes are **idempotent** (webhook dedup on the unique external-event key; filtered
unique on succeeded transaction; forward-only state machines) and, where the phase says so, guarded
by a Redis **distributed lock** — with the DB constraint as the authoritative backstop.
- [ ] `ledger_entries` is append-only and balanced (Σdebit = Σcredit per `transaction_group_id`).
## API surface
- [ ] Controllers are `sealed`, inherit `BaseController`, inject `ISender`, return
`base.OperationResult(...)` — never `Ok()/BadRequest()/NotFound()` directly. (Note: the baseline
has **no** controllers yet — REST is introduced in an early phase; follow that pattern thereafter.)
- [ ] Routes use `[controller]`/`[action]` tokens (snake_case transformer); pass `CancellationToken`.
- [ ] Authorize with the narrowest fitting policy; auth/OTP/refund/payout-sensitive endpoints are
rate-limited.
- [ ] The endpoint's contract is published to `dev/contracts/` (see operating-rules §6).
## Quality
- [ ] `async`/`await` all the way; `CancellationToken` threaded through; no `.Result`/`.Wait()`/`async void`.
- [ ] Package versions only in `Directory.Packages.props`.
- [ ] Handler unit tests (NSubstitute) + at least one `WebApplicationFactory` integration test per new
feature area (happy path, 401, validation 400).
- [ ] `dotnet build` zero new warnings; `dotnet test` green; no dead code.
+43
View File
@@ -0,0 +1,43 @@
# Definition of Done — applies to every phase
A phase is **done** only when *all* of the following are true. Each phase file adds its own
phase-specific criteria on top of this shared baseline.
## Code
- [ ] The full scope in the phase file is implemented — no laziness, no unsanctioned stubs. Anything
not real is mocked **behind a DI seam** and recorded in the mock registry.
- [ ] It follows the project conventions exactly (server `CLAUDE.md` + `CONVENTIONS.md`, or client
`CLAUDE.md` + the frontend-designer skill) and the relevant conventions checklist.
- [ ] No dead code (unused vars/imports/usings/params/members). Comments explain *why*, not *what*.
- [ ] Best practices honoured: (backend) clean-arch boundaries, projected/paginated reads, caching where
it pays, idempotency/locks on the money path, IRR `BIGINT` money, validation at the boundary;
(frontend) RSC/client boundary, query caching + no needless refetch, minimal re-renders, MUI
primitives reused, i18n in both locales, tokens-based colours, RTL-correct.
## Gate
- [ ] **Backend:** `dotnet build Baya.sln` has zero new warnings **and** `dotnet test Baya.sln` passes,
including the tests this phase adds.
- [ ] **Frontend:** `npm run check` passes **and** `npm run test:ci` passes if a shared component was
touched/added; `en.json` and `fa.json` are in sync.
## Documentation
- [ ] The relevant architecture map is updated in the same change (server *Project map* / client
*Project Structure* / root *Repository layout*) if the structure changed.
- [ ] Any business rule discovered/decided is reflected in the `product/` docs (no invented rules).
- [ ] New reusable patterns/seams are noted in the relevant `CLAUDE.md`/`CONVENTIONS.md`.
## Contracts & handoff
- [ ] **Backend:** the API contract for what shipped is written to `dev/contracts/domains/<domain>.md`
and the `swagger.json` snapshot is published per `dev/contracts/openapi/README.md`.
- [ ] **Frontend:** types/services are derived from the published contract (not guessed); any contract
gap is appended to `dev/shared-working-context/frontend/requests/for-backend.md`.
- [ ] The handoff note `dev/shared-working-context/<lane>/...` is written (backend: a new
`handoff/after-backend-phase-N.md`; both lanes: a STATUS append).
## Reporting & memory
- [ ] The per-phase report `dev/shared-working-context/reports/<lane>-phase-N-report.md` is written:
what was built, **what is now testable and exactly how**, what is mocked + how to make it real,
contracts produced/consumed, follow-ups.
- [ ] The mock registry `dev/shared-working-context/reports/mocks-registry.md` is updated for every
seam this phase mocked/touched.
- [ ] Persistent memory is saved for any non-obvious decision/seam/gotcha, with a `MEMORY.md` pointer.
@@ -0,0 +1,49 @@
# Frontend conventions checklist (quick reference)
The authoritative rules are [`client/CLAUDE.md`](../../../client/CLAUDE.md) and the **frontend-designer**
skill (invoke it for any visual work). This is a tick-list. If anything here seems to conflict with
those, **they win**.
## Boundaries & structure
- [ ] Never add a layout above `[locale]`; `src/app/[locale]/layout.tsx` is the root layout.
- [ ] Respect the RSC/client boundary: no `next/headers`, `next-intl/server`, or `@/lib/cookies/server`
in client components; no `@/lib/cookies/client` in an RSC.
- [ ] New route group / provider / top-level `src/` folder ⇒ update the **Project Structure** tree in
`client/CLAUDE.md`.
## Data fetching & caching (prevent extra fetches and re-renders)
- [ ] Fetch **only** through `clientFetch`/`serverFetch` (`@/lib/api`); domain calls live in
`src/services/{domain}/apis/`. Never raw `fetch()`.
- [ ] Server state is **TanStack Query**: a `keys.ts` factory per domain, deliberate `staleTime`/`gcTime`,
and **cache invalidation on mutation** (`invalidateQueries`/`setQueryData`) so you never refetch
data you already hold. Prefer prefetch/`initialData` from RSC where it removes a client round-trip.
- [ ] One hook per file (`use{Action}.ts`), `useQuery`/`useMutation`. Don't toast 401/403/5xx in hooks
(the fetch layer already does) — only domain-specific 4xx messages.
- [ ] Minimise re-renders: stable references (`useCallback`/`useMemo` only where it pays), `select` to
subscribe to slices, colocate state low, lift only when shared. Don't put fast-changing state in
a high context provider.
## UI composition
- [ ] **Concrete MUI primitives stay MUI** — use `Button`, `Avatar`, `Paper`, `TextField`, etc. (or the
existing `App*` wrappers); never invent a new root-level Button/Avatar.
- [ ] **Composite/shareable components** (built from primitives, reused in >1 place — a nurse card, an
OTP input, a price-breakdown, a step header) live at the right **shared** level (`src/components/…`),
not inline in a page or buried in a leaf. A component imported from >1 place gets a co-located
`*.test.tsx`.
- [ ] Page-only, never-reused composition can stay in the page.
## i18n, theme, direction
- [ ] Every user-visible string is a key in **both** `messages/en.json` and `messages/fa.json` (in sync).
`fa` is default and **RTL** — design RTL-first; verify mirroring.
- [ ] Colours come from `tokens.css` (`var(--bal-…)` / brand tokens), never hardcoded in `sx`. Use the
pre-built `APP_THEME_LTR/RTL`; never `createTheme()` in a component.
- [ ] MUI **v9** API only (`sx={{ mb: 4 }}`, no v5/v6-only props).
## Quality
- [ ] Magic strings → named constants (`src/constants/` or a colocated `constants.ts`).
- [ ] Cookies/app state only through the cookie manager; never `document.cookie`/`localStorage` for auth.
- [ ] No dead code (unused vars/imports are lint **errors**). Comment the *why*, not the *what*.
- [ ] `npm run check` green; `npm run test:ci` green when a shared component changed.
- [ ] Types come from the published contract in `dev/contracts/` — don't guess server shapes; if a shape
is missing, append a request to `dev/shared-working-context/frontend/requests/for-backend.md` and
mock behind the `services/{domain}` seam meanwhile.
+63
View File
@@ -0,0 +1,63 @@
# Phase prompt template (the skeleton every phase file follows)
> This is the shape of every `backend-phase-N.md` and `frontend-phase-N-bM.md`. It exists so the
> chain is uniform and an agent always knows where to find each thing. When you (a planning author)
> create or edit a phase file, fill every section. When you (an executing agent) run a phase, expect
> every section to be present.
---
```
# <Backend|Frontend> Phase N — <Title>
> One-paragraph mission: what this phase delivers and why it matters to the product.
> **Track:** backend|frontend · **Depends on:** <prior phases / backend phase bM> · **Unlocks:** <what comes next>
> **Before you start, read [_shared/agent-operating-rules.md](../_shared/agent-operating-rules.md).** It is not optional.
## 1. Context — where this sits
- Where we are in the chain; the 23 sentence product framing.
- **What already exists (do not rebuild):** bullet list linking the prior phases + the baseline
facts (from `dev/shared-working-context/...` and the project state).
## 2. Required reading (do this first)
- Exact product docs to read (with paths) and *why* each matters.
- Exact code areas to read (existing patterns to mirror).
- Contracts to consume (frontend) / prior handoff notes.
## 3. Scope — build this
- The precise, enumerated deliverables: entities/migrations, commands/queries, endpoints
(backend); screens/flows, services/hooks, components (frontend). Each with enough detail to build
without guessing. Tag anything (DEFERRED) that is explicitly out of scope.
## 4. Mocks & seams in this phase
- Which external services are mocked, the interface each sits behind, what the mock returns, and the
pointer to record it in the mock registry. (Reuse seams introduced earlier; only *introduce* the
ones this phase owns.)
## 5. Critical rules you must not get wrong
- The domain-specific invariants (money correctness, idempotency, tenancy, two-stage clinical
disclosure, same-gender matching, RSC boundary, re-render/caching, etc.) relevant to this phase.
## 6. Definition of Done
- The phase-specific acceptance criteria, on top of the shared
[definition-of-done.md](../_shared/definition-of-done.md).
## 7. How to test (what a human can verify after this phase)
- Concrete, runnable steps (endpoints to curl / Swagger calls / screens to click) and the expected
result for each. This becomes the "what can be tested" section of your report.
## 8. Hand off & document (close the phase)
- Docs to update (which CLAUDE.md / product doc).
- Contract(s) to write (backend) / consume (frontend).
- The handoff note + report files to write, and the memory to save. (Mechanics in operating-rules §58.)
```
---
## Authoring notes
- Keep each phase **self-contained**: an agent should be able to execute it having read only the phase
file + the files it links. Link generously to prior phases and to `product/` — don't restate them.
- Phases are **vertical slices** where possible (entity → handler → endpoint → contract for backend;
service → hook → screen for frontend) so each ends in something testable.
- Never let a phase silently expand scope. If something belongs to a later phase, say so and link it.