cleanup phases 6

This commit is contained in:
hamid
2026-08-02 18:48:32 +03:30
parent e2db97392a
commit 51e86a1e5f
239 changed files with 118 additions and 70 deletions
+162
View File
@@ -0,0 +1,162 @@
# The Clarify Chain — a plan to clean up Balinyaar's documentation
**Status:** planned, not started · **Written:** 2026-07-29 · **Baseline commit:** `96b57eb`
This folder is a **plan**, not documentation. It describes eight phases that take the repo from its
current state — 260 markdown files, ~10 competing rule sources, five unreconciled backlogs, and a
contract layer that stopped tracking the code on 2026-07-13 — to a single navigable `docs/` tree that
tells the truth.
When the chain finishes, **this folder moves to `archive/`**. It is temporary by design.
---
## Why this exists (the diagnosis)
Measured against the working tree at `96b57eb`:
| Finding | Evidence |
| --- | --- |
| **3.0 MB / 199 files of build history in [`dev/`](../../dev/)** reads as instruction, not record | [`dev/phases/`](../../dev/phases/) last touched 2026-06-28 (already-executed prompts) sits beside [`dev/post-phase/`](../../dev/post-phase/) touched 2026-07-28 (live plan). Nothing marks the difference. |
| **Rules live in ~10 places** | root [CLAUDE.md](../../CLAUDE.md) · [client/CLAUDE.md](../../client/CLAUDE.md) **161 KB** · [server/CLAUDE.md](../../server/CLAUDE.md) 75 KB · [server/CONVENTIONS.md](../../server/CONVENTIONS.md) · [client/messages/STYLE.md](../../client/messages/STYLE.md) · [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) · [dev/phases/_shared/](../../dev/phases/_shared/) ×4 · [dev/contracts/conventions/](../../dev/contracts/conventions/) ×2 · 3× `AGENTS.md` · [.githooks/README.md](../../.githooks/README.md) |
| **Loading `client/CLAUDE.md` costs ~40k tokens** on any client edit | 161 KB, of which lines 103421 are a project-structure listing and lines 4211100 are explanatory reference |
| **Remaining work is split across 5 ledgers** | 67 REQs in a 1,115-line append-only file · **18 hardening items, none ticked** · per-phase "Follow-ups" buried in 50+ reports · backend deferrals-with-pull-triggers · [product/notes/open-questions.md](../../product/notes/open-questions.md) · two raw feedback notes in [dev/manual-testing/](../../dev/manual-testing/) |
| **Contracts drifted from code** | [`dev/contracts/`](../../dev/contracts/) frozen 2026-07-13; `server/src` moved through 2026-07-28. OpenAPI snapshot is from 07-13; a second stale copy sat at `temp/swagger.json` (07-06). **Phase 0 correction:** that copy was **untracked** (`.gitignore:1`), and the measured OpenAPI drift turned out to be one endpoint — see [open-contradictions.md](open-contradictions.md#openapi-drift). |
| **18 files still instruct you to use `dotnet user-secrets`** — removed in `5885280` | includes [manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md), the closest thing to a test guide |
| **No single "what's implemented + how to test it"** | knowledge split across manual-testing-plan, [RUNBOOK.md](../../dev/post-phase/refinement/RUNBOOK.md), `product/business/`, and 18 contract files |
| **The client↔server dependency is implicit** | envelope shape, casing, idempotency, cookies/refresh, CORS, `NEXT_PUBLIC_API_URL`, 3 containers + Caddy + remote SQL + the OTP bot — described nowhere as one thing |
The code itself is **not** the mess. 83 client routes, 22 service domains, 125 client tests; 56
controllers, 199 handlers, 24 migrations. The problem is that nothing tells you which parts of that
are real, which are mocked, and which are described by a document written three weeks ago.
---
## Decisions this plan implements
Agreed 2026-07-29, before any file was written:
| Decision | Choice |
| --- | --- |
| Doc home | **New top-level `docs/` tree.** `product/` stays as-is; `dev/` becomes `archive/`; CLAUDE.md files shrink to hard rules + pointers |
| `dev/` history | **Distill, then archive in-repo.** Every live fact extracted first; raw files moved under `archive/` with a do-not-obey banner |
| Rules | **Tiered.** CLAUDE.md keeps only non-negotiables (~200 lines); everything explanatory becomes reference read on demand |
| Verification | **Verify the load-bearing claims.** Flow status, the 18 hardening items, REQ dispositions, bring-up steps, OpenAPI — checked against code, not copied |
| Flow docs | **One file per flow, indexed** by a status table |
| Backlog | **One triaged file, new `BL-###` ids**, each carrying its origin id |
| `product/` | **Untouched.** An implementation overlay in `docs/status/` maps business areas → build state |
| Language | **English throughout** |
| Skills | **Small set, reality-checked.** Rewrite `frontend-designer`; add a backend-feature and a flow-testing skill |
| Roadmap | **Record + propose** a sequenced next chain; ordering is a proposal you can overrule |
| Anti-drift | **Lightweight guardrails.** A documentation convention, `Last verified:` stamps, a pre-commit warning |
---
## Target tree
```
docs/
README.md the one entry point — a map, nothing else
rules/ what must never be broken
index.md
documentation.md the anti-drift convention
shared/ naming, money & types, api conventions, git
client/ structure, theme, forms, i18n, services, auth, testing
server/ structure, cqrs, persistence, identity, conventions
integration/ the client<->server dependency, in one place
index.md the seam, as a single picture
api-contract.md envelope, casing, pagination, errors, idempotency
domains/ per-domain contracts (refreshed from dev/contracts)
openapi/swagger.v1.json regenerated, dated
config-matrix.md every env var / setting, both projects + docker
topology.md 3 containers + Caddy + remote SQL + OTP bot
flows/ what is implemented and how to test it
index.md status table of every flow
testing-setup.md bring-up, accounts, seeded world, reset
<flow>.md one per flow
status/ where the project actually is
index.md
implemented.md product/business area -> build state overlay
backlog.md BL-### triaged, every open item
backlog-closed.md
decisions.md distilled ADR log from the phase chain
roadmap/ where it goes next
index.md next-up.md deferred.md tech-debt.md pre-launch.md
_plan/ this folder (moves to archive/ when done)
archive/
README.md "historical record. Do NOT treat as instructions."
build-chain/ was dev/phases + dev/shared-working-context
post-phase/ was dev/post-phase
manual-testing/ was dev/manual-testing (screenshots kept)
product/ unchanged
CLAUDE.md slim, points into docs/
DEPLOY.md stays at root — the deploy *procedure*; topology lives in docs/integration/
```
**The rule that keeps these apart:** `product/` = what the business is. `docs/` = what we built and how
we work. `archive/` = how we got here. A file belongs in exactly one.
---
## The eight phases
| # | Phase | Depends on | Rough size | Output |
| --- | --- | --- | --- | --- |
| 0 | [Inventory & scaffold](phase-0-inventory-and-scaffold.md) | — | 1 session | `docs/` skeleton + a disposition for all 260 files + fresh OpenAPI |
| 1 | [Rules consolidation](phase-1-rules-consolidation.md) | 0 | 12 sessions | `docs/rules/` + slim CLAUDE.md files |
| 2 | [Integration & dependency](phase-2-integration.md) | 0 | 1 session | `docs/integration/` |
| 3 | [Flow atlas (verified)](phase-3-flow-atlas.md) | 0, 2 | **done** 2026-08-02 | `docs/flows/` — 25 files, 23 flows, 283 gaps for phase 4 |
| 4 | [Backlog reconciliation](phase-4-backlog.md) | 0, 3 | 12 sessions | `docs/status/` |
| 5 | [Roadmap & tech requirements](phase-5-roadmap.md) | 4 | 1 session | `docs/roadmap/` |
| 6 | [Archive & prune](phase-6-archive.md) | 15 | 1 session | `archive/`, `dev/` gone, links fixed |
| 7 | [Skills & guardrails](phase-7-skills-and-guardrails.md) | 1, 3 | 1 session | `.claude/skills/` rewritten + anti-drift hooks |
```
┌─ 1 rules ──────────────┐
0 ──────┼─ 2 integration ─ 3 flows ─ 4 backlog ─ 5 roadmap ─┼─ 6 archive
└────────────────────────┴──── 7 skills ────────────┘
```
Phases 1 and 2 can run in parallel with each other after 0. Everything else is a chain.
---
## How to run a phase
Point a fresh agent session at one phase file:
> Execute `docs/_plan/phase-2-integration.md`.
Each phase file states its own inputs, outputs, steps, verification, and definition of done. It ends
by ticking its own row in the progress table below and writing a short handoff note at the bottom of
its own file. **Do not run two phases in one session** — the point of this exercise is that context
stays small.
## Non-negotiables for every phase
1. **Nothing is deleted before it is distilled.** Phase 6 is the only phase that removes files, and it
may only remove files that Phase 0's inventory marked as *archived* or *extracted*.
2. **Verify, don't copy.** If a claim is load-bearing (a flow works, an item is closed, a command
boots the app), check it against the code or run it. If you cannot verify it, write it with an
explicit `UNVERIFIED:` prefix rather than asserting it.
3. **Every status/flow doc carries a `> Last verified: <date> against <commit>` header line.**
4. **Write short.** The failure mode this chain fixes is length. A reference doc over ~400 lines
should be split. A phase that produces a 30 KB file has misunderstood the assignment.
5. **Record contradictions, don't silently pick.** When two docs disagree, check the code, write the
truth, and log the contradiction in `docs/status/decisions.md`.
6. **Update this README's progress table** in the same change that finishes a phase.
## Progress
| Phase | Status | Finished | Notes |
| --- | --- | --- | --- |
| 0 Inventory & scaffold | **done** | 2026-07-29 | 275 files surveyed (not ~260). OpenAPI refreshed — drift is **1 endpoint**, not a rewrite. 3 of 5 seeded contradictions were narrower than stated; see [open-contradictions.md](open-contradictions.md#corrections-to-the-seeded-list). Phase 4 owns 149 files |
| 1 Rules consolidation | **done** | 2026-07-30 | Row reconstructed by phase 2 — phase 1 finished without updating it. Evidence: all 18 `docs/rules/**` files exist and are stamped `2026-07-30 against d3ec723`, `docs/README.md` marks the section **written**, and C-11 + R-1…R-6 are recorded as resolved-by-phase-1 |
| 2 Integration & dependency | **done** | 2026-07-30 | 27 files under `docs/integration/`. All 186 operations assigned to exactly one of 22 domain files (1:1 with `client/src/services/`). **Main finding: 24 phantom endpoints** — the client↔swagger axis nobody had checked; 2 are live 404s. Also 5 mis-filed REQs, 1 never-filed REQ (**C-15**), 8 client drifts, 5 config gaps. Resolved C-2, C-6, C-7, C-8, C-9 + C-3's contract half |
| 3 Flow atlas | **done** | 2026-08-02 | `docs/flows/` — 25 files, 23 flows, 283 gaps. 1 built · 15 partial · 7 mocked. Six findings, led by dead admin RBAC and 34 phantom client seam operations |
| 4 Backlog reconciliation | **done** | 2026-08-02 | `docs/status/` — 262 open `BL-###` (18 blocker · 86 major · 115 minor · 43 deferred), 88 closed, from ~700 raw rows across 10 sources. Admin RBAC (BL-001/002) touches 11 of 14 business areas |
| 5 Roadmap | **done** | 2026-08-02 | `docs/roadmap/` — 51 deferred items (43 + 8 filed elsewhere by severity) recorded with triggers, all 8 unbuilt tables named; `pre-launch.md` covers credential rotation (+ the FieldEncryption migration spelled out), 11 mocked rails, and the Development-in-production trade; `next-up.md` proposes 5 sequenced units; one stray finding (BL-245) verified and corrected in `backlog.md`/`decisions.md` along the way |
| 6 Archive & prune | **done** | 2026-08-02 | `dev/` (199 md + 1 json, 3.6 MB) moved to `archive/` via `git mv`, preserving history. `archive/README.md` written first with the do-not-obey banner + area→successor map. 9 live docs' inbound links repointed (`CLAUDE.md`, `docs/status/*`, `docs/flows/*`, `docs/integration/domains/index.md`, `product/notes/open-questions.md`); `docs/README.md`'s stale "not yet written" status/roadmap rows and "archive/ does not exist yet" line corrected in the same pass. `docs/_plan/` itself moved to `archive/clarify-chain/` last |
| 7 Skills & guardrails | not started | | |
+421
View File
@@ -0,0 +1,421 @@
# Inventory — a disposition for every markdown file
> Survey run 2026-07-29 against commit `c99e3f4`. Produced by
> [phase 0](phase-0-inventory-and-scaffold.md). **This is a survey, not documentation** — it moves to
> `archive/` with the rest of `_plan/` when the chain finishes.
**275 markdown files**, 3.58 MB total. 209 carry
**live facts** — content not yet captured anywhere else, which must be extracted before the file is archived.
## How to read this
| Column | Meaning |
| --- | --- |
| `kind` | `rule` (must-obey) · `reference` · `contract` · `plan` (an instruction to an agent) · `report` · `history` · `business` · `ops` · `feedback` |
| `disposition` | `keep-as-is` · `move` · `distill` · `merge-into` · `archive` · `delete` |
| `target` | where the *content* ends up — a `docs/…` path, or `archive/…` |
| `owner phase` | the phase that extracts the content. `none` = no phase touches the file |
| `live facts?` | does it hold anything not already captured elsewhere? |
Two conventions keep the `target` column short:
1. **Every `dev/**` row is additionally moved to `archive/` by Phase 6.** The `owner phase` column names
the phase that extracts its content *first*; Phase 6 is implied everywhere and is not repeated.
2. `§5` / `§7` refer to the fixed section numbering every `dev/phases/*` prompt shares —
**§5 "Critical rules you must not get wrong"** (the decisions that are *not* visible in the code) and
**§7 "How to test"** (the input Phase 3 turns into flow docs). Verified present in all 32 prompt files.
## Summary
| disposition | files |
| --- | --- |
| `archive` | 172 |
| `keep-as-is` | 59 |
| `distill` | 24 |
| `move` | 17 |
| `merge-into` | 2 |
| `delete` | 1 |
| owner phase | files |
| --- | --- |
| 0 | 1 |
| 1 | 17 |
| 2 | 23 |
| 3 | 2 |
| 4 | 149 |
| 6 | 17 |
| 7 | 31 |
| none | 35 |
| kind | files |
| --- | --- |
| plan | 86 |
| report | 70 |
| business | 48 |
| history | 25 |
| contract | 19 |
| rule | 15 |
| ops | 5 |
| reference | 5 |
| feedback | 2 |
### What this says
- **172 files are `archive`** — nearly all of `dev/`. They are
executed prompts and their reports: a record of how the code got here, phrased as instructions. That
phrasing is the single biggest hazard in the repo, and Phase 6's do-not-obey banner is the fix.
- **Only 1 file is deleted outright** (`Prompt.md`, 0 bytes). Nothing else is lost —
everything either moves, is distilled, or is archived intact.
- **Phase 4 owns 149 files**, by far the largest share. The backlog
reconciliation is the heaviest extraction job in the chain, not the flow atlas.
---
## The table
### Root & repo-level — 6 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `.claude/skills/frontend-designer/SKILL.md` | 21 K | 2026-07-27 | rule | `distill` | docs/rules/client/theme.md; skill rewritten | 1 | yes |
| `.githooks/README.md` | 1.6 K | 2026-07-28 | ops | `keep-as-is` | .githooks/README.md + docs/rules/documentation.md | 7 | yes |
| `AGENTS.md` | 478 B | 2026-06-21 | rule | `keep-as-is` | AGENTS.md — links repointed at docs/ | 1 | no |
| `CLAUDE.md` | 8.4 K | 2026-07-28 | rule | `distill` | CLAUDE.md (slim) + docs/rules/ | 1 | yes |
| `DEPLOY.md` | 8.3 K | 2026-07-28 | ops | `keep-as-is` | DEPLOY.md — stale user-secrets ref fixed | 2 | yes |
| `Prompt.md` | 0 B | 2026-06-28 | plan | `delete` | — (0 bytes, empty) | 0 | no |
### `client/` — 5 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `client/AGENTS.md` | 594 B | 2026-06-21 | rule | `keep-as-is` | client/AGENTS.md — links repointed | 1 | no |
| `client/CLAUDE.md` | 158 K | 2026-07-27 | rule | `distill` | client/CLAUDE.md (slim) + docs/rules/client/* | 1 | yes |
| `client/README.md` | 4.5 K | 2026-06-23 | reference | `keep-as-is` | client/README.md | 1 | no |
| `client/graphify-out/GRAPH_REPORT.md` | 18 K | untracked | report | `keep-as-is` | — (gitignored tool output, not repo content) | none | no |
| `client/messages/STYLE.md` | 7.6 K | 2026-07-19 | rule | `distill` | docs/rules/client/i18n.md | 1 | yes |
### `server/` — 6 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `server/AGENTS.md` | 573 B | 2026-06-21 | rule | `keep-as-is` | server/AGENTS.md — links repointed | 1 | no |
| `server/CLAUDE.md` | 73 K | 2026-07-28 | rule | `distill` | server/CLAUDE.md (slim) + docs/rules/server/* | 1 | yes |
| `server/CONVENTIONS.md` | 26 K | 2026-07-28 | rule | `distill` | docs/rules/server/conventions.md | 1 | yes |
| `server/LICENSE.md` | 1.1 K | 2026-06-16 | reference | `keep-as-is` | server/LICENSE.md | none | no |
| `server/README.md` | 5.3 K | 2026-06-21 | reference | `keep-as-is` | server/README.md | 1 | no |
| `server/graphify-out/GRAPH_REPORT.md` | 76 K | untracked | report | `keep-as-is` | — (gitignored tool output, not repo content) | none | no |
### `telegram-otp-bot/` — 2 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `telegram-otp-bot/INTEGRATION-PROMPT.md` | 8.1 K | 2026-07-27 | plan | `archive` | archive/post-phase/; config facts → docs/integration/config-matrix.md | 2 | yes |
| `telegram-otp-bot/README.md` | 7.5 K | 2026-07-28 | ops | `keep-as-is` | telegram-otp-bot/README.md; cited by docs/integration/topology.md | 2 | yes |
### `docs/_plan/` — this chain — 9 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `docs/_plan/README.md` | 10 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-0-inventory-and-scaffold.md` | 7.6 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-1-rules-consolidation.md` | 9.3 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-2-integration.md` | 7.8 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-3-flow-atlas.md` | 9.6 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-4-backlog.md` | 8.5 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-5-roadmap.md` | 5.8 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-6-archive.md` | 4.8 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
| `docs/_plan/phase-7-skills-and-guardrails.md` | 5.9 K | 2026-07-29 | plan | `archive` | archive/_plan/ (when the chain finishes) | 6 | yes |
### `dev/contracts/` — the API contract layer — 21 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/contracts/README.md` | 2.7 K | 2026-06-28 | contract | `move` | docs/integration/index.md | 2 | yes |
| `dev/contracts/conventions/api-conventions.md` | 2.9 K | 2026-07-13 | rule | `distill` | docs/rules/shared/api-conventions.md + docs/integration/api-contract.md | 1 | yes |
| `dev/contracts/conventions/money-and-types.md` | 2.6 K | 2026-06-28 | rule | `distill` | docs/rules/shared/money-and-types.md | 1 | yes |
| `dev/contracts/domains/_TEMPLATE.md` | 1.2 K | 2026-07-13 | contract | `move` | docs/integration/domains/_TEMPLATE.md | 2 | no |
| `dev/contracts/domains/bnpl.md` | 9.5 K | 2026-07-13 | contract | `move` | docs/integration/domains/bnpl.md | 2 | yes |
| `dev/contracts/domains/booking-requests.md` | 11 K | 2026-07-13 | contract | `move` | docs/integration/domains/booking-requests.md | 2 | yes |
| `dev/contracts/domains/bookings-evv.md` | 9.1 K | 2026-07-13 | contract | `move` | docs/integration/domains/bookings-evv.md | 2 | yes |
| `dev/contracts/domains/catalog.md` | 9.3 K | 2026-07-13 | contract | `move` | docs/integration/domains/catalog.md | 2 | yes |
| `dev/contracts/domains/config-reference.md` | 7.4 K | 2026-07-13 | contract | `move` | docs/integration/domains/config-reference.md | 2 | yes |
| `dev/contracts/domains/geography-addresses.md` | 8.1 K | 2026-07-13 | contract | `move` | docs/integration/domains/geography-addresses.md | 2 | yes |
| `dev/contracts/domains/identity-auth.md` | 7.3 K | 2026-07-13 | contract | `move` | docs/integration/domains/identity-auth.md | 2 | yes |
| `dev/contracts/domains/identity-profiles.md` | 7.1 K | 2026-07-13 | contract | `move` | docs/integration/domains/identity-profiles.md | 2 | yes |
| `dev/contracts/domains/messaging-notifications-admin.md` | 11 K | 2026-07-13 | contract | `merge-into` | docs/integration/domains/messaging.md (absorbs messaging.md) | 2 | yes |
| `dev/contracts/domains/messaging.md` | 851 B | 2026-07-13 | contract | `merge-into` | docs/integration/domains/messaging.md (with messaging-notifications-admin.md) | 2 | yes |
| `dev/contracts/domains/payments.md` | 5.2 K | 2026-07-13 | contract | `move` | docs/integration/domains/payments.md | 2 | yes |
| `dev/contracts/domains/payouts.md` | 9.8 K | 2026-07-13 | contract | `move` | docs/integration/domains/payouts.md | 2 | yes |
| `dev/contracts/domains/refunds-invoices.md` | 11 K | 2026-07-13 | contract | `move` | docs/integration/domains/refunds-invoices.md | 2 | yes |
| `dev/contracts/domains/reviews-records.md` | 9.5 K | 2026-07-13 | contract | `move` | docs/integration/domains/reviews-records.md | 2 | yes |
| `dev/contracts/domains/search.md` | 6.6 K | 2026-07-13 | contract | `move` | docs/integration/domains/search.md | 2 | yes |
| `dev/contracts/domains/verification.md` | 18 K | 2026-07-13 | contract | `move` | docs/integration/domains/verification.md | 2 | yes |
| `dev/contracts/openapi/README.md` | 1.2 K | 2026-06-28 | contract | `move` | docs/integration/openapi/README.md | 2 | yes |
### `dev/phases/` — executed build prompts — 38 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/phases/README.md` | 11 K | 2026-06-28 | plan | `archive` | archive/build-chain/ | 6 | no |
| `dev/phases/_shared/agent-operating-rules.md` | 13 K | 2026-06-28 | rule | `distill` | docs/rules/shared/* | 1 | yes |
| `dev/phases/_shared/backend-conventions-checklist.md` | 4.1 K | 2026-06-28 | rule | `distill` | docs/rules/server/* | 1 | yes |
| `dev/phases/_shared/definition-of-done.md` | 2.8 K | 2026-06-28 | rule | `distill` | docs/rules/documentation.md + docs/rules/shared/git.md | 1 | yes |
| `dev/phases/_shared/frontend-conventions-checklist.md` | 3.3 K | 2026-06-28 | rule | `distill` | docs/rules/client/* | 1 | yes |
| `dev/phases/_shared/phase-template.md` | 3.1 K | 2026-06-28 | plan | `archive` | archive/build-chain/ (template — nothing to extract) | 6 | no |
| `dev/phases/backend/backend-phase-0.md` | 12 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-1.md` | 32 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-10.md` | 38 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-11.md` | 38 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-12.md` | 33 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-13.md` | 28 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-14.md` | 27 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-15.md` | 42 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-2.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-3.md` | 31 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-4.md` | 30 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-5.md` | 35 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-6.md` | 35 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-7.md` | 31 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-8.md` | 38 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/backend/backend-phase-9.md` | 43 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-0.md` | 11 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-1-b2.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-10-b11.md` | 23 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-11-b12.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-12-b13.md` | 27 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-13-b14.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-14-b15.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-15-b15.md` | 56 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-2-b3.md` | 26 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-3-b4.md` | 23 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-4-b5.md` | 27 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-5-b6.md` | 28 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-6-b7.md` | 25 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-7-b8.md` | 27 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-8-b9.md` | 29 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
| `dev/phases/frontend/frontend-phase-9-b10.md` | 27 K | 2026-06-28 | plan | `archive` | archive/build-chain/phases/ · §5 → docs/status/decisions.md + docs/rules/ · §7 → docs/flows/ | 4 | yes |
### `dev/post-phase/` — follow-up chains — 56 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/post-phase/hardening/LOOP-PROMPT.md` | 3.0 K | 2026-07-17 | plan | `archive` | archive/post-phase/ | 6 | no |
| `dev/post-phase/hardening/README.md` | 9.4 K | 2026-07-17 | plan | `archive` | archive/post-phase/; scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-0-auth-gate.md` | 6.9 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-1-admin-rbac.md` | 7.3 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-2-mock-integrity.md` | 7.7 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-3-session-error-ux.md` | 6.2 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-4-contract-completion.md` | 7.1 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/hardening-phase-5-final-demock.md` | 6.2 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · scope → docs/status/backlog.md | 4 | yes |
| `dev/post-phase/hardening/issues.md` | 12 K | 2026-07-17 | plan | `distill` | docs/status/backlog.md (18 items, re-verified) | 4 | yes |
| `dev/post-phase/manual-testing-plan.md` | 24 K | 2026-07-27 | ops | `distill` | docs/flows/testing-setup.md + docs/flows/<flow>.md | 3 | yes |
| `dev/post-phase/refinement/README.md` | 10 K | 2026-07-10 | plan | `archive` | archive/post-phase/ | 6 | no |
| `dev/post-phase/refinement/RUNBOOK.md` | 15 K | 2026-07-28 | ops | `distill` | docs/flows/testing-setup.md | 3 | yes |
| `dev/post-phase/refinement/refinement-phase-0-bring-up.md` | 12 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-1-database-and-seed.md` | 10 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-2-auth-and-role-nav.md` | 9.8 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-3-contract-batch.md` | 13 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-4-frontend-de-mock.md` | 10 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-5-security-hygiene.md` | 5.5 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-6-money-correctness.md` | 5.9 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-7-unattended-ops.md` | 6.5 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-8-external-rails.md` | 7.7 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/refinement/refinement-phase-9-observability-and-scale.md` | 6.3 K | 2026-07-10 | plan | `archive` | archive/post-phase/ · decisions → docs/status/decisions.md | 4 | yes |
| `dev/post-phase/server/README.md` | 2.5 K | 2026-07-10 | plan | `archive` | archive/post-phase/ | 6 | no |
| `dev/post-phase/server/frontend-backend-gaps.md` | 18 K | 2026-07-10 | plan | `distill` | docs/status/backlog.md | 4 | yes |
| `dev/post-phase/server/post-phase-backend-plan.md` | 42 K | 2026-07-10 | plan | `distill` | docs/status/decisions.md + backlog.md | 4 | yes |
| `dev/post-phase/server/runtime-services.md` | 21 K | 2026-07-13 | reference | `distill` | docs/integration/topology.md + docs/rules/server/* | 2 | yes |
| `dev/post-phase/ui/README.md` | 16 K | 2026-07-17 | plan | `archive` | archive/post-phase/; design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/admin-partner.md` | 21 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/auth-first-run.md` | 18 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/booking-lifecycle.md` | 20 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/checkout-money.md` | 19 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/component-primitives.md` | 20 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/cross-cutting-ux.md` | 19 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/customer-account.md` | 18 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/customer-storefront.md` | 20 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/feature-components.md` | 20 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/messaging-notifications.md` | 19 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/microcopy.md` | 17 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/nurse-trust-ops.md` | 21 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/nurse-workspace.md` | 19 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/shell-and-navigation.md` | 20 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/audit/theme-and-brand.md` | 19 K | 2026-07-17 | report | `archive` | archive/post-phase/ · design reality → frontend-designer skill | 7 | yes |
| `dev/post-phase/ui/ui-phase-0-design-language.md` | 24 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-1-primitives-and-states.md` | 23 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-10-messaging-and-notifications.md` | 22 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-11-admin-and-partner-console.md` | 22 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-12-copy-motion-and-polish.md` | 23 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-13-public-front-door.md` | 21 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-2-shells-and-navigation.md` | 23 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-3-auth-and-first-run.md` | 21 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-4-customer-storefront.md` | 24 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-5-booking-lifecycle.md` | 21 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-6-checkout-and-money.md` | 23 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-7-nurse-daily-ops.md` | 22 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-8-nurse-business-and-verification.md` | 22 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
| `dev/post-phase/ui/ui-phase-9-customer-account-and-care-circle.md` | 23 K | 2026-07-17 | plan | `archive` | archive/post-phase/ · design rules → docs/rules/client/theme.md | 7 | yes |
### `dev/shared-working-context/` — handoffs, status, reports — 81 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/shared-working-context/README.md` | 3.0 K | 2026-06-28 | plan | `archive` | archive/build-chain/ | 6 | no |
| `dev/shared-working-context/backend/STATUS.md` | 39 K | 2026-07-13 | history | `distill` | docs/status/decisions.md + docs/status/implemented.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-0.md` | 3.1 K | 2026-06-30 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-1.md` | 4.3 K | 2026-07-02 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-10.md` | 4.2 K | 2026-07-06 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-11.md` | 3.5 K | 2026-07-09 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-12.md` | 4.2 K | 2026-07-09 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-13.md` | 4.2 K | 2026-07-09 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-14.md` | 4.5 K | 2026-07-09 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-15.md` | 4.5 K | 2026-07-10 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-2.md` | 3.5 K | 2026-07-02 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-3.md` | 4.1 K | 2026-07-02 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-4.md` | 4.4 K | 2026-07-02 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-5.md` | 6.4 K | 2026-07-02 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-6.md` | 7.3 K | 2026-07-05 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-7.md` | 3.3 K | 2026-07-05 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-8.md` | 4.9 K | 2026-07-06 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-backend-phase-9.md` | 3.5 K | 2026-07-06 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-0.md` | 2.5 K | 2026-07-12 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-1.md` | 3.4 K | 2026-07-13 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-6.md` | 2.2 K | 2026-07-13 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-7.md` | 2.4 K | 2026-07-13 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-8.md` | 4.0 K | 2026-07-13 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/backend/handoff/after-refinement-phase-9.md` | 3.0 K | 2026-07-13 | history | `archive` | archive/build-chain/ · deferrals → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/frontend/STATUS.md` | 45 K | 2026-07-13 | history | `distill` | docs/status/decisions.md + docs/status/implemented.md | 4 | yes |
| `dev/shared-working-context/frontend/requests/for-backend.md` | 104 K | 2026-07-20 | history | `distill` | docs/status/backlog.md (67 REQs → BL-###) | 4 | yes |
| `dev/shared-working-context/reports/README.md` | 1.4 K | 2026-06-28 | plan | `archive` | archive/build-chain/ | 6 | no |
| `dev/shared-working-context/reports/backend-phase-0-report.md` | 6.8 K | 2026-06-30 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-1-report.md` | 5.9 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-10-report.md` | 5.4 K | 2026-07-06 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-11-report.md` | 6.7 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-12-report.md` | 7.6 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-13-report.md` | 6.2 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-14-report.md` | 7.0 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-15-report.md` | 6.5 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-2-report.md` | 7.8 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-3-report.md` | 5.2 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-4-report.md` | 5.7 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-5-report.md` | 7.8 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-6-report.md` | 10 K | 2026-07-05 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-7-report.md` | 6.3 K | 2026-07-05 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-8-report.md` | 6.6 K | 2026-07-06 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/backend-phase-9-report.md` | 6.4 K | 2026-07-06 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-0-report.md` | 6.8 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-1-report.md` | 7.4 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-10-report.md` | 8.4 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-11-report.md` | 8.4 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-12-report.md` | 8.3 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-13-report.md` | 11 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-14-report.md` | 13 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-15-report.md` | 10 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-2-report.md` | 6.6 K | 2026-07-02 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-3-report.md` | 8.4 K | 2026-07-05 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-4-report.md` | 9.3 K | 2026-07-05 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-5-report.md` | 8.9 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-6-report.md` | 6.5 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-7-report.md` | 9.5 K | 2026-07-09 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-8-report.md` | 9.5 K | 2026-07-10 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/frontend-phase-9-report.md` | 14 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/mocks-registry.md` | 73 K | 2026-07-19 | reference | `distill` | docs/status/implemented.md + docs/integration/index.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-0-report.md` | 6.1 K | 2026-07-12 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-1-report.md` | 7.3 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-2-report.md` | 6.6 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-6-report.md` | 6.8 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-7-report.md` | 6.6 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-8-report.md` | 12 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/refinement-phase-9-report.md` | 10 K | 2026-07-13 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-0-report.md` | 14 K | 2026-07-17 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-1-report.md` | 18 K | 2026-07-17 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-10-report.md` | 18 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-11-report.md` | 22 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-12-report.md` | 21 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-13-report.md` | 11 K | 2026-07-20 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-2-report.md` | 14 K | 2026-07-17 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-3-report.md` | 14 K | 2026-07-18 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-4-report.md` | 12 K | 2026-07-18 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-5-report.md` | 15 K | 2026-07-18 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-6-report.md` | 17 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-7-report.md` | 15 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-8-report.md` | 18 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
| `dev/shared-working-context/reports/ui-phase-9-report.md` | 14 K | 2026-07-19 | report | `archive` | archive/build-chain/reports/ · "Follow-ups" → docs/status/backlog.md | 4 | yes |
### `dev/manual-testing/` — human feedback — 2 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/manual-testing/iteration-1/improvement-and-fix-1.md` | 3.4 K | 2026-07-27 | feedback | `distill` | docs/status/backlog.md (unfinished items); PNGs kept | 4 | yes |
| `dev/manual-testing/iteration-2/improvement-2.md` | 1.2 K | 2026-07-27 | feedback | `distill` | docs/status/backlog.md (unfinished items); PNGs kept | 4 | yes |
### `dev/` root — 1 file
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `dev/README.md` | 2.3 K | 2026-07-17 | plan | `archive` | archive/README.md context | 6 | no |
### `product/` — business docs (untouched) — 48 files
| path | bytes | last commit | kind | disposition | target | owner phase | live facts? |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `product/README.md` | 2.9 K | 2026-06-24 | business | `keep-as-is` | product/README.md | none | no |
| `product/business/01-actors-and-onboarding.md` | 3.9 K | 2026-07-02 | business | `keep-as-is` | product/business/01-actors-and-onboarding.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/02-nurse-verification.md` | 6.8 K | 2026-07-05 | business | `keep-as-is` | product/business/02-nurse-verification.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/03-service-catalog-and-pricing.md` | 2.6 K | 2026-06-24 | business | `keep-as-is` | product/business/03-service-catalog-and-pricing.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/04-search-and-matching.md` | 2.8 K | 2026-06-24 | business | `keep-as-is` | product/business/04-search-and-matching.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/05-booking-and-scheduling.md` | 3.6 K | 2026-06-24 | business | `keep-as-is` | product/business/05-booking-and-scheduling.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/06-evv-and-service-delivery.md` | 2.3 K | 2026-06-24 | business | `keep-as-is` | product/business/06-evv-and-service-delivery.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/07-cancellation-and-refunds.md` | 4.1 K | 2026-07-09 | business | `keep-as-is` | product/business/07-cancellation-and-refunds.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/08-payments-and-escrow.md` | 4.8 K | 2026-06-24 | business | `keep-as-is` | product/business/08-payments-and-escrow.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/09-installments-bnpl.md` | 4.6 K | 2026-06-24 | business | `keep-as-is` | product/business/09-installments-bnpl.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/10-payouts.md` | 5.0 K | 2026-07-09 | business | `keep-as-is` | product/business/10-payouts.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/11-reviews-trust-and-safety.md` | 2.2 K | 2026-06-24 | business | `keep-as-is` | product/business/11-reviews-trust-and-safety.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/12-messaging-and-emergencies.md` | 2.3 K | 2026-06-24 | business | `keep-as-is` | product/business/12-messaging-and-emergencies.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/13-tax-invoicing-and-legal.md` | 4.0 K | 2026-06-24 | business | `keep-as-is` | product/business/13-tax-invoicing-and-legal.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/14-notifications-and-admin.md` | 2.8 K | 2026-06-24 | business | `keep-as-is` | product/business/14-notifications-and-admin.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/business/index.md` | 5.3 K | 2026-06-24 | business | `keep-as-is` | product/business/index.md · read-only source for docs/status/implemented.md | 4 | no |
| `product/data-model/01-identity-and-access.md` | 8.9 K | 2026-07-02 | business | `keep-as-is` | product/data-model/01-identity-and-access.md | none | no |
| `product/data-model/02-geography.md` | 1.9 K | 2026-07-02 | business | `keep-as-is` | product/data-model/02-geography.md | none | no |
| `product/data-model/03-services-and-pricing.md` | 4.2 K | 2026-06-24 | business | `keep-as-is` | product/data-model/03-services-and-pricing.md | none | no |
| `product/data-model/04-verification-and-credentials.md` | 3.8 K | 2026-06-24 | business | `keep-as-is` | product/data-model/04-verification-and-credentials.md | none | no |
| `product/data-model/05-booking-and-scheduling.md` | 8.3 K | 2026-06-24 | business | `keep-as-is` | product/data-model/05-booking-and-scheduling.md | none | no |
| `product/data-model/06-payments-ledger-and-refunds.md` | 11 K | 2026-07-09 | business | `keep-as-is` | product/data-model/06-payments-ledger-and-refunds.md | none | no |
| `product/data-model/07-payouts.md` | 2.1 K | 2026-06-24 | business | `keep-as-is` | product/data-model/07-payouts.md | none | no |
| `product/data-model/08-bnpl.md` | 2.8 K | 2026-06-24 | business | `keep-as-is` | product/data-model/08-bnpl.md | none | no |
| `product/data-model/09-messaging.md` | 958 B | 2026-06-24 | business | `keep-as-is` | product/data-model/09-messaging.md | none | no |
| `product/data-model/10-reviews-and-records.md` | 1.6 K | 2026-06-24 | business | `keep-as-is` | product/data-model/10-reviews-and-records.md | none | no |
| `product/data-model/11-notifications.md` | 868 B | 2026-06-24 | business | `keep-as-is` | product/data-model/11-notifications.md | none | no |
| `product/data-model/12-audit-config-and-reference.md` | 3.7 K | 2026-07-02 | business | `keep-as-is` | product/data-model/12-audit-config-and-reference.md | none | no |
| `product/data-model/13-partner-centers-and-future.md` | 2.6 K | 2026-06-24 | business | `keep-as-is` | product/data-model/13-partner-centers-and-future.md | none | no |
| `product/data-model/diagrams.md` | 5.4 K | 2026-06-24 | business | `keep-as-is` | product/data-model/diagrams.md | none | no |
| `product/data-model/index.md` | 20 K | 2026-06-24 | business | `keep-as-is` | product/data-model/index.md | none | no |
| `product/index.md` | 3.2 K | 2026-06-24 | business | `keep-as-is` | product/index.md | none | no |
| `product/notes/future-ideas.md` | 2.5 K | 2026-06-24 | business | `keep-as-is` | product/notes/future-ideas.md | none | no |
| `product/notes/open-questions.md` | 4.6 K | 2026-07-20 | business | `keep-as-is` | product/notes/open-questions.md · read-only source for docs/status/backlog.md | 4 | no |
| `product/overview/platform-summary.md` | 5.2 K | 2026-06-24 | business | `keep-as-is` | product/overview/platform-summary.md | none | no |
| `product/payments/bnpl-landscape.md` | 6.4 K | 2026-06-24 | business | `keep-as-is` | product/payments/bnpl-landscape.md | none | no |
| `product/payments/cancellation-and-payout.md` | 5.8 K | 2026-06-24 | business | `keep-as-is` | product/payments/cancellation-and-payout.md | none | no |
| `product/payments/escrow-ledger.md` | 5.5 K | 2026-07-06 | business | `keep-as-is` | product/payments/escrow-ledger.md | none | no |
| `product/payments/index.md` | 6.1 K | 2026-06-24 | business | `keep-as-is` | product/payments/index.md | none | no |
| `product/payments/integration-notes.md` | 6.5 K | 2026-06-24 | business | `keep-as-is` | product/payments/integration-notes.md | none | no |
| `product/payments/iranian-payment-reality.md` | 5.1 K | 2026-06-24 | business | `keep-as-is` | product/payments/iranian-payment-reality.md | none | no |
| `product/payments/sources.md` | 6.5 K | 2026-06-24 | business | `keep-as-is` | product/payments/sources.md | none | no |
| `product/research/go-to-market.md` | 5.0 K | 2026-06-24 | business | `keep-as-is` | product/research/go-to-market.md | none | no |
| `product/research/index.md` | 4.5 K | 2026-06-24 | business | `keep-as-is` | product/research/index.md | none | no |
| `product/research/legal-landscape.md` | 5.0 K | 2026-06-24 | business | `keep-as-is` | product/research/legal-landscape.md | none | no |
| `product/research/market-and-competitors.md` | 10 K | 2026-06-24 | business | `keep-as-is` | product/research/market-and-competitors.md | none | no |
| `product/research/problems-and-risks.md` | 9.7 K | 2026-06-24 | business | `keep-as-is` | product/research/problems-and-risks.md | none | no |
| `product/research/verification.md` | 7.5 K | 2026-06-24 | business | `keep-as-is` | product/research/verification.md | none | no |
---
## Non-markdown files this chain also moves
The survey covers `.md` files. Three non-markdown files are load-bearing for the same phases:
| path | bytes | disposition | target | owner phase |
| --- | --- | --- | --- | --- |
| `dev/contracts/openapi/swagger.v1.json` | 610 K | `archive` | superseded by `docs/integration/openapi/swagger.v1.json` | 2 |
| `temp/swagger.json` | 364 K | `delete` | — (stale duplicate, 2026-07-06; **untracked**`.gitignore:1` ignores `temp`) | 0 |
| `dev/manual-testing/iteration-{1,2}/*.png` (7 files) | — | `archive` | `archive/manual-testing/` — the only visual record of the pre-overhaul UI | 6 |
@@ -0,0 +1,143 @@
# Open contradictions
> Opened 2026-07-29 by [phase 0](phase-0-inventory-and-scaffold.md), against commit `c99e3f4`.
> **Phase 0 only finds these. It resolves none of them.**
> Last updated 2026-07-30 by [phase 2](phase-2-integration.md), against commit `d3ec723`:
> **C-2, C-6, C-7, C-8 and C-9 resolved**, C-3's contract-layer half resolved, **C-15 and C-16 added**.
Each row is *claim A* vs *claim B* with a location for both, and the phase that owns the resolution.
When a phase resolves one, it moves the row to **Resolved** at the bottom with the decision, and — per
the chain's non-negotiable #5 — records the decision in `docs/status/decisions.md`.
Three of the five contradictions the plan seeded turned out to be **narrower than stated**. Those are
written up as they actually are, with the evidence, in [§ Corrections to the seeded list](#corrections-to-the-seeded-list).
---
## Open
| # | Claim A | Claim B | Owner | Status |
| --- | --- | --- | --- | --- |
| C-1 | **Set the crypto keys with `dotnet user-secrets`** — [manual-testing-plan.md:22](../../dev/post-phase/manual-testing-plan.md), [:233](../../dev/post-phase/manual-testing-plan.md) | **`user-secrets` is not used; `<UserSecretsId>` was removed so the store is not read** — [CLAUDE.md:90](../../CLAUDE.md), [DEPLOY.md:20](../../DEPLOY.md), [server/CLAUDE.md:70](../../server/CLAUDE.md), and `Baya.Web.Api.csproj` (no `UserSecretsId` element) | 3 | open |
| C-3 | **The server listens on `https://localhost:5002`** — [CLAUDE.md:62](../../CLAUDE.md), [:135](../../CLAUDE.md), [api-conventions.md:6](../../dev/contracts/conventions/api-conventions.md), [RUNBOOK.md:7](../../dev/post-phase/refinement/RUNBOOK.md), [:84](../../dev/post-phase/refinement/RUNBOOK.md), [:112](../../dev/post-phase/refinement/RUNBOOK.md), + 12 more | **It listens on `http://localhost:5002`**`launchSettings.json:25` (`"applicationUrl": "http://localhost:5002"`), and `client/.env.development:20` (`NEXT_PUBLIC_API_URL = http://localhost:5002`) | 2 + 3 | **partly resolved by phases 1 + 2** — the three rule-file occurrences now say `http`; phase 2's [api-contract.md](../integration/api-contract.md) states `http` and banner-marks `api-conventions.md` as history. **Phase 2 also found a new occurrence the survey missed: `client/.env.sample:20`**, the file a fresh clone copies. `RUNBOOK.md` + the remaining occurrences are phase 3 |
| C-4 | **RUNBOOK's `dotnet dev-certs https --trust` step is required**, because the browser would otherwise reject the API — [RUNBOOK.md:26](../../dev/post-phase/refinement/RUNBOOK.md) | **The API is plain HTTP locally** (C-3's B side), so there is no certificate to trust | 3 | open — likely a dead step |
| C-5 | **Bring-up starts a local SQL Server in Docker on `localhost:1433`** — [RUNBOOK.md:18](../../dev/post-phase/refinement/RUNBOOK.md), [:3548](../../dev/post-phase/refinement/RUNBOOK.md), [:63](../../dev/post-phase/refinement/RUNBOOK.md) | **The committed dev config points at a remote SQL Server**`appsettings.Development.json` (`Server=87.107.152.16,1433`), and [manual-testing-plan.md:20](../../dev/post-phase/manual-testing-plan.md) calls the remote one "currently" the target | 3 | open — the two bring-up paths give *different worlds*: the remote DB is already seeded, a fresh local one is not |
| C-10 | **18 hardening items are open** — [issues.md](../../dev/post-phase/hardening/issues.md), 18 of 18 checkboxes unticked, last touched 2026-07-17 | **Fourteen UI phases, two manual-testing iterations, a Telegram integration and a deploy commit ran afterwards** (`12ce7fa``96b57eb`, 07-20 → 07-28) without ticking any box | 4 | open — Phase 4 must re-verify each item against code, not trust the checkbox |
| C-12 | **The skill is current** | **It is exactly one iteration behind the code.** SKILL.md's last commit is `baa3cc6` ("manual improvement 1"); `client/CLAUDE.md`'s is `e6a8f93` ("manual improvement 2"), which changed **44 files, +3419/2449** under `client/src`. Anything iteration 2 changed is absent from the skill | 7 | **partly resolved by phase 1** — the design-language half is corrected (see R-2); phase 7 still owns the skill's own workflow/procedure content |
| C-13 | **`dev/` is "the plan for building Balinyaar"**, written in the imperative — [dev/README.md:3](../../dev/README.md) | **It is a record of work already done.** `dev/phases/` last touched 2026-06-28; the code it describes shipped weeks ago | 6 | open — resolved by the archive banner, not by editing 199 files |
| C-14 | **`temp/swagger.json` is a stale committed duplicate** — [_plan/README.md](README.md) diagnosis table | **It is not committed at all**`.gitignore:1` ignores `temp`, and `git ls-files temp/` is empty. It is local clutter, not repo content | 0 | see [§ Corrections](#corrections-to-the-seeded-list) |
| C-15 | **`ui-phase-11-report.md:235` records "REQ-061…064 appended"** to the frontend request ledger | **REQ-061 was never appended.** The ledger goes 060 → 062; **ten live client files** cite REQ-061 for the admin user directory (`admin_users/search`, `admin_users/lookup`), which are 2 of the 24 phantom endpoints | 4 | **found by phase 2** — phase 4 must *file* it, not assume it is tracked |
| C-16 | **Five REQs' filed status** — REQ-050, REQ-063, REQ-066, REQ-067 (open, as filed) and the reasons `admin/constants.ts` gives for the admin mock | **All five are wrong or narrower than filed**, checked against the live swagger rather than against another document. `variantLabel` already ships; `tickets/close`+`reopen` already ship; `search/nurses` and `nurses/{id}/profile` are already anonymous; REQ-029/030 already shipped | 4 | **found by phase 2** — the table is in [phase-2's handoff § B](phase-2-integration.md) |
---
## OpenAPI drift
The fresh snapshot is at [`docs/integration/openapi/swagger.v1.json`](../integration/openapi/swagger.v1.json).
See its [README](../integration/openapi/README.md) for provenance. Measured against the 2026-07-13 snapshot
at `dev/contracts/openapi/swagger.v1.json`:
| | 2026-07-13 | 2026-07-29 |
| --- | --- | --- |
| paths | 177 | **178** |
| operations | 185 | **186** |
| component schemas | 339 | **339** |
**Added (1)**
- `POST /api/v1/webhooks/payouts/{provider}`
**Removed (0)** · **Methods changed on an existing path (0)** · **Schemas added/removed (0)**
**Schema definitions changed (1)**
- `GeneratePayoutBatchCommand` — gained `systemInitiated: boolean` (**C-7**, resolved)
> **This was Phase 2's worklist for the machine contract, and it was two lines long.** The 16-day gap
> between the snapshot and the code produced almost no wire-level drift. Phase 2 therefore spent its
> budget on the **hand-written** contract docs instead. See
> [§ Corrections](#corrections-to-the-seeded-list) C-14b.
### What phase 2 found once it looked
Re-scoping was right, but the conclusion "the hand-written docs are where the drift is" turned out to be
only half true, and the more useful axis was a third one nobody had checked:
| Axis | Result |
| --- | --- |
| Old contract docs → live swagger, at **route** level | **Clean.** Every route named across the 17 files exists in the live API (the two apparent misses are prose counter-examples: "X, *not* Y") |
| Old contract docs → live swagger, at **convention** level | **Drifted.** Body casing ("typically snake_case" vs. proven camelCase), the server's local URL scheme, the envelope's field count (5 vs. 6 — `code` was added), and the enum vocabularies |
| **Client's real API clients → live swagger** | **24 phantom routes** — calls to endpoints the server does not expose, 2 of them reachable today. This axis had never been checked and is where the real gap was |
The third row is the phase's main finding, and it is in
[phase-2's handoff § A](phase-2-integration.md).
---
## Corrections to the seeded list
The plan seeded five contradictions. Two hold as written; three are narrower than stated. Recording
this here so later phases do not budget for work that is already done.
**Holds — `user-secrets`.** The plan says 18 files still instruct you to use it. 32 mentions across 18
files is right, but the split matters: **6 files document the removal correctly** (root `CLAUDE.md`,
`DEPLOY.md`, `server/CLAUDE.md`, `server/CONVENTIONS.md`, and `RUNBOOK.md` twice — including a
troubleshooting row that names the error you now get). **12 are historical** — refinement prompts,
handoffs and reports written before the removal, all headed for `archive/`. Only **one live document
still gives the wrong instruction**: [manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md)
(last commit `bd06ef0`, the day *before* the removal in `5885280`), plus the archived
[telegram-otp-bot/INTEGRATION-PROMPT.md](../../telegram-otp-bot/INTEGRATION-PROMPT.md).
→ **The plan's statement that "both `manual-testing-plan.md` and `RUNBOOK.md` are stale on secrets
handling" is half wrong. `RUNBOOK.md` is current.** Phase 3 fixes one file, not two.
**Holds — hardening.** C-10 above. 18 of 18 unticked, four later chains, nothing reconciled.
**Narrower — contract drift (C-14b).** "`dev/contracts/` frozen 07-13 vs `server/src` through 07-28"
is true by date but nearly empty in substance at the OpenAPI layer: 1 endpoint, 1 schema. The drift
that matters, if any, is in the 17 hand-written domain markdown files. Phase 2 should re-scope
accordingly.
**Narrower — the design-language skill.** The plan says the skill "predates that overhaul" (mobile-scoped
shell, bottom nav, react-hook-form, new icon set). It does not: SKILL.md was rewritten at `baa3cc6`
during iteration 1 and already covers `AppFrame` (4×), `BottomBar`, `APP_FRAME_MAX_WIDTH` (2×) and the
Lucide-only icon registry with `@mui/icons-material` removed. `react-hook-form` is absent from the skill,
but it is an engineering rule that `client/CLAUDE.md` §Forms owns — not a design-language gap. The real
gap is C-12: the skill stopped at iteration 1 while the code went on to iteration 2.
**Wrong — `temp/swagger.json`.** C-14 above. It is `.gitignore`d and untracked, so it was never part of
the repo's documentation surface. Phase 0's brief says to delete it; that deletes a local file only.
---
## Resolved
Each row records the decision. **These decisions still need folding into `docs/status/decisions.md`
when phase 4 creates it** — that file does not exist yet, so this table is their only home.
| # | Was | Decision | By |
| --- | --- | --- | --- |
| **C-11** | The frontend-designer skill and `client/CLAUDE.md` both claimed the design language, with no stated precedence | **Precedence is now stated in both directions.** The skill is the **design** contract (brand, tone, logo construction, the visual decisions, and the workflow for turning a design into a screen); [`docs/rules/client/`](../rules/client/) is the **engineering** contract and **wins on every overlap** — tokens, typography, the component library, shells, icons. SKILL.md's header carries the precedence statement plus a table pointing at the four files it defers to, and the overlapping detail was removed from the skill rather than duplicated. `client/CLAUDE.md` no longer restates design content at all. | phase 1 |
| **C-2** | The placeholder `SET_VIA_USER_SECRETS_OR_ENV` names a store that was removed, so its *name* instructs a reader to use a removed mechanism | **The name stays; the mechanism is documented authoritatively elsewhere.** The string is a load-bearing sentinel in **seven live files**`appsettings.json` (×6), `StartupSecretsGuard.PlaceholderMarkers`, `.githooks/pre-commit`, `.githooks/README.md`, `Baya.Test.Api/StartupSecretsGuardTests.cs` (×2), `docs/rules/shared/git-and-gates.md`, `docs/rules/server/structure.md`. Renaming it is a server-code + git-hook + test change needing `dotnet build`/`dotnet test` to prove the gate still fires — outside a documentation phase's scope. [config-matrix.md](../integration/config-matrix.md#the-placeholders-name) is now the single authoritative statement that **config lives in appsettings files and environment variables and `user-secrets` is not read**, and `DEPLOY.md` says the same. **The rename is filed for phase 4 with that exact seven-file worklist.** | phase 2 |
| **C-6** | `POST /api/v1/webhooks/payouts/{provider}` was absent from the frozen contract | **It exists and is now documented** — the payout transferor's reconciliation callback, anonymous, `webhook` rate-limit policy, in [domains/payouts.md](../integration/domains/payouts.md). | phase 2 |
| **C-7** | `GeneratePayoutBatchCommand` changed shape between the two snapshots, unexplained | **It gained `systemInitiated: boolean`** alongside `periodStart`/`periodEnd`. That is the refinement-phase-7 scheduler flag distinguishing a job-generated draft batch from an admin-generated one — which is what keeps the "generation may be automatic, *processing* is always an explicit admin action" rule auditable. Recorded in [domains/payouts.md](../integration/domains/payouts.md). | phase 2 |
| **C-8** | Two live contract files for one domain: a headerless 851-byte `messaging.md` silently amending the 10.6 K `messaging-notifications-admin.md` | **Merged and split three ways along the client's real domain boundaries** — tickets → [domains/tickets.md](../integration/domains/tickets.md), the notification feed → [domains/notifications.md](../integration/domains/notifications.md), config/holidays/audit/alerts → [domains/admin.md](../integration/domains/admin.md). Every REQ-028 amendment is folded in as current fact, not as a change log. Both old files carry a merged-into banner so neither reads as live; phase 6 archives them. | phase 2 |
| **C-9** | The OpenAPI folder claimed documents `v1` **and** `v1.1`; only `v1` was ever committed | **Both documents genuinely are registered** (`AddSwagger("v1","v1.1")` in `Program.cs`), so `/swagger/v1.1/swagger.json` is served — **and it contains zero paths.** `ApiVersionDocumentProcessor` drops every path whose URL lacks the document's version segment, and all **55 controllers are `[ApiVersion("1")]`** on the route template `api/v{version:apiVersion}/…`. The old claim was literally true and substantively empty. `v1` is the contract; only `v1` is worth committing. **Resolved by reading the code — no server boot needed, so the `UNVERIFIED` marker is retired.** | phase 2 |
### Corrections landed by phase 1 that were not on the seeded list
Six rule statements were **false against the code**, not merely duplicated. Each was rewritten against
reality rather than carried over. They are recorded here because a future reader of `dev/`'s history will
find the old wording and needs to know it was checked.
| R- | The stale claim | Reality | Where it was |
| --- | --- | --- | --- |
| R-1 | "Use `ColorSchemeScript` from `@/theme`" | **No such export exists.** The no-flash boot is CSS-only; `theme/index.ts` exports only `ThemeProvider`, `getDirection`, `APP_THEME_*` | `client/CLAUDE.md:857` |
| R-2 | A `Storage.prototype.setItem` intercept writes the theme cookie (3 occurrences) | **There is no such patch.** `ColorSchemeCookieSync` — a `useColorScheme()` effect in `ThemeProvider.tsx` — writes it via `setClientCookie` | `client/CLAUDE.md:698, 711, 741` |
| R-3 | `AppImage` is part of the component library | **No such component** under `src/components/` | `SKILL.md:154` |
| R-4 | `CONTENT_MAX_WIDTH = 800` | It is **480**, mirroring `APP_FRAME_MAX_WIDTH` — iteration 1 changed it and the skill was never updated (this is C-12's concrete shape) | `SKILL.md:159` |
| R-5 | `AppFrame`'s header/`<main>`/footer are flex siblings, so a top bar is `position: static` | Iteration 2 pinned both bars **`position: absolute`** over a single scrolling `<main>`, which reserves their height as padding and publishes `--bal-chrome-top`/`-bottom` | `SKILL.md:181186` |
| R-6 | `DarkModeButton.tsx` is the `common` namespace's consumer | **Component deleted**; `ThemeModeSetting` (a three-way segmented control in `SettingsPanel`) replaced it | `client/CLAUDE.md:507` |
Two counts were also wrong and are corrected in the new docs: `client/CLAUDE.md:925` said "14 domains are
now REAL" and then listed **15** (verified against `services/*/constants.ts`: 15 real, 7 mocked), and
`:61` described `npm run check` as "type then lint", omitting **`lint:copy`**.
@@ -0,0 +1,221 @@
# Phase 0 — Inventory & scaffold
**Depends on:** nothing · **Blocks:** every other phase · **Size:** one session
## Goal
Before anything is moved, merged, or deleted, produce two things:
1. **A disposition for every one of the ~260 markdown files in the repo** — so that "summarize
without losing data" is a checkable claim rather than a hope.
2. **The empty `docs/` skeleton** with a real entry point, so later phases have somewhere to write.
Plus one piece of housekeeping every later phase needs: a **fresh OpenAPI snapshot**, because the
committed one is 16 days behind the server code.
This phase writes almost no prose. It is a survey.
---
## Inputs
- The whole repo. Specifically: `dev/` (199 files), `product/` (48), root (4), `client/` (5),
`server/` (6), `telegram-otp-bot/` (2), `.claude/skills/` (1), `.githooks/` (1).
- [`../README.md`](README.md) — the target tree and the decisions.
## Outputs
| File | What it is |
| --- | --- |
| `docs/_plan/inventory.md` | The disposition table — every markdown file, one row |
| `docs/README.md` | The single entry point: a map of `docs/`, `product/`, `archive/` and what belongs where |
| `docs/rules/index.md` `docs/integration/index.md` `docs/flows/index.md` `docs/status/index.md` `docs/roadmap/index.md` | Stub indexes, each with a one-line purpose and a "populated by phase N" note |
| `docs/integration/openapi/swagger.v1.json` | Regenerated from the running server |
| `docs/_plan/open-contradictions.md` | Running list of doc-vs-doc and doc-vs-code conflicts spotted during the survey — later phases resolve these |
---
## Steps
### 1. Build the inventory
Walk every `.md` file (exclude `node_modules`, `bin`, `obj`, `.git`). For each, record:
| Column | Meaning |
| --- | --- |
| `path` | repo-relative |
| `bytes` | size |
| `last commit` | `git log -1 --format=%ad --date=short -- <path>` |
| `kind` | `rule` · `reference` · `contract` · `plan` · `report` · `history` · `business` · `ops` · `feedback` |
| `disposition` | `keep-as-is` · `move` · `distill` · `merge-into` · `archive` · `delete` |
| `target` | where its content ends up (a `docs/…` path, or `archive/…`) |
| `owner phase` | which phase (17) handles it |
| `live facts?` | `yes` / `no` — does it contain anything not yet captured elsewhere? |
Rules for assigning disposition:
- **`dev/phases/backend/*` and `dev/phases/frontend/*`** (32 files, ~1 MB): these are *prompts that
were already executed*. Disposition `archive`. But scan each for **decisions and constraints stated
in the prompt that are not visible in the code** — those are `live facts: yes` and go to Phase 1
(if a rule) or Phase 4 (`decisions.md`).
- **`dev/shared-working-context/reports/*` (50 files)**: `archive`, but every "Follow-ups for later
phases" / "Deferred" / "Known gap" section is a live fact for **Phase 4**. Extract the section
headings now; Phase 4 reads them in detail.
- **`dev/shared-working-context/*/STATUS.md`** (86 KB combined): `distill` → Phase 4 (`decisions.md`
+ `implemented.md`), then `archive`.
- **`dev/shared-working-context/frontend/requests/for-backend.md`** (67 REQs): `distill` → Phase 4.
- **`dev/post-phase/hardening/issues.md`** (18 open items): `distill` → Phase 4, **with
re-verification** — the UI and refinement chains ran after this file was written and some items are
probably already fixed.
- **`dev/contracts/**`**: `move``docs/integration/` — Phase 2 owns it, and refreshes it against code.
- **`dev/post-phase/manual-testing-plan.md`** + **`refinement/RUNBOOK.md`**: `distill` → Phase 3
(`docs/flows/testing-setup.md` + the per-flow files). Both are stale on secrets handling.
- **`dev/manual-testing/iteration-*/`**: `distill` → Phase 4 (unfinished items) then `archive`
(**keep the PNG screenshots** — they are the only visual record of the pre-overhaul UI).
- **`product/**`**: `keep-as-is`, every one. Not this chain's business.
- **`client/CLAUDE.md`, `server/CLAUDE.md`, `server/CONVENTIONS.md`, `client/messages/STYLE.md`,
`dev/phases/_shared/*`, `dev/contracts/conventions/*`, `.claude/skills/*/SKILL.md`**: `distill`
Phase 1.
- **`DEPLOY.md`**: `keep-as-is` at root (it is the deploy *procedure* and it is current) — but Phase 2
fixes its stale `user-secrets` reference and Phase 2's `topology.md` links to it.
- **`Prompt.md`** (0 bytes): `delete`.
- **`temp/swagger.json`** (stale duplicate): `delete` — Phase 2 replaces it.
- **`client/graphify-out/GRAPH_REPORT.md`, `server/graphify-out/GRAPH_REPORT.md`**: generated tool
output. Decide `keep-as-is` if the tool is still used, else `delete`; check `.gitignore` first.
### 2. Log contradictions as you go
Write `docs/_plan/open-contradictions.md` with one row per conflict: *claim A (file:line) vs claim B
(file:line or code:line) — unresolved*. Seed it with the ones already known:
- **`user-secrets` is required** (18 files) vs **`user-secrets` was removed and the store isn't read**
(root [CLAUDE.md](../../CLAUDE.md) §6, commit `5885280`).
- **`dev/contracts/` describes the API** (frozen 2026-07-13) vs **`server/src`** (through 2026-07-28).
- **Design language in [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) §§17**
vs **[client/CLAUDE.md](../../client/CLAUDE.md) "Theme System" / "Anti-patterns"** — overlapping, possibly divergent.
- **Both** vs **the reality after iterations 12** (mobile-scoped shell, bottom nav, react-hook-form,
new icon set) — the skill predates that overhaul.
- **18 hardening items open** (2026-07-16) vs **UI phases 013 and the deploy commits that ran after**.
Do **not** resolve these here. Phase 0 only finds them.
### 3. Regenerate the OpenAPI snapshot
Boot the server and capture the live swagger document:
```bash
cd server && dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj
# then, from another shell:
curl -sk https://localhost:5002/swagger/v1/swagger.json -o docs/integration/openapi/swagger.v1.json
```
Record in the file's sibling `README.md`: the date, the commit, and the endpoint count. Diff the
endpoint *paths* against the old `dev/contracts/openapi/swagger.v1.json` and write the added/removed
list into `docs/_plan/open-contradictions.md` — Phase 2 uses it as its worklist.
If the server will not boot (config, DB reachability), **stop and report** rather than guessing. A
stale snapshot is what caused half of this mess.
### 4. Scaffold `docs/`
Create the directories and stub index files from the target tree in [`README.md`](README.md). Each
stub is ~10 lines: what lives here, which phase fills it, and a `> Populated by phase N — not yet
written` banner. `docs/README.md` is the only one with real content: the map, and the
`product/` vs `docs/` vs `archive/` rule.
Do **not** create `archive/` yet — Phase 6 does that, once there is something safe to put in it.
---
## Verification
- [ ] `docs/_plan/inventory.md` has a row for every `.md` file the survey walked; the count matches
`find . -name "*.md" -not -path "./node_modules/*" … | wc -l` (~260 at baseline).
- [ ] No row has an empty `disposition` or `owner phase`.
- [ ] Every row with `live facts: yes` names the phase that will extract them.
- [ ] `docs/integration/openapi/swagger.v1.json` exists and its endpoint count is recorded.
- [ ] Every stub index exists and says which phase fills it.
- [ ] Nothing outside `docs/` was modified, except deleting `Prompt.md` and `temp/swagger.json`.
## Definition of done
You can answer, for any markdown file in the repo, "where does this end up and who handles it?"
without re-reading the file.
## Handoff
**Run 2026-07-29 against commit `c99e3f4`. All six outputs delivered; all six verification boxes pass.**
### Counts
| | Planned | Actual |
| --- | --- | --- |
| Markdown files surveyed | ~260 | **275** (273 tracked + 2 gitignored `graphify-out/GRAPH_REPORT.md`) |
| `dev/` | 199 | 199 ✓ |
| `dev/shared-working-context/reports/` | 50 | **53** reports + `README.md` + `mocks-registry.md` |
| `dev/phases/backend|frontend` prompts | 32 | 32 ✓ |
| REQs in `for-backend.md` | 67 | 67 ✓ |
| Hardening items | 18 open | 18 of 18 unticked ✓ |
| `product/` | 48 | 48 ✓ |
The extra 15 over "~260" are the 9 files of `docs/_plan/` itself, the 2 gitignored graph reports, and 3
more reports than the plan counted.
Disposition split: **172 archive · 59 keep-as-is · 24 distill · 17 move · 2 merge-into · 1 delete**.
**209 of 275 carry live facts.** Owner phases: **4 → 149 files**, 7 → 31, 2 → 23, 1 → 17, 6 → 17, 3 → 2,
0 → 1, none → 35.
### Four things that change a later phase's scope
1. **Phase 2 is smaller than budgeted at the OpenAPI layer.** The 16-day-stale snapshot differs from the
live server by **one endpoint** (`POST /api/v1/webhooks/payouts/{provider}`) and **one schema**
(`GeneratePayoutBatchCommand`). Zero removals, zero method changes, identical schema count (339).
Spend the budget on the 17 hand-written `domains/*.md` instead — that is where drift can hide, and
nothing has ever checked them mechanically.
2. **Phase 3 fixes one stale bring-up doc, not two.** The plan says `manual-testing-plan.md` *and*
`RUNBOOK.md` are both stale on secrets. `RUNBOOK.md` was updated in `5885280` and is correct — it even
has a troubleshooting row for the error you now get. Only `manual-testing-plan.md` (last commit
`bd06ef0`, the day before) still instructs `dotnet user-secrets`. But Phase 3 inherits a **bigger**
bring-up problem the plan did not list: contradictions **C-3/C-4/C-5** — the API is `http://`, not
`https://`, in ~18 places; the `dev-certs` step is therefore dead; and `RUNBOOK.md` builds a *local*
Docker SQL Server while the committed dev config uses a *remote, already-seeded* one. Those are two
different worlds and Phase 3 must pick one and walk it.
3. **Phase 7's premise is wrong in one direction and right in another.** The frontend-designer skill does
**not** predate the UI overhaul — it was rewritten at `baa3cc6` (manual improvement 1) and already
covers `AppFrame`, `BottomBar`, `APP_FRAME_MAX_WIDTH` and the Lucide-only registry. It is stale by
exactly **one iteration**: `client/CLAUDE.md` was updated at `e6a8f93` (manual improvement 2), which
changed **44 files, +3419/2449** under `client/src`. Diff against iteration 2, not against the whole
overhaul.
4. **Phase 4 is the heavy phase, not Phase 3.** 149 of 275 files land on it. Two structural findings make
it tractable: every `dev/phases/*` prompt shares a fixed layout where **§5 "Critical rules you must not
get wrong"** is exactly the not-in-the-code decision set (verified in all 32), and **all 53 reports**
carry a "Follow-ups for later phases" section (verified). Both are mechanically extractable.
### Smaller notes
- **`temp/swagger.json` was never committed** — `.gitignore:1` ignores `temp`. Deleting it removed local
clutter, not repo content. The `_plan/README.md` diagnosis calls it a "second stale copy" in the repo;
it is not in the repo.
- **`dev/contracts/domains/messaging.md`** (851 B) is a headerless fragment that silently amends
`messaging-notifications-admin.md`. Phase 2 should **merge**, not move both (C-8).
- **`SET_VIA_USER_SECRETS_OR_ENV`** is still the placeholder string in `appsettings.json` and is enforced
by `StartupSecretsGuard` and the pre-commit hook. Behaviour is correct; the *name* instructs a reader to
use a store that no longer exists (C-2).
- **The `graphify-out/` reports are gitignored generated output**, so the plan's "decide keep or delete"
is moot — they are not repo content and were left alone.
- **Leaf directories are not pre-created.** `docs/rules/{shared,client,server}/` and
`docs/integration/domains/` are named in their index stubs but not made on disk: git does not track
empty directories, so an empty scaffold would silently vanish. Each phase creates its own with its
first file.
- **Server boot gotchas worth reusing** (recorded in `docs/integration/openapi/README.md`): it binds
**HTTP**, first boot takes ~40 s because Development migrates and seeds against the *remote* DB, and
`curl` to localhost returns **502** unless you pass `--noproxy '*'`.
### Contradictions
14 logged in [open-contradictions.md](open-contradictions.md), including a
[corrections section](open-contradictions.md#corrections-to-the-seeded-list) covering the three seeded
claims that did not reproduce as stated. Phase 0 resolved none, by design.
@@ -0,0 +1,243 @@
# Phase 1 — Rules consolidation
**Depends on:** Phase 0 · **Can run in parallel with:** Phase 2 · **Size:** 12 sessions
## Goal
Collapse ~10 rule sources into one tiered system, and cut the cost of editing client code from
~40k tokens to ~5k.
**The tiering rule:**
| Tier | Where | What goes in it | Budget |
| --- | --- | --- | --- |
| **Hard rules** | `client/CLAUDE.md`, `server/CLAUDE.md`, root `CLAUDE.md` | Constraints whose violation breaks the build, the gate, or a business invariant. Stated imperatively, no explanation. | ~200 lines each |
| **Reference** | `docs/rules/{shared,client,server}/*.md` | The *how* and the *why*. Read on demand when working on that area. | ~200400 lines per file |
| **Procedure** | `.claude/skills/` | Step-by-step playbooks for recurring tasks. **Phase 7** owns these. | — |
A rule that only matters when you are already editing theme code is **reference**, not a hard rule.
A rule like "never change `Seams:FieldEncryption:Key`" is a hard rule — it belongs inline.
---
## Inputs
Read these in full; they are the raw material:
| Source | Size | Contains |
| --- | --- | --- |
| [client/CLAUDE.md](../../client/CLAUDE.md) | 161 KB | 22 sections; lines 103421 are a structure listing, 421+ is reference |
| [server/CLAUDE.md](../../server/CLAUDE.md) | 75 KB | 11 sections; lines 89603 are the project map |
| [server/CONVENTIONS.md](../../server/CONVENTIONS.md) | 27 KB | naming, layering, CQRS shape |
| [client/messages/STYLE.md](../../client/messages/STYLE.md) | 8 KB | Persian copy rules (enforced by `lint:copy`) |
| [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) | 21 KB | brand, tokens, typography, component library, layout, icons |
| [dev/phases/_shared/agent-operating-rules.md](../../dev/phases/_shared/agent-operating-rules.md) | 13 KB | how agents were told to work |
| [dev/phases/_shared/definition-of-done.md](../../dev/phases/_shared/definition-of-done.md) | 3 KB | the gate |
| [dev/phases/_shared/backend-conventions-checklist.md](../../dev/phases/_shared/backend-conventions-checklist.md) | 4 KB | |
| [dev/phases/_shared/frontend-conventions-checklist.md](../../dev/phases/_shared/frontend-conventions-checklist.md) | 3 KB | |
| [dev/contracts/conventions/api-conventions.md](../../dev/contracts/conventions/api-conventions.md) | 3 KB | → **Phase 2 owns this**; read for cross-check only |
| [dev/contracts/conventions/money-and-types.md](../../dev/contracts/conventions/money-and-types.md) | 3 KB | → **Phase 2 owns this**; read for cross-check only |
| root [CLAUDE.md](../../CLAUDE.md) · 3× `AGENTS.md` · [.githooks/README.md](../../.githooks/README.md) | small | working agreements, pointers, the pre-commit hook |
Plus: `docs/_plan/inventory.md` and `docs/_plan/open-contradictions.md` from Phase 0.
## Outputs
```
docs/rules/
index.md what's here, and the tiering rule restated
documentation.md the anti-drift convention (Phase 7 adds the hook that enforces it)
shared/
naming.md Baya* vs balinyaar-client, @/* alias, file/dir conventions
git-and-gates.md branch, commit, pre-commit hook, what "done" means per project
code-quality.md no dead code, comment the why, no starter scaffolding
client/
structure.md the route/folder map (regenerated from reality, not copied)
theme.md tokens, palette, dark mode, RTL, fonts
components.md the App* library, when to reach for it vs raw MUI
forms.md react-hook-form (post-iteration-2), validation, field components
i18n.md next-intl v4, en/fa parity, STYLE.md copy rules folded in
services.md services/{domain} pattern, fetch layer, envelope, query keys
auth.md cookies, session state, refresh, RoleGuard, middleware/PUBLIC_PATHS
testing.md what is tested, how, the 125 existing tests
server/
structure.md the project map (condensed from server/CLAUDE.md lines 89-603)
cqrs.md how a feature is shaped: command/query/handler/validator
persistence.md EF Core, migrations, interceptors, the audit interceptor
identity.md JWE, sessions, rotation, field encryption, PhoneHash
conventions.md successor to CONVENTIONS.md
```
Rewritten in place: `CLAUDE.md` (root), `client/CLAUDE.md`, `server/CLAUDE.md`, 3× `AGENTS.md`.
Deleted after distillation: `server/CONVENTIONS.md`, `client/messages/STYLE.md` (content moves to
`docs/rules/client/i18n.md`; **check `lint:copy` doesn't read STYLE.md by path before deleting**).
---
## Steps
### 1. Extract every distinct rule into a ledger first
Before writing any output file, build a working list (scratch, not committed) of every *rule* found
across all inputs, tagged with: source file:line, scope (client/server/shared), tier
(hard/reference), and whether it is **contradicted or obsoleted** by another source or by the code.
This is the step that prevents loss. Merging by reading two documents side by side and writing a
third loses whatever was in neither's first half.
### 2. Reality-check the client rules against the post-overhaul code
`client/CLAUDE.md` and the frontend-designer skill both predate iterations 12 (commits `baa3cc6`,
`e6a8f93`). Those commits changed load-bearing things:
- **Mobile-scoped shell** — max-width container, no desktop sidebar for the nurse side
- **Bottom navigation** replacing the drawer, grouped root pages with domain summaries
- **Icon set replaced** wholesale
- **react-hook-form** for every form with >1 field (28 files currently import it — confirm coverage
and note any state-based forms left behind; that gap belongs in Phase 4's backlog)
- **Theme/language switches** moved into settings only, out of every top bar
- **Paper border-radius** reduced globally
Any rule in either document that describes the *old* behaviour is obsolete. Rewrite it against the
code, and log the correction in `docs/_plan/open-contradictions.md` as resolved.
Do the same, more briefly, for the server: `server/CLAUDE.md`'s "Project map" (514 lines) must match
the 14 `.csproj` projects and 56 controllers actually present.
### 3. Write the reference layer
One file per row of the Outputs tree. Each opens with a two-line purpose and a
`> Last verified: <date> against <commit>` line. Keep them under ~400 lines; if `client/structure.md`
wants to be longer, it is listing files it should be describing patterns for.
### 4. Rewrite the three CLAUDE.md files
Each becomes, in order:
1. One paragraph: what this project is.
2. **Stack** and **Commands** (keep — they are consulted constantly).
3. **Quality gates** — the exact commands that must pass.
4. **Hard rules** — a numbered list, imperative, no prose. Target 1525 items.
5. **Where to read more** — a table mapping "working on X" → `docs/rules/…/X.md`.
Root `CLAUDE.md` keeps its "What Balinyaar is", "Repository layout" (updated for `docs/` and
`archive/`), and the working agreements — but agreement 7 ("keep the architecture map current") now
points at `docs/rules/` as well.
Rules that must survive into the hard-rule lists verbatim (do not soften):
- `Seams:FieldEncryption:Key` / `:HashKey` are load-bearing — changing them makes every PII read throw
and every phone lookup miss.
- Config lives in files, not a secret store — **`dotnet user-secrets` is not used and is not read**.
(This is the single most-repeated stale instruction in the repo; state it loudly.)
- Stay within one project per change.
- No dead code; the client fails the build on unused vars.
- Don't reintroduce starter scaffolding or `_TITLE_`/`_DESCRIPTION_` placeholders.
- Read `product/` before changing behaviour.
### 5. Rewrite the three `AGENTS.md`
They stay thin pointers. Update the paths they point at.
### 6. Write `docs/rules/documentation.md`
The anti-drift convention, as agreed:
- What to update when X changes (endpoint → `docs/integration/`; flow ships → `docs/flows/<flow>.md`;
backlog item closed → tick it in `docs/status/backlog.md`, never delete it; structure changes →
the matching architecture section).
- The `> Last verified: <date> against <commit>` header convention, and which docs must carry it.
- The one-home rule: `product/` = business, `docs/` = engineering + status, `archive/` = history.
- Length budgets, so this doesn't regrow.
Phase 7 adds the pre-commit warning that enforces the first bullet.
---
## Verification
- [ ] `client/CLAUDE.md` under 250 lines; `server/CLAUDE.md` under 250 lines.
- [ ] Every rule in the Step-1 ledger appears in exactly one output file — spot-check 20 at random.
- [ ] No rule describes pre-iteration-1/2 client behaviour.
- [ ] `grep -rn "user-secrets" client/ server/ CLAUDE.md docs/` returns only statements that it is
**not** used.
- [ ] `cd client && npm run check` still passes (in case `lint:copy` referenced `STYLE.md` by path).
- [ ] Both `AGENTS.md` pointer files resolve.
- [ ] Every contradiction Phase 0 logged in the rules domain is marked resolved with its resolution.
## Definition of done
An agent opening `client/CLAUDE.md` learns what it may not do in under 250 lines, and knows exactly
which one file to open next for the area it is touching.
## Handoff
**Run 2026-07-30 against commit `d3ec723`. Complete.**
### What shipped
| | Before | After |
| --- | --- | --- |
| `client/CLAUDE.md` | 1,098 lines / 158 K | **177 lines** |
| `server/CLAUDE.md` | 772 lines / 73 K | **184 lines** |
| root `CLAUDE.md` | 136 lines | **164 lines** |
| `server/CONVENTIONS.md` | 508 lines | **deleted**`docs/rules/server/conventions.md` |
| `client/messages/STYLE.md` | 116 lines | **deleted**`docs/rules/client/i18n.md` §4 |
| `docs/rules/` | 1 stub | **18 files, 3,486 lines**, every one ≤400 |
The cost of opening the client rules before editing client code went from ~40k tokens to ~5k: 177 lines of
hard rules plus one ~200-line reference file for the area you are in.
### Deviations from the plan, and why
1. **`docs/rules/server/money.md` is a 6th server file**, not in the Outputs tree. `persistence.md` came in
at 456 lines with the money content in it, over the 400-line budget this phase itself sets. Splitting the
money path out is the sanctioned response to overflow, and it is the most-consulted sub-topic on that
side — `persistence.md` is now 382 and `money.md` 244. Both `CLAUDE.md` and `rules/index.md` route to it.
2. **`docs/rules/shared/api-conventions.md` and `money-and-types.md` were not created**, though
`_plan/inventory.md:134135` assigns them owner phase 1. The phase file (lines 3839) says **phase 2 owns
those two contract files** and to read them for cross-check only, and `docs/README.md` puts the wire
contract in `docs/integration/`. The plan file is the more specific and later instruction, so it won.
**Phase 2 must therefore write `docs/integration/api-contract.md`** covering the envelope, status codes,
casing, pagination, idempotency keys, money-on-the-wire, enum codes, PII masking, and the Shamsi
`day_of_week` rule. `docs/rules/index.md` already points there and says so.
3. **`.claude/skills/frontend-designer/SKILL.md` was edited**, which the tree lists as phase 7's. C-11 could
not be resolved without stating precedence *in the skill*, and four of its factual claims were wrong
(R-3…R-5 in [open-contradictions.md](open-contradictions.md)). Only the design-language half was touched;
§8's workflow and §10's Figma section are untouched and still phase 7's.
### Also changed, to keep the tree consistent
- `AGENTS.md` ×3 — repointed at `docs/rules/`; still thin pointers (14 lines each).
- `client/scripts/check-copy.mjs` — its doc comment now names `docs/rules/client/i18n.md` §4 (it never read
`STYLE.md` by path, so the delete was safe; `npm run check` confirms).
- `server/README.md`, `server/.dockerignore` — dropped the `CONVENTIONS.md` references.
- `server/docker-compose.yml`, `client/.env.sample` — two live files still instructed `dotnet user-secrets`.
Neither was on C-1's list. Fixed.
- `docs/README.md``rules/` marked written.
### What the next phases inherit
| Phase | What phase 1 leaves it |
| --- | --- |
| **2** | Write `docs/integration/api-contract.md` (see deviation 2). Fix C-3's remaining half in `api-conventions.md`. The rules tree links to `docs/integration/index.md` and expects it to answer the wire contract. |
| **3** | C-1's one genuinely wrong live doc (`manual-testing-plan.md`) is still open — phase 1 fixed two other files it didn't know about. C-3's RUNBOOK half too. |
| **4** | **Six decisions need folding into `docs/status/decisions.md`** — the C-11 resolution and R-1…R-6, all recorded in [open-contradictions.md](open-contradictions.md) § Resolved, which is currently their only home. Also: `docs/rules/` links to `docs/status/backlog.md` for the 7 mock-blocking REQs and to `docs/status/` as the mock registry's new home. And one drift worth a backlog item: `client/src/services/payment/constants.ts` has `MOCK_PLATFORM_FEE_RATE = 0.12`, while refinement-phase-3 settled the canonical model at 0.15 — mock-only today, but it will lie on a checkout screenshot. |
| **6** | The `dev/`-lane handoff protocol (STATUS.md, `for-backend.md`, per-phase reports, the "save memory" step) was deliberately **not** carried into `docs/rules/` — the parallel-agent chain is finished. Its durable half (contract-first, record every mock) is in `documentation.md`. |
| **7** | Owns the pre-commit warning that enforces `documentation.md` §2, and the rest of the skill. C-12's non-design half is still open. |
### Verification
- [x] `client/CLAUDE.md` 177 lines, `server/CLAUDE.md` 184 — both under 250.
- [x] 20 ledger rules spot-checked for single-home placement; the 6 stale ones are gone from every file.
- [x] No rule describes pre-iteration-1/2 client behaviour (R-1…R-6 rewritten against the code).
- [x] `grep -rn "user-secrets"` over tracked `client/ server/ CLAUDE.md docs/` returns only statements that
it is **not** used (plus `_plan/`'s own descriptions of the contradiction).
- [x] `cd client && npm run check` passes — `check-copy: 2005 strings checked, 0 banned variants found.`
- [x] All 3 `AGENTS.md` resolve; a link check over all 27 new/changed markdown files found 0 broken links.
- [x] C-11 resolved with its decision; C-3 and C-12 marked partly resolved with what remains and to whom.
The Step-1 rule ledger (109 numbered rules across 11 groups, each tagged with source, scope, tier,
destination and state) was scratch by design and is not committed, per the phase brief. Its content is fully
represented in the output files; the six corrections and two count fixes it surfaced are recorded durably in
[open-contradictions.md](open-contradictions.md) § Resolved.
@@ -0,0 +1,280 @@
# Phase 2 — Integration & dependency
**Depends on:** Phase 0 · **Can run in parallel with:** Phase 1 · **Blocks:** Phase 3 · **Size:** one session
## Goal
Make the client↔server dependency a **thing you can read in one place**, and re-sync the contract
layer with the code it stopped tracking on 2026-07-13.
Right now the seam is real but scattered: envelope shape and casing in one contract doc, cookies and
refresh in `client/CLAUDE.md`, CORS in a refinement report, `NEXT_PUBLIC_API_URL` in `.env` files,
the container topology in `DEPLOY.md` and `docker-compose.yml`, and the OTP relay in its own README.
Nobody can answer "what does the client actually need from the server?" without reading six files.
---
## Inputs
- `docs/integration/openapi/swagger.v1.json` — the **fresh** snapshot from Phase 0, plus the
added/removed endpoint diff Phase 0 wrote into `docs/_plan/open-contradictions.md`.
- [dev/contracts/](../../dev/contracts/) — 18 domain files + 2 convention files + the stale snapshot.
- [dev/shared-working-context/frontend/requests/for-backend.md](../../dev/shared-working-context/frontend/requests/for-backend.md) —
67 REQs; many *are* contract amendments that were delivered but never folded back into the domain docs.
- [dev/shared-working-context/reports/mocks-registry.md](../../dev/shared-working-context/reports/mocks-registry.md) — which seams are mocked.
- [DEPLOY.md](../../DEPLOY.md) · [docker-compose.yml](../../docker-compose.yml) · [deploy/Caddyfile](../../deploy/Caddyfile)
- [telegram-otp-bot/README.md](../../telegram-otp-bot/README.md) + [INTEGRATION-PROMPT.md](../../telegram-otp-bot/INTEGRATION-PROMPT.md)
- `client/.env.development`, `client/.env.production`, `server/src/API/Baya.Web.Api/appsettings*.json`
- Code, for the seam itself: `client/src/lib/api/`, `client/src/services/*/`, the server's
`ApiResult` envelope, CORS setup, and auth middleware.
## Outputs
```
docs/integration/
index.md THE seam, one page: what crosses the wire and what each side owes the other
api-contract.md envelope, casing, pagination, errors, idempotency, auth headers/cookies
domains/ 22 files, one per service domain — refreshed against the live swagger
openapi/
swagger.v1.json (from Phase 0)
README.md how to regenerate, when it was last taken, endpoint count
config-matrix.md every env var / appsettings key, both projects + docker + the bot
topology.md the runtime dependency graph
```
Also updated: [DEPLOY.md](../../DEPLOY.md) — fix the stale `user-secrets` reference and link to
`docs/integration/topology.md`. It stays at root and stays the deploy *procedure*.
---
## Steps
### 1. Write `index.md` first — the seam on one page
Before touching the per-domain detail, answer these in one page:
- **Transport**: HTTP/JSON over `NEXT_PUBLIC_API_URL`; where gRPC exists and whether it is used.
- **The envelope**: `ApiResult``{ isSuccess, statusCode, message, requestId, data }`, payload
always under `data`, `requestId` is a W3C trace id (refinement-phase-9). Client unwraps in
`clientFetch`/`unwrap()`.
- **Casing**: JSON bodies camelCase; URL segments snake_case. (REQ-001 settled this — confirm against
the live swagger, don't trust the doc.)
- **Pagination**: `{ items, total, page, pageSize }`; the server binds `pageSize` case-insensitively
(REQ-010).
- **Errors**: status codes, machine-readable error codes (REQ-003), what the client does with 401 /
403 / 5xx / network.
- **Auth**: the cookie set, JWE opacity to the client, silent refresh, session rotation and
reuse-detection, `/me` and `me/select_role`, role hydration.
- **Idempotency**: which endpoints require `Idempotency-Key` and what the client generates.
- **Money**: IRR on the wire, Toman at the UI boundary — link to `docs/rules/shared/`.
- **What the server owes the client** and **what the client owes the server**, as two short lists.
### 2. Refresh the 22 domain contracts against the live swagger
For each domain, compare the contract doc against `swagger.v1.json` and the handler code. Mark each
endpoint: `matches` · `drifted (describe)` · `undocumented (in code, not in contract)` ·
`phantom (in contract, not in code)`.
Fold in the delivered REQs — 17+ were delivered in refinement-phase-3 and amended shapes that the
domain docs still describe the old way. **The domain doc is the thing that should be true; the REQ
ledger is a change log.** After this phase, a reader should never need to read the REQ file to know
the current shape.
Note the domain-file cleanup: there is both a `messaging.md` (851 B stub) and a
`messaging-notifications-admin.md` (10.6 KB) — merge. Align the file set with the client's 22
`services/` domains so the mapping is one-to-one where it can be.
Anything you cannot verify from swagger or code: mark `UNVERIFIED:` and add a row to Phase 4's input
list. Do not guess a shape.
### 3. Write `config-matrix.md`
One table: **key · where it's set (appsettings / .env / docker-compose / Caddyfile) · consumed by ·
required? · default · notes**. Cover at minimum:
- `NEXT_PUBLIC_API_URL`, `NEXT_PUBLIC_NESHAN_KEY`, and the rest of the client's `NEXT_PUBLIC_*`
- `IdentitySettings:SecretKey` / `:Encryptkey`
- `Seams:FieldEncryption:Key` / `:HashKey`**flag as load-bearing and immutable**
- the connection strings (app DB + log DB), and that the DB is remote and **not** containerised
- `OpenTelemetry:Otlp:Endpoint`, the health endpoints (`/healthz/live`, `/healthz/ready`)
- the seam selectors that choose real vendor adapters vs mocks (refinement-phase-8)
- the Telegram OTP bot's token/chat config
- CORS origins, and the Caddy hostnames `balinyaar.ir` / `api.balinyaar.ir`
State plainly, once, that config lives in files and `dotnet user-secrets` is not used — and that this
is a deliberate pre-launch trade with live credentials in git (link to `DEPLOY.md` "Going to
Production" and to Phase 5's `pre-launch.md`).
### 4. Write `topology.md`
The runtime dependency graph — a mermaid diagram plus a short table:
```
browser -> Caddy (caddy_net) -> client container (Next.js) -> server container (ASP.NET)
-> server container -> remote SQL Server (not containerised)
-> telegram-otp-bot (OTP relay)
-> object storage / external rails (per seam config)
```
For each edge: what flows over it, what breaks if it is down, and where it is configured. This is the
"dependency between projects, documented in a proper place" deliverable.
### 5. Point the old locations at the new one
`dev/contracts/README.md` gets a one-line "moved to `docs/integration/`" banner (Phase 6 archives the
folder; until then, don't leave two live copies competing).
---
## Verification
- [ ] Every endpoint in `swagger.v1.json` appears in exactly one `docs/integration/domains/*.md`, or
is listed in that file's "undocumented, intentionally" section with a reason.
- [ ] No `phantom` endpoints remain undeclared — each is either removed from the doc or listed as
"planned, not built" with a backlog reference for Phase 4.
- [ ] `config-matrix.md` accounts for every key in `appsettings.Production.json`,
`docker-compose.yml`, and both `.env` files — diff mechanically, don't eyeball.
- [ ] `DEPLOY.md` no longer instructs anyone to use `user-secrets`.
- [ ] `index.md` fits on one screen-and-a-half and answers the seam question without a single click.
## Definition of done
A frontend agent can build against the API by reading `docs/integration/index.md` plus one domain
file, and a deploy question is answered by `topology.md` + `config-matrix.md` without opening
`docker-compose.yml`.
## Handoff
> Run 2026-07-30 against commit `d3ec723`. **All verification items pass**, checked mechanically
> (script in the session scratchpad, results reproduced below).
### What shipped
```
docs/integration/
index.md 153 lines — the whole seam, one screen and a half
api-contract.md envelope · casing · status codes · auth · pagination · idempotency · money · enums · rate limits
config-matrix.md every key in both appsettings, docker-compose, 3 .env files, the bot, Caddy, CORS
topology.md mermaid graph + a 10-edge table + ports + startup order + the local variant
domains/
index.md the census, the route-shape exceptions, the enum map, what-replaced-what
<22 files> one per client services/ domain, 1:1
openapi/README.md updated: C-9 resolved, the servers-block provenance wrinkle recorded
```
Also updated: `DEPLOY.md` (links topology + config-matrix; states there is no `appsettings.Production.json`
so step 2 of "Going to Production" is a *create*), `docs/README.md` (integration → **written**),
`dev/contracts/README.md` + `openapi/README.md` + `domains/messaging.md` (moved/merged banners).
### Verification
| Item | Result |
| --- | --- |
| Every swagger path declared in exactly one `domains/*.md` | **178/178**, 0 unreferenced, 0 duplicated |
| Operation census adds up | 186 = 184 domain + 2 `ping` in `api-contract.md` |
| Every phantom declared with a reason + REQ | **24/24** |
| `config-matrix.md` accounts for every key | Diffed mechanically; 5 gaps found and written up |
| `DEPLOY.md` no longer instructs `user-secrets` | Pass — it already documented the removal; now also links the new files |
| `index.md` fits a screen and a half | 153 lines |
| Every doc carries a `Last verified` stamp | 27/27 |
| No reference file over 400 lines | Pass |
| Relative links resolve | **216 checked, 0 broken** |
### Scope note
`api-contract.md` was **merged into `index.md`'s siblings as planned**, but the plan's `domains/` count of
22 was met by re-cutting the file set along the **client's** domain boundaries rather than the backend
phases the old 17 files used. That is what makes the mapping 1:1 and is why the file names changed.
`swagger.v1.json` was **not** re-fetched — Phase 0's 2026-07-29 snapshot is 1 day older than this run and
the server was not booted. Everything here is derived from that snapshot plus current source.
---
### Drift list — Phase 4's input
**A. Phantom endpoints (24).** The client's real API clients call 24 routes the server does not expose.
Each is declared in its domain file with its REQ. Grouped by REQ:
| REQ | Status | Phantoms | Domain |
| --- | --- | --- | --- |
| REQ-031 | deferred | 3 (`admin_roles/*`) | admin |
| **REQ-061** | **never filed** | 2 (`admin_users/search`, `/lookup`) | admin |
| REQ-022 | partial | 3 (`checkout_bnpl/options`, `/schedule`, `/wallet_installments`) | bnpl |
| REQ-032 | partial | 5 (`centers/me/*`, `partner-centers/{id}/nurses`) | partner-center |
| REQ-033 | partial | 1 (`centers/me/settlement`) | partner-center |
| REQ-064 | open | 1 (`centers/me/bookings/{id}`) | partner-center |
| REQ-034 | deferred | 3 (`admin_verifications` documents-url / approve / reject) | verification |
| REQ-035 | deferred | 3 (`admin_refunds` preview / approve / reject) | refunds |
| REQ-036 | deferred | 1 (`admin_payouts/{id}/transfer_reference`) | payouts |
| REQ-047 | open | 1 (`bookings/payment_history`) | payment |
| REQ-048 | open | 1 (`refunds/my`) | refunds |
| REQ-063 | open | 1 (`tickets/{id}/assign`) | tickets |
**Two are live 404s** because their domain's mock is off: `bookings/payment_history` (payment) and
`tickets/{id}/assign` (tickets). Both are guarded in the client, so neither is user-visible — but they are
reachable, not hypothetical.
**B. Five REQs whose filed status is wrong or narrower than reality.** Each was checked against the
swagger, not against another document. Phase 4 should re-triage these rather than copy the ledger.
| REQ | Filed as | Actually |
| --- | --- | --- |
| REQ-050 | open — "the list DTO carries neither field" | `BookingRequestListItemDto` **has `variantLabel`** (and `patientAge`). It lacks `variantPrice`/`variantPriceUnit` and the `status=answered` group filter. The REQ was verified against the *client type*, not the wire |
| REQ-063 | open — "no close/reopen/assign routes yet" | `tickets/{id}/close` and `/reopen` **exist and are wired**. Only `assign` is missing. `tickets/constants.ts` carries the stale reason |
| REQ-066 | open — needs an anonymous search read | `GET /search/nurses` **is already anonymous**. What is missing is the rate limit — `SearchController` has no `[EnableRateLimiting]` |
| REQ-067 | open — needs an anonymous profile read | `GET /nurses/{id}/profile` **is already anonymous**. What is missing is the privacy review |
| REQ-029 / REQ-030 | delivered | Correct — but `admin/constants.ts` still names them as reasons the admin mock is primary. The only live reasons are REQ-031 and REQ-061 |
**C. Client-side drifts (client work, not contract work).**
| # | Where | What |
| --- | --- | --- |
| 1 | `client/src/lib/api/types.ts` | `ApiEnvelope<T>` omits **`code`**, which the server sends and `clientFetch` already reads at runtime. Incomplete type, no defect |
| 2 | `client/src/services/admin/apis/clientApi.ts` | `pageQuery()` sends **`page_size`**; these endpoints declare `PageSize`. Model binding is case-insensitive, **not separator-insensitive**, so it binds nothing and every admin list silently gets the default page size. Latent until `USE_ADMIN_MOCK` flips |
| 3 | `client/src/services/bookingRequests/types.ts` | Marks `variantLabel` as client-augmented/absent; the server serves it. Widening the type would light up the redesigned inbox card today |
| 4 | `client/src/services/payouts/apis/clientApi.ts` | Comment says `NursePayoutHistoryDto` has no `failureReason`; **the wire has it** on all three payout read models |
| 5 | `client/src/services/tickets/constants.ts` | Says the backend has no close/reopen/assign; close and reopen exist (B, above) |
| 6 | `client/src/services/payouts/apis/clientApi.ts` | Sends `Idempotency-Key` on `admin_payouts` process/retry, where the server never reads it. Decorative, not harmful |
| 7 | `client/.env.sample` | Still `NEXT_PUBLIC_API_URL = https://localhost:5002` — the `https` half of **C-3**, in the file a fresh clone copies. `.env.development` is correct |
| 8 | `client/src/services/profiles/` | `POST customer_profiles/avatar` exists and is live; the client only wires the nurse route, so a customer cannot set a photo |
**D. Cross-side vocabulary asymmetry (1).** The client's `TicketAuthorRole` includes **`system`**;
`Entities/Messaging/TicketCodes.cs` defines only `customer`/`nurse`/`admin`. Safe on the reading side, but a
reader of the client types would wrongly conclude the server emits it. All other 17 shared vocabularies
match exactly, both directions.
**E. Route-shape exceptions (4).** `admin/partner-centers` (+ `/set-active`, `/sponsor-nurse`),
`admin/tickets`, `admin/reviews/…` and `internal/bookings/…` hardcode route strings instead of using the
`[controller]`/`[action]` tokens; three introduce hyphens, against the snake_case rule. **Because the route
also derives the dynamic-permission key, normalising them breaks permissions as well as URLs** — recorded,
not fixed.
**F. Config gaps (5).** Written up in
[config-matrix.md § What the diff found](../integration/config-matrix.md#what-the-diff-found):
`NEXT_PUBLIC_EVV_MOCK_GPS` and `NEXT_PUBLIC_VERSION` read but declared in no `.env`;
`OpenTelemetry:Otlp:Endpoint`, `Search:Backend` and `Seed:Admin*` read but set nowhere (and a bad
`Search:Backend` **throws at startup**); `.env.sample`'s stale `https`; the Telegram shared secret
duplicated across two files with nothing keeping them equal; no `appsettings.Production.json`.
**G. Unfiled REQ (1).** `ui-phase-11-report.md` records "REQ-061…064 appended" to the ledger. **Only
062/063/064 were.** Ten live client files cite REQ-061 for the admin user directory
(`admin_users/search`, `admin_users/lookup`). Phase 4 must **file it**, not assume it is tracked.
### Contradictions resolved here
**C-6** · **C-7** · **C-8** · **C-9** closed; **C-2** closed as a documentation decision; **C-3**'s
contract-layer half closed. Decisions recorded in
[open-contradictions.md § Resolved](open-contradictions.md#resolved).
### What Phase 3 should know
- The seam facts it needs are settled and mechanically verified: camelCase bodies, snake_case URLs, bearer
header (**not** cookie auth), money as a digit string outbound and an int64 inbound, `Idempotency-Key` on
exactly two endpoints, 20 anonymous operations.
- **`GET /api/v1/dev/last_otp/{phone}` is live on `api.balinyaar.ir`** — the deployment runs as Development
with a capture-safe SMS provider, so both gate conditions hold. Any flow doc that describes logging in
should say this is how you do it today, and that it is the deployment's largest exposure.
- C-4 (the `dev-certs` step) is confirmed dead: the API binds plain HTTP locally, so there is no certificate
to trust. C-5's two bring-up worlds are real and give **different data** — the committed dev config points
at the same remote, already-seeded database the deployment uses.
+272
View File
@@ -0,0 +1,272 @@
# Phase 3 — The flow atlas (verified)
**Depends on:** Phase 0, Phase 2 · **Blocks:** Phase 4 · **Size:** 24 sessions — the biggest phase
## Goal
Build **the one go-to place** that answers, for every flow in the product:
1. What is it, and who does it?
2. **Is it actually implemented — really, or only mocked?**
3. What screens and endpoints does it use?
4. **How do I test it, step by step, with which account?**
5. What's known to be broken or missing?
This is the phase where "verify the load-bearing claims" earns its keep. The existing
[manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) is the closest predecessor and
it is already wrong about bring-up (it tells you to set `user-secrets`, which the code no longer
reads). Copying it forward would reproduce the problem this chain exists to fix.
**Run this phase in slices.** One session does `testing-setup.md` + 46 flows. Later sessions pick up
the next slice. The index table tracks which flows are done.
---
## Inputs
- [dev/post-phase/manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) — flow
walkthroughs, test accounts, the seeded world, the mock-vs-real map, the numbers the UI must respect
- [dev/post-phase/refinement/RUNBOOK.md](../../dev/post-phase/refinement/RUNBOOK.md) — bring-up, demo
accounts, login round-trip, reset, troubleshooting
- [dev/shared-working-context/reports/mocks-registry.md](../../dev/shared-working-context/reports/mocks-registry.md)
- `docs/integration/` — from Phase 2, the endpoint truth
- `product/business/*` — the 14 requirement areas; what "correct" means
- The seeder code (`DemoWorldSeeder`, `DemoLifecycleSeeder`) — **the authority on test accounts and
seeded state**, over any doc
- `client/src/app/[locale]/**` — 83 routes across `(customer)`, `(customer-focused)`, `nurse`,
`admin`, `partner`, `(public-routes)`
- `client/src/services/*/` — 22 domains, each with a mock/real flag
## Outputs
```
docs/flows/
index.md the status table — every flow, one row
testing-setup.md bring-up, accounts, seeded world, OTP, reset, troubleshooting
<flow>.md one per flow (see the candidate list)
```
---
## Candidate flow list
Derived from the route groups, the 22 service domains, and the 14 business areas. Confirm and adjust
in the first session; the point is one file per *user-meaningful journey*, not per screen.
| # | Flow | Actor | Primary routes |
| --- | --- | --- | --- |
| 1 | `auth-login-otp` | all | `(public-routes)/login`, `select-role` |
| 2 | `public-front-door` | guest | `/`, `welcome`, `terms`, `privacy` |
| 3 | `onboarding-customer` | customer | onboarding, account |
| 4 | `care-circle-patients` | customer | patients / care-circle |
| 5 | `addresses-and-map` | customer | addresses, Neshan pin |
| 6 | `onboarding-nurse` | nurse | profile, bank account |
| 7 | `nurse-service-areas` | nurse | coverage, whole-city (`districtId = null`) |
| 8 | `nurse-verification` | nurse + admin | verification journey, document upload, review queue |
| 9 | `nurse-catalog-and-pricing` | nurse | services, variant builder |
| 10 | `search-and-discovery` | customer | C1C3, filters, nurse profile |
| 11 | `booking-request` | customer + nurse | C4/C5, nurse inbox, countdown, accept/reject |
| 12 | `checkout-and-payment` | customer | C6, gateway return, confirmation, escrow |
| 13 | `bnpl-installments` | customer | D1D5 |
| 14 | `booking-lifecycle-evv` | nurse + customer | check-in/out, two-stage clinical gate |
| 15 | `cancellation-and-refunds` | customer + admin | cancel, policy, refund settlement |
| 16 | `reviews` | customer | post-visit review, moderation |
| 17 | `patient-care-records` | nurse + customer | append-only records |
| 18 | `nurse-earnings-and-payouts` | nurse | earnings, weekly payout run |
| 19 | `messaging-tickets` | all | threads, `is_internal` boundary |
| 20 | `notifications` | all | bell, day-grouped list |
| 21 | `admin-backoffice` | admin | config, holidays, audit, RBAC, queues |
| 22 | `partner-center` | partner | the separately-scoped portal |
| 23 | `account-and-settings` | all | profile, theme/language (settings-only since iteration 1) |
---
## Steps
### 1. Write `testing-setup.md` — and **actually boot it**
Do not transcribe RUNBOOK.md. Follow it, note where it is wrong, and write what really happens.
Must cover:
- Prerequisites and the two-terminal run (`dotnet run` + `npm run dev`).
- **Configuration** — the current, correct story: config in `appsettings.*.json` and `.env.*`;
`user-secrets` **is not used and is not read** (`<UserSecretsId>` was removed). The four crypto
values still matter and must match whatever the target DB was encrypted under — booting with
different `Seams:FieldEncryption` keys makes every phone lookup miss and every PII read throw
`Padding is invalid`. Say where they live now.
- **Which database.** The dev config has pointed at a *remote* SQL Server. Confirm the current
target, and give the local-DB alternative.
- **Test accounts** — read them out of the seeder, not the old doc. Note the phone-OTP admins
(`09120000020` super_admin, `09120000021` finance) and what each demo account is set up to
demonstrate.
- **Getting the OTP** — server console (`MOCK SMS — OTP code …`), `GET /api/v1/dev/last_otp/{phone}`,
or the Telegram relay. Note the limits: 120 s resend window, 5 wrong attempts, 60 s validity, and
that the OTP endpoints are IP rate-limited (scripted logins will 429).
- **The seeded world** — what `DemoLifecycleSeeder` builds (the 8-booking world), and the fact that
**time-relative scenarios age out** and need a reseed.
- **Reset** — the drop-and-reseed procedure, verified.
- **Troubleshooting** — the failures you actually hit while doing the above.
### 2. Build the mock-vs-real map — from code
The single most important input to every flow file, and the thing most likely to be stale in the
docs. For each of the 22 client `services/` domains, read the code:
- Is the mock flag on or off?
- If real, does the whole domain hit the API, or only part of it?
- Server-side: which seams are mocked (SMS, payment gateway, BNPL provider, object storage,
geocoder, search) and which have a real adapter available behind config (refinement-phase-8)?
Cross-check `mocks-registry.md` and **correct it** — Phase 0 already flagged that the registry has
had stale rows before. Put the result in `docs/flows/index.md` as a column, and in each flow file as
a header block.
Known suspects from the hardening audit (2026-07-16, never ticked off — verify each against current
code, do not assume): verification fully mocked while catalog/search are real; the refunds mock
reading a retired store; the BNPL wizard on a disconnected store; nurse earnings fabricated despite
live endpoints; `patientRecords` id-type mismatch.
### 3. Write one file per flow
Template — keep each under ~200 lines:
```markdown
# Flow — <name>
> Last verified: <date> against <commit>
**Actor(s):** · **Status:** built | partial | mocked | not started
**Business source:** product/business/NN-….md
## What it does
Two or three sentences. The user's intent, not the implementation.
## Screens
| Step | Route | Component/notes |
## API
| Call | Endpoint | Notes |
Link to docs/integration/domains/<domain>.md — don't restate shapes here.
## Rules that must hold
The load-bearing numbers and invariants, with their product/ source.
(e.g. commission 0.15, VAT 0.10 on commission only; forward-only status;
escrow released after confirmed check-out; whole-city = districtId NULL)
## How to test
1. Log in as <account> (see testing-setup.md)
2.
**Expect:** …
## Known gaps
- [BL-xxx] … (filled by Phase 4; leave a plain list here for now)
```
**Verification standard per flow.** For each, do at least the cheap check — trace the route → service
→ endpoint → handler and confirm the chain is real. For the money flows (1115, 18) and auth (1), do
the expensive check too: run the walkthrough against a booted app. If you cannot run it, mark the
flow's status `UNVERIFIED` in the index and say why — an honest gap beats a confident guess.
### 4. Write `index.md`
The status table, and nothing else of substance:
| Flow | Actor | Status | Client | Server | Verified | File |
| --- | --- | --- | --- | --- | --- | --- |
| booking-request | customer + nurse | built | real | real | 2026-…-… | [link] |
Statuses: `built` (end-to-end real) · `partial` (real but with gaps) · `mocked` (UI real, data fake) ·
`not started`. `Client`/`Server` columns say `real`/`mock` independently — a flow can have a real UI
on a mocked service, which is exactly the trap the hardening audit found.
---
## Verification
- [x] `testing-setup.md` was executed, not transcribed — the API and the client were booted, all 8 demo
accounts logged in over the real phone-OTP round-trip, and a production client build was run to settle
the root-path question. 10 stale instructions in the predecessor docs were found and corrected.
- [x] Every flow file has a status backed by a code trace. The 7 money/auth flows were additionally walked
against the running API by an adversarial second agent. **0 flows are `UNVERIFIED`.**
- [x] The mock-vs-real map was derived from code (22 domains, 153 seam operations; 26 server seams) and
**17 disagreements with `mocks-registry.md` are logged** in `docs/flows/index.md`. That file now
carries a banner pointing at the correction.
- [x] No flow file restates an API shape. 126 links into `docs/integration/` instead; the only JSON block
anywhere is one `request_otp` response in `testing-setup.md`, used as a bring-up example.
- [x] The index accounts for all 22 client service domains, all 14 business areas and all 83 routes. Area
13 (Tax, Invoicing & Legal) is flagged as the weakest coverage and is a Phase 4 item.
- [x] Every flow file carries a `Last verified:` line. 477 relative links checked, 0 broken.
## Definition of done
You can hand someone `docs/flows/testing-setup.md` and `docs/flows/index.md` and they can test the
product without asking you a single question — and without hitting an instruction that no longer works.
## Handoff
**Done 2026-08-02 against `c841bde`, in one session rather than the planned 24 slices.**
### What was produced
`docs/flows/` — 25 files, ~3 500 lines: `index.md`, `testing-setup.md`, and **all 23 flow files**. The
candidate list needed no adjustment; every one turned out to be a real, distinct journey.
**Status spread: 1 `built` · 15 `partial` · 7 `mocked` · 0 `not started` · 0 `UNVERIFIED`.**
Only `auth-login-otp` is end-to-end real and observed working.
### How it was verified
The stack was booted and stayed up throughout. Every flow got the cheap check (route → hook → seam →
endpoint → controller → handler, cited `file:line`). The 7 money/auth flows got the expensive check *twice*:
once by the author, then by an independent adversarial agent told to refute the status claim. That second
pass was worth its cost — it caught a fabricated test count, five wrong `file:line` refs, two factually
wrong gaps, a business-rule citation that asserted the **opposite** of the claim it was supporting, a
fabricated source for a money constant, a self-contradicting headline, and a test step that was false
against the running world. All were corrected in place.
Verification also **mutated the shared demo DB**: booking requests 2124 were created and driven through
accept / reject / cancel / convert to prove those paths work. They carry fresh dates (2026-08-06…08-12) and
are the only non-aged requests in the world.
### The six findings that matter most
1. **The admin backoffice cannot reach its own server.** All 16 admin GET operations `403` for both seeded
admin accounts. `DynamicPermissionService.CanAccess` grants on the literal role `"admin"` or a
per-controller `DynamicPermission` claim; the demo admins hold `super_admin`/`finance`, and **no code
anywhere writes that claim**. `USE_ADMIN_MOCK = true` hides it completely.
2. **34 of 153 client seam operations target routes that do not exist server-side** — they would `404` the
day a flag is flipped. 12 more fabricate or client-derive a value. The flag is not the honesty signal.
3. **No card payment can complete from a browser.** `MockPaymentProvider` redirects to a non-existent host.
The server money path is correct and idempotent; only the last hop is missing.
4. **VAT is computed two different ways on two surfaces** — carved out of the commission at checkout,
added to it on the invoice — differing by 341 IRR on one seeded booking. No `product/` file resolves it.
5. **Booking deadline timestamps ship without a timezone** (`DateTime`, not `DateTimeOffset`), so every
countdown the client renders is wrong by the UTC offset — 3.5 h in Tehran.
6. **The real BNPL rail is dead.** `SeedPaymentGatewaysAsync` seeds only a `Standard` gateway, never a
`Bnpl` one, so `checkout_bnpl/initiate` returns `400 "No active BNPL gateway is configured."` for every
request. The mocked UI hides it entirely.
Plus: the demo world is dated 2026-07-26 and has aged out (no `pending`/`accepted` request survived the
60-second expiry job); `/healthz/ready` is a genuine Windows-only code defect; and a re-login silently
invalidates every token previously issued to that account, so two people cannot share a demo phone.
### Input to Phase 4
**283 gaps** are recorded across the 23 files, each a plain bullet naming what breaks, for whom, and where
in the code. That list plus the 17 `mocks-registry.md` corrections is Phase 4's primary input. No `BL-###`
ids were invented — Phase 4 assigns them.
### What was left undone, and why
- **The local-Docker database path is documented but `UNVERIFIED`** — Docker is not installed on the
verification machine. The remote path was fully exercised instead.
- **The reset/reseed procedure was not executed.** It requires dropping a database shared with the
`balinyaar.ir` demo deployment; that is the owner's call, not a doc-writing side effect.
- **No screen was driven in a browser.** Everything client-side is a code trace plus HTTP-level probing of
the dev and production servers. Where that limits a claim, the file says so.
- **Backend seam rows in `mocks-registry.md` were not re-audited** row-by-row; the current server picture is
the seam table in `docs/flows/index.md` instead.
- `dev/post-phase/manual-testing-plan.md`, `dev/post-phase/refinement/RUNBOOK.md` and
`dev/shared-working-context/reports/mocks-registry.md` now carry supersession banners pointing at
`docs/flows/`. They were otherwise left intact, because `dev/` is history.
+222
View File
@@ -0,0 +1,222 @@
# Phase 4 — Backlog reconciliation
**Depends on:** Phase 0, Phase 3 (and consumes Phase 2's drift list) · **Blocks:** Phase 5 · **Size:** 12 sessions
## Goal
Turn **five unreconciled ledgers plus 50+ scattered "follow-ups" sections** into one triaged backlog
where every open item is real, deduplicated, and carries its origin.
This is the "remaining works from plans, dev, refine and ui phases should be well documented"
deliverable. Today the honest answer to "what's left?" is *nobody knows* — the hardening ledger has
18 items with **zero ticked**, written before three more chains ran on top of it.
---
## Inputs
| Source | Volume | Note |
| --- | --- | --- |
| [dev/post-phase/hardening/issues.md](../../dev/post-phase/hardening/issues.md) | 18 items, **all unticked** | Written 2026-07-16. UI phases 013 and the deploy commits ran after. **Every item must be re-verified against current code.** |
| [dev/shared-working-context/frontend/requests/for-backend.md](../../dev/shared-working-context/frontend/requests/for-backend.md) | 67 REQs, 1,115 lines | Most delivered in refinement-phase-3; some `partially delivered`; REQ-066/067 blocked on a privacy sign-off |
| `dev/shared-working-context/reports/*.md` | 50 files | Each has a "Follow-ups for later phases" / "Deferred" section |
| `dev/shared-working-context/backend/STATUS.md` + `frontend/STATUS.md` | 86 KB | Deferrals recorded with explicit **pull-triggers** (e.g. Elasticsearch `INurseSearch`, SMS/push dispatcher, analytics, holiday feed, 8 unbuilt product tables) |
| [dev/manual-testing/iteration-1/](../../dev/manual-testing/iteration-1/) + [iteration-2/](../../dev/manual-testing/iteration-2/) | 2 raw notes + screenshots | Your own most recent feedback. Some applied in `baa3cc6` / `e6a8f93`; **which parts landed is unknown** |
| [product/notes/open-questions.md](../../product/notes/open-questions.md) | build backlog + research questions | |
| Phase 2's output | drift list | `phantom` and `drifted` endpoints |
| Phase 3's output | gap list | everything found while verifying flows |
| Root [CLAUDE.md](../../CLAUDE.md) §6 | | credential rotation before real users — a real pre-launch item |
## Outputs
```
docs/status/
index.md where the project is, in one page
implemented.md the product/business overlay: 14 areas -> build state
backlog.md BL-### — every open item, triaged
backlog-closed.md items confirmed done, with what closed them
decisions.md the distilled decision log
```
---
## Steps
### 1. Harvest everything into one raw list
One row per candidate item, with its **origin id** (`H-01`, `REQ-042`, `ui-phase-9 follow-up`,
`iteration-2`, `deferral: elasticsearch`, `phase-3 finding`, `phase-2 drift`). Expect 150250 raw
rows before dedup. Do not filter while harvesting.
### 2. Verify each item's current state
This is the phase's real work, and the reason it comes after Phase 3.
- **The 18 hardening items**: re-locate each in the code. The file itself warns that line numbers
drifted. Several are likely fixed by the UI chain — e.g. **H-01** (the auth gate never running,
traced to a stray `pnpm-lock.yaml` and the `middleware.ts``proxy.ts` question) overlaps directly
with what ui-phase-13 did to the root route and matcher. Verify; don't assume either way.
- **The 67 REQs**: classify `delivered` / `partially delivered — what's left` / `open` / `obsolete`.
The ones marked `partially delivered in refinement-phase-3` need the residue spelled out. Once
Phase 2 folded delivered REQs into the domain docs, a delivered REQ is *closed*, not an item.
- **Iterations 1 & 2**: walk each bullet against the code. The clearest testable one:
*"replace all forms with more than 1 field with react-hook-form"* — 28 files import it today;
find the forms that still use raw state and file the residue.
- **Deferrals**: these are not bugs; they are *decisions with pull-triggers*. Keep them as
`deferred`, carry the trigger, and hand them to Phase 5's `roadmap/deferred.md`.
### 3. Dedup and assign `BL-###`
Many items appear in three ledgers. Merge them into one `BL-###` carrying **all** origin ids.
Old ids stay greppable — never rewrite the archived sources.
### 4. Write `backlog.md`
```markdown
> Last verified: <date> against <commit>
| ID | Area | Sev | Item | Origin | Status | Blocks |
|----|------|-----|------|--------|--------|--------|
| BL-001 | client | blocker | … | H-01 | open | flow: auth-login-otp |
```
- **Area**: `client` · `server` · `contract` · `ops` · `product` · `docs`
- **Sev**: `blocker` (product is wrong or unusable) · `major` · `minor` · `deferred`
- **Status**: `open` · `in-progress` · `blocked (on what)` · `deferred (trigger)`
- **Blocks**: the flow(s) from `docs/flows/` it degrades — this is what connects the backlog to
something a user can feel
Sort by severity, then area. Anything closed goes to `backlog-closed.md` with *what* closed it
(commit or phase), so the count of open items is honest at a glance.
### 5. Write `implemented.md` — the product overlay
The agreed alternative to touching `product/`. One row per business area:
| Business area | Doc | State | Flows | Gaps |
| --- | --- | --- | --- | --- |
| 08 Payments & escrow | [product/business/08-…](../../product/business/08-payments-and-escrow.md) | built | checkout-and-payment, cancellation-and-refunds | BL-023 |
States: `built` · `partial` · `mocked` · `not started` · `deferred`. Add the reverse link from each
`docs/flows/*.md` back to its business area. This gives the two-way mapping without editing a single
`product/` file.
Do the same, briefly, for the data model: the STATUS logs mention **8 product tables that were never
built** — name them here rather than leaving them in a status log.
### 6. Write `decisions.md`
The distilled decision log — the highest-value thing buried in 3 MB of reports. Extract every
**non-obvious decision with a reason** and write it as a short ADR-style entry: *what was decided,
when, why, and where it binds*. Candidates already visible in the STATUS logs and memory:
- Commission 0.15 / VAT 0.10 **on commission only** (the canonical fee model, refinement-phase-3)
- `district_id = NULL` means whole-city — in both directions
- Verification `status` is the source of truth; `is_verified` is a guarded flip
- Booking status is forward-only; the three-amount split has a CHECK constraint
- The two-stage clinical-disclosure gate; EVV is **advisory**, never a block
- Webhook idempotency is upsert-first; ledger postings must balance
- Reviews recompute from source; nurse care records are append-only
- `is_internal` ticket messages never appear in user-facing types
- One payout per booking (UNIQUE); whole-clawback greedy netting
- Escrow released after a confirmed check-out; weekly payout generation automatic, processing manual
- Config in files, not a secret store — deliberate pre-launch trade
- Error state is never an empty state (the client convention)
- Root `/` forks by auth via middleware **rewrite**, never redirect
Each entry: 36 lines. Where a decision is already stated in `product/`, link rather than restate —
`product/` wins for business rules; `decisions.md` is for *engineering* decisions and for business
decisions that were made **during** the build and never made it back into `product/`. Anything in the
second category should also get a note in `product/notes/` so the business truth stays complete.
### 7. Write `index.md`
One page: how many flows are built/partial/mocked, how many backlog items are open by severity, the
top five things standing between here and a usable product, and links to everything. This is the page
you open when you come back after two weeks away.
---
## Verification
- [x] Every one of the 18 hardening items has a verdict backed by a code check — none carried over
unexamined. (3 fixed, 4 partially-fixed, 11 open, 0 obsolete — see `backlog-closed.md`/`backlog.md`.)
- [x] Every REQ-001…067 is classified; the count of `open` is explicit. (28 delivered, 1 obsolete, 6
deferred, 2 partially-delivered, 30 open.)
- [x] Every "Follow-ups for later phases" section across the 53 reports was read and harvested. (Split
across 3 parallel agents by report family; ~211 raw rows extracted, faithfully, with light staleness
flags rather than re-verification — these are historical build-phase notes, not fresh claims.)
- [x] Both iteration notes are fully accounted for, bullet by bullet. (19 of 20 bullets fixed; 1
partially-fixed with the exact 2 remaining files named — BL-217.)
- [x] No `BL-###` duplicates another; every one names its origin id(s). (Root-cause consolidation applied
throughout — e.g. the admin-RBAC finding alone carries 18 origin ids into one `BL-001`.)
- [x] Every `blocker` names the flow it blocks.
- [x] `implemented.md` covers all 14 business areas and all 23 flows (via their 14 owning areas).
## Definition of done
"What's left?" is answered by one file, and every number in it was checked rather than inherited. **Met**
`docs/status/index.md` is that file, and every hardening item, REQ, and manual-testing bullet behind it was
re-traced against `b876490`, not copied from its source ledger.
## Handoff
**Done 2026-08-02 against `b876490`, in one session using 10 parallel Sonnet subagents for the harvest.**
### What was produced
`docs/status/``index.md`, `backlog.md` (262 open items), `backlog-closed.md` (88 closed items),
`implemented.md` (14-area product overlay), `decisions.md` (18 distilled ADR-style entries). ~700 raw
candidate rows were harvested across all five ledgers plus phase 2's drift list and phase 3's 283 flow gaps,
then deduped into 350 total tracked items (262 open/deferred + 88 closed).
**Severity spread: 18 blocker · 86 major · 115 minor · 43 deferred.**
### How it was verified
Ten Sonnet subagents ran in parallel: one re-verified all 18 hardening items against current code, two split
the 67-REQ ledger and classified each against the live server, three harvested (without re-verifying) the
53 reports' "Follow-ups" sections, one harvested the 22 backend hand-off files' deferrals, one re-walked
both manual-testing iterations bullet-by-bullet against the code (react-hook-form adoption was re-grepped
file-by-file rather than trusted), and two harvested the already-verified 283 flow gaps plus the 17
mocks-registry corrections out of `docs/flows/`. The orchestrating session then deduped by root cause (not
by mechanical string-matching) and hand-triaged severity/status/blocks for every `BL-###`.
Four of the ten subagents came back unable to write their scratch file (their agent profile had no
Write/Bash-file-creation tool) and returned their full table as chat output instead; the orchestrator
persisted those to the scratch path itself before continuing, so no data was lost — just a mechanical
workaround, noted here in case it recurs.
### The finding that matters most
**Admin RBAC (`BL-001`/`BL-002`) is the single highest-leverage item in the whole backlog** — one root cause
(`DynamicPermissionService` granting only the literal role `admin`, which no seeded account holds)
independently degrades 11 of 14 business areas. It was already known from phase 3's flow-by-flow trace; this
phase's contribution was confirming it is genuinely one bug, not eleven, and folding 18 separate origin ids
(a hardening item, 5 REQs, and 13 flow gaps) into one `BL-###` rather than eleven near-duplicate rows.
Second: five domains are 100% client-mocked while a **working, code-verified server sits behind them**
(verification, refunds, nurse payouts, patient/care records, partner-center) — and three of those five would
*break*, not just show stale data, on a naive flag flip, because the client and server DTO shapes have
independently drifted since the mock was written.
### What was left undone, and why
- **Report follow-ups (~211 rows) were harvested but not individually re-verified against code** — that
would have meant re-running phase 3's entire flow-gap sweep at 10x the scope for marginal new information,
since the overwhelming majority either (a) are already superseded by a later, more current phase report,
confirmed by cross-referencing the later report's own "What was built" section, or (b) restate a deferred
decision that the 22 backend hand-off files already state more precisely with a pull-trigger. Genuinely
new, still-open findings from this pool were promoted into `backlog.md`; the rest are either in
`backlog-closed.md` (confirmed done) or folded into the Deferred section (confirmed intentional).
- **The Deferred section (43 items) is consolidated, not 1:1 with its ~150 raw source rows** — the same
"Redis needed for >1 instance" or "Elasticsearch not MVP" statement recurs verbatim across 3-4 separate
hand-off files; each `BL-###` in that section carries every origin id it absorbed.
- **`product/notes/open-questions.md`'s remaining open items were checked directly** (not delegated) since
the file is 86 lines — rate limiting turned out already built for auth/OTP (only search lacks it, already
tracked as REQ-066/`BL-206`); the ToS/Privacy pages exist but are explicitly commented as placeholder
legal copy pending review (`BL-097`); PWA/Workbox caching is untouched and was marked "maybe" in the
original backlog, so it's carried as `BL-251`, deferred.
- **This phase did not touch `dev/`, `product/`, or any code** — pure reconciliation, as scoped. Phase 6
(archive) is what moves/banners the source ledgers; phase 5 (roadmap) is what turns the Deferred section
into a sequenced plan.
+182
View File
@@ -0,0 +1,182 @@
# Phase 5 — Roadmap & technical requirements
**Depends on:** Phase 4 · **Size:** one session
## Goal
Answer "what next?" — recording every already-decided future item **and** proposing a sequenced
order, with the technical prerequisites each step needs. The ordering is a proposal you can overrule;
the recording is not negotiable.
---
## Inputs
- `docs/status/backlog.md` and `implemented.md` — Phase 4's output, the ground truth
- `docs/flows/index.md` — what's mocked vs built
- The **deferrals with pull-triggers** from the STATUS logs: Elasticsearch `INurseSearch`, real
SMS/push `INotificationDispatcher`, the analytics pipeline, the holiday feed, **8 unbuilt product
tables**, and the refinement-phase-9 items 9.79.11
- [product/notes/future-ideas.md](../../product/notes/future-ideas.md) and
[open-questions.md](../../product/notes/open-questions.md) — including PWA/Workbox caching
- ui-phase-13's follow-ups: **tier (c)** — guest search + public nurse profiles (REQ-066/067), blocked
on a backend phase **and an explicit privacy sign-off on the nurse-profile field list**; the OG
image Persian variant
- Root [CLAUDE.md](../../CLAUDE.md) §6 + [DEPLOY.md](../../DEPLOY.md) "Going to Production" — the
credential-rotation obligation
- `product/business/*` — anything specified but never built
- `product/research/*` — go-to-market, legal landscape (informs sequencing, not scope)
## Outputs
```
docs/roadmap/
index.md the proposed sequence + the reasoning, in one page
next-up.md the next 3-5 units of work, each spec'd enough to start
deferred.md recorded, with the trigger that pulls each one forward
tech-debt.md what must be paid before scale, and what it costs to defer
pre-launch.md the hard gate before real users touch this
```
---
## Steps
### 1. `pre-launch.md` first — it's the one with a deadline
Everything that must be true before a real user with real money uses the platform. Known already:
- **Rotate the committed credentials** and move the secret half out of git. The repo currently
contains live credentials by deliberate pre-launch decision. Note the exception: `Seams:FieldEncryption:Key`
/ `:HashKey` decrypt existing PII and derive the phone-lookup hash — rotating those requires a data
migration, not a config edit. Spell out that migration as its own item.
- **Real external rails** — which seams are still mocked in production config (payment gateway, SMS,
BNPL provider, object storage). Phase 3's mock-vs-real map is the input; this is the list of seams
that must flip.
- **Running as Development in production**`DEPLOY.md` documents this as a deliberate trade.
State what it implies (gRPC reflection, dev endpoints such as `/dev/last_otp`, seeding behaviour,
log verbosity) and what must change.
- Anything Phase 4 marked `blocker`.
- Legal/tax items from `product/business/13-tax-invoicing-and-legal.md` that are code-side.
Each item: what, why it blocks launch, roughly what it takes.
### 2. `deferred.md` — record faithfully, don't re-decide
One row per deferral: **item · why deferred · the pull-trigger (the condition that makes it
necessary) · rough size · where it was decided**. The pull-triggers already exist in the STATUS logs
— preserve them verbatim in substance. A deferral with a trigger is a decision; a deferral without
one is just a forgotten task, so any you find without a trigger, give one.
Include the 8 unbuilt product tables, named individually.
### 3. `tech-debt.md`
Debt is different from backlog: it doesn't block a flow, it raises the cost of everything after it.
Candidates to assess: the single-instance in-process scheduler; search without Elasticsearch; the
absence of E2E tests over the money paths; the remaining raw-state forms; the Windows-generated
client lockfile wrinkle in `DEPLOY.md`; test coverage asymmetry between the two projects.
For each: what it costs now, what it costs at 10× usage, and the trigger to pay it.
### 4. `next-up.md` — the opinionated part
Three to five units of work, each with: goal, why now, what it unblocks, technical prerequisites,
affected flows, rough size, and the backlog ids it closes. Enough that a fresh agent session could
start one without re-deriving the context.
**Sequencing principle to apply, and state explicitly in `index.md`:** the product's own promise is
trust-first and money-holding. So the order is (1) anything that makes a *money or trust* flow lie to
a user, (2) anything that makes a built flow unusable, (3) anything that makes a mocked flow real,
(4) new surface area. Tier (c) guest search is new surface — it ranks below making the authenticated
flows honest, regardless of how visible it is.
Where a proposed item conflicts with something in `product/`, say so and defer to `product/`.
### 5. `index.md`
The one-page sequence: a table of the proposed order with rationale per step, plus the standing
answer to "what are we not doing, and why" (a pointer to `deferred.md`). Mark clearly which parts are
**recorded decisions** and which are **this document's proposal** — the reader must be able to tell
your judgement from the project's.
---
## Verification
- [ ] Every `deferred` item in `docs/status/backlog.md` appears in `deferred.md` with a trigger.
- [ ] Every recorded deferral from the STATUS logs is present, including the 8 unbuilt tables.
- [ ] `pre-launch.md` covers credential rotation, every still-mocked production seam, and the
Development-in-production trade.
- [ ] Every `next-up.md` item names the backlog ids it closes and the flows it affects.
- [ ] Proposal is visibly distinguished from record.
## Definition of done
You can pick the next piece of work in five minutes, and you can explain to someone else why it's
that piece and not another.
## Handoff
**Done 2026-08-02 against `cd8144e`, in one session, single agent (no subagent fan-out needed — the inputs
were five already-triaged status files plus a handful of small product docs, not a fresh harvest).**
### What was produced
`docs/roadmap/``pre-launch.md`, `deferred.md`, `tech-debt.md`, `next-up.md`, `index.md`. All five
verification checklist items pass: every deferred item in `backlog.md` (51 total — the labeled 43 plus 8
more filed by severity elsewhere that also carry deferred status) appears in `deferred.md` with its trigger
preserved in substance; all 8 unbuilt product tables are named individually; `pre-launch.md` covers credential
rotation, all 11 still-mocked production rails, and the Development-in-production trade; every `next-up.md`
unit names the backlog ids it closes and the flows it affects; proposal is labeled apart from record
throughout (index.md marks each claim **recorded** or **this phase's proposal** explicitly).
### How it was verified
Read `backlog.md`, `implemented.md`, `decisions.md`, and `backlog-closed.md` in full (not sampled) since
`next-up.md`/`deferred.md`/`pre-launch.md` all need to cite exact `BL-###` ids. Cross-checked the phase
brief's tech-debt candidates against the actual code rather than restating them: **two turned out overstated.**
"Absence of E2E tests over the money paths" — false as stated; `Baya.Test.Api` and `Baya.Test.Foundation`
carry ~119 test files with real WebApplicationFactory integration coverage over Payments/Bookings/BNPL/
Payouts/Refunds. The real gap, confirmed by grepping for Playwright/Cypress in `client/package.json` (none),
is that nothing automated drives a real browser against a real API — a narrower, more precise claim than the
brief's. "Test coverage asymmetry" — also not a raw-count gap (119 server files vs 125 client files); the
actual asymmetry is that `docs/rules/server/cqrs.md` makes testing mandatory for every new feature while root
`CLAUDE.md`'s client gate is reactive ("if you touched a tested component"). Both corrected in
[tech-debt.md](../roadmap/tech-debt.md) rather than carried forward as-stated. One new debt item was found
and added that the brief didn't name: no OpenAPI→TypeScript codegen pipeline exists (confirmed absent by grep),
which is the mechanism that would have caught the client/server DTO drifts phases 2 and 3 had to discover by
hand.
One deferred item, [BL-245](../status/backlog.md#deferred-43), carried its own trigger — "phase 5 verification
pass" — naming this phase directly. Rather than deferring it again, it was executed: grepped the server for
`SuspendNurse`/`ResolveSupportAlert`/`FlagConcern`. Two of three are real and code-traced
(`ResolveSupportAlert` + `AssignSupportAlert` in `SupportAlertsController.cs`; nurse suspension as
`AdminSuspendVerificationCommand`); only `FlagConcern` is genuinely absent. Corrected in place in `backlog.md`
and logged in `decisions.md`, both outside this phase's own output folder — a deliberate, narrow exception to
"stay in your own phase's files," made because the alternative was knowingly publishing a roadmap that cites
a stale row its own source phase had flagged as needing exactly this check.
### The sequencing call worth flagging
Applying the brief's stated principle (money/trust lies > unusable > mocked→real > new surface) literally
puts admin RBAC ([BL-001](../status/backlog.md#blockers-18)/[BL-002](../status/backlog.md#blockers-18)) third
in `next-up.md`, behind two smaller truth-fixes (nurse-verification status, checkout/payment-window honesty)
— even though RBAC has zero prerequisites of its own and unblocks the most downstream work of anything in the
backlog (11 of 14 business areas). `next-up.md` and `index.md` both say this outright rather than quietly
picking one reading: the ranking follows the letter of the stated principle, and a reader who'd rather
optimize for unlock-radius should run unit 3 first. Two more mocked domains that are just as legitimate as
the four chosen (patient/care-records, partner-center) didn't fit the 3-5 slot cap and are named explicitly
as next-in-line rather than silently dropped.
### What was left undone, and why
- **Patient/care-records and partner-center de-mocks are not among the 5 `next-up.md` units** — both are
real candidates (see above), left out only by the slot cap, not by judgment that they matter less.
- **No code was written or changed** — pure roadmap synthesis, as scoped. The one exception is the BL-245
correction above, which is a fact-check, not a feature.
- **This phase did not re-audit `product/business/*` line by line for "specified but never built" beyond what
`backlog.md`'s Deferred section already carries** — a grep for `DEFERRED` across all 14 business docs
confirmed every theme they name (the 8 tables, holiday/surge pricing, GPS discovery, double-blind reviews,
tiered commission, organizations, etc.) already has a `BL-###` home. Re-deriving that reconciliation from
scratch would have been redoing phase 4's job, not phase 5's.
+159
View File
@@ -0,0 +1,159 @@
# Phase 6 — Archive & prune
**Depends on:** Phases 15 all complete · **Size:** one session
## Goal
Move the 3 MB build-chain history out of the way — **after**, and only after, every live fact in it
has been extracted. Then fix every link that pointed into it.
This phase is mechanical. Its only real risk is running it early, so it has a hard gate.
---
## Gate — do not start until all of these are true
- [ ] Phase 0's `docs/_plan/inventory.md` has a disposition for every file, with no blanks.
- [ ] Phases 1, 2, 3, 4, 5 are marked complete in [`README.md`](README.md)'s progress table.
- [ ] `docs/_plan/open-contradictions.md` has no unresolved rows (or each remaining one is explicitly
accepted with a reason).
- [ ] Every inventory row marked `live facts: yes` has been extracted by its owner phase — check them
off one by one, not in bulk.
If any box is unticked, stop and report which phase is incomplete.
---
## Inputs
- `docs/_plan/inventory.md` — the authority on what moves where
- The whole `dev/` tree
## Outputs
```
archive/
README.md "Historical record. Do NOT treat as instructions."
build-chain/
phases/ was dev/phases (32 executed prompt files + _shared)
working-context/ was dev/shared-working-context (STATUS, handoffs, 50 reports)
contracts/ was dev/contracts (superseded by docs/integration/)
post-phase/ was dev/post-phase (hardening, refinement, server, ui + audits)
manual-testing/ was dev/manual-testing (notes + screenshots)
docs/_plan/ moved to archive/clarify-chain/ at the very end
```
---
## Steps
### 1. Write `archive/README.md` before moving anything
It must say, unambiguously and at the top:
> **This folder is a historical record of how Balinyaar was built. It is not instruction.**
> Nothing here describes current behaviour, current rules, or current plans. Do not follow a
> procedure from this folder. Current truth lives in [`docs/`](../docs/README.md) and
> [`product/`](../product/README.md).
Then: what each subfolder was, the date range it covers, and a table mapping each archived area to
the `docs/` file that superseded it. Someone finding `archive/post-phase/hardening/issues.md` must be
able to see in one step that it became `docs/status/backlog.md`.
### 2. Move, with `git mv`
Preserve history. Move whole directories rather than file-by-file. Keep the screenshots in
`manual-testing/` — they are the only visual record of the pre-overhaul UI.
Delete outright (per Phase 0's inventory): `Prompt.md` (0 bytes), `temp/swagger.json` (stale
duplicate), and the `graphify-out/GRAPH_REPORT.md` files if Phase 0 marked them generated-and-unused.
### 3. Fix inbound links
Every doc outside `archive/` that links into `dev/` must be repointed at its `docs/` successor — not
at the archived copy. Sweep at minimum: root `CLAUDE.md`, `client/CLAUDE.md`, `server/CLAUDE.md`,
`DEPLOY.md`, all three `AGENTS.md`, `product/README.md`, `product/index.md`,
`telegram-otp-bot/README.md`, `.githooks/README.md`, and everything under `docs/`.
Mechanical check:
```bash
grep -rn "](\.\./dev/\|](dev/\|(dev/" --include="*.md" . | grep -v "^./archive/"
```
should return nothing. Do the same sweep for `product/*.html` — the generated view has its own
cross-links, and if any point at `dev/`, fix the **`.md` source** and regenerate
(`cd product && node build-docs.mjs`), never the HTML.
### 4. Update the architecture map
Root `CLAUDE.md`'s "Repository layout" table is canonical for repo structure (its own working
agreement 7). Update it: `dev/` is gone, `docs/` and `archive/` are in, and the sentence describing
`dev/` as the build plan is replaced.
### 5. Update the memory index
`MEMORY.md` has ~50 entries, most of them phase memories whose file paths now point into `archive/`.
Add a single note at its top recording that the build-chain docs moved and where current truth lives,
so a future session doesn't chase dead paths. Don't rewrite 50 memory files.
### 6. Retire this plan
Move `docs/_plan/``archive/clarify-chain/`, and leave one line in `docs/README.md` noting when the
cleanup ran and where its plan lives.
---
## Verification
- [ ] `dev/` no longer exists.
- [ ] The link grep above returns nothing outside `archive/`.
- [ ] `cd product && node build-docs.mjs` runs clean and the regenerated HTML has no `dev/` links.
- [ ] `cd client && npm run check` passes; `cd server && dotnet build Baya.sln` passes — confirming
nothing moved was referenced by tooling.
- [ ] `git status` shows moves as renames, not delete+add.
- [ ] `archive/README.md` maps every archived area to its successor.
## Definition of done
Nothing in the repo tells you to do something that was true three weeks ago, and nothing that was
learned in those three weeks is gone.
## Handoff
Ran 2026-08-02 against commit `e2db973`. Gate re-checked before starting: phases 15 all show **done** in
this file's progress table; `inventory.md` has a disposition for every one of its 275 rows (no blanks);
`open-contradictions.md`'s remaining open rows (C-1, C-3 tail, C-4, C-5, C-10, C-12 tail, C-13, C-14) all
either live in files this phase archives (so the do-not-obey banner resolves them) or are explicitly
deferred to phase 7 (C-12's remaining scope) — none blocked the move. C-15/C-16 were confirmed filed into
`docs/status/backlog.md` and `decisions.md` by phase 4.
**What moved**, all via `git mv` (renames, not delete+add):
- `dev/phases/``archive/build-chain/phases/`
- `dev/shared-working-context/``archive/build-chain/working-context/`
- `dev/contracts/` (incl. the 610 K `openapi/swagger.v1.json`) → `archive/build-chain/contracts/`
- `dev/post-phase/``archive/post-phase/`
- `dev/manual-testing/``archive/manual-testing/`
- `dev/README.md` — content folded into `archive/README.md`'s top-level table rather than kept as a
standalone file (nothing else referenced it directly); removed via `git rm`
- `docs/_plan/``archive/clarify-chain/` (this move, done last)
`Prompt.md` and `temp/swagger.json` were already gone before this phase ran — no delete needed.
`client/graphify-out/` and `server/graphify-out/GRAPH_REPORT.md` are untracked/gitignored tool output per
the inventory; left alone.
**Links fixed** — 9 live docs outside `archive/` and `docs/_plan/` had inbound links into the old `dev/`
paths, all repointed at `archive/build-chain/...` or `archive/post-phase/...`: `CLAUDE.md` (Repository
layout table + the "archive/ does not exist yet" paragraph, now past tense), `docs/README.md` (same, plus
its "Being built" banner and the status/roadmap "not yet written" rows — both phases 4 and 5 are actually
done, so this was corrected in the same pass rather than left stale), `docs/status/backlog.md`,
`docs/status/index.md`, `docs/flows/index.md`, `docs/flows/nurse-earnings-and-payouts.md`,
`docs/flows/cancellation-and-refunds.md`, `docs/flows/testing-setup.md`,
`docs/integration/domains/index.md`, `product/notes/open-questions.md`. `product/*.html` had no `dev/`
links, so no `build-docs.mjs` regeneration was needed. Links **inside** `docs/_plan/*` (now
`archive/clarify-chain/*`) were left pointing at their original `dev/`-relative paths — they're historical
record now, consistent with how the phase prompt files themselves are frozen.
**Verification results:** the link grep (`grep -rn "](\.\./dev/\|](dev/\|(dev/" --include="*.md" .`) returns
nothing outside `archive/`. `dev/` no longer exists. `git status` shows every move as a rename (`R`), not
delete+add. `archive/README.md` maps all six archived areas to their `docs/` successor.
@@ -0,0 +1,125 @@
# Phase 7 — Skills & anti-drift guardrails
**Depends on:** Phase 1 (rules) and Phase 3 (reality) · **Can run before or after Phase 6** · **Size:** one session
## Goal
Two things:
1. **Skills that match reality.** The one existing skill was written before the UI overhaul; parts of
it describe an app that no longer exists.
2. **Guardrails so this doesn't happen again** — the reason the cleanup was needed at all.
**The division of labour, restated:** a *rule* is a constraint that must never break → `docs/rules/`.
A *skill* is a procedure for a recurring task → `.claude/skills/`. If you're writing "always do X",
it's a rule. If you're writing "to do X: first…, then…", it's a skill.
---
## Inputs
- [.claude/skills/frontend-designer/SKILL.md](../../.claude/skills/frontend-designer/SKILL.md) — 21 KB,
10 sections (brand, tokens, typography, component library, layout, icons, hard rules, workflow,
anti-patterns, Figma)
- `docs/rules/` — Phase 1's output, so the skill can stop restating rules and link instead
- `docs/flows/` — Phase 3's output, especially `testing-setup.md` and the mock-vs-real map
- The client code as it is **after** iterations 12
- [.githooks/pre-commit](../../.githooks/pre-commit) (3.4 KB) + [.githooks/README.md](../../.githooks/README.md)
- `client/package.json` scripts (`check`, `lint:copy`, `test:ci`) and the server's build/test commands
## Outputs
```
.claude/skills/
frontend-designer/SKILL.md rewritten against current reality
backend-feature/SKILL.md NEW — adding a feature to the .NET server
flow-testing/SKILL.md NEW — boot, seed, and walk a flow end-to-end
```
Updated: `.githooks/pre-commit`, `docs/rules/documentation.md` (Phase 1 wrote the convention; this
phase adds the enforcement note), and status-doc headers.
---
## Steps
### 1. Rewrite `frontend-designer`
Reality-check every section against the code, then rewrite. Specifically at risk (confirm each):
- **§5 Layout & page shells** — the app is now **mobile-scoped**: a max-width container so the shell
never stretches on desktop, and the nurse side moved from a drawer to a **bottom navigation** with
grouped root pages that summarize their domain. Any desktop-sidebar guidance is obsolete except
where admin still uses one.
- **§6 Icons** — the icon set was replaced wholesale in iteration 1. The old mapping guidance is dead.
- **§2 Design tokens / §3 Typography** — check against the current theme, including the reduced
Paper border-radius.
- **§7 Non-negotiable rules** — most of these are now **rules**, not skill content. Cut them down to
a link into `docs/rules/client/`, keeping only what's design-specific.
- **§1 Brand / §4 Component library** — verify the `App*` inventory against `client/src/components/`
(which currently holds ~40 feature components in addition to the shared kit).
- Add what's missing: **forms are react-hook-form** now, so the "build a form" procedure changes; and
theme/language switches live **only in settings**, not in top bars.
Target: shorter than the current 21 KB, because the rules half moves out.
### 2. Write `backend-feature`
The procedure for adding a feature to the server, derived from how the 199 handlers are actually
shaped: where the command/query goes, the handler and validator, the DTO, the controller action, the
EF configuration and migration, the tests, and the doc updates it must trigger
(`docs/integration/domains/<domain>.md` + the OpenAPI snapshot). Link to `docs/rules/server/` for
constraints; keep the skill to the sequence.
### 3. Write `flow-testing`
The procedure a session follows to actually exercise a flow: boot both sides per
`docs/flows/testing-setup.md`, get an OTP, log in as the right seeded account, walk the flow, and —
importantly — **check the mock-vs-real map first** so a "working" flow isn't just a mock answering.
Include the reseed step for when the time-relative scenarios age out.
### 4. Extend the pre-commit hook
Read the existing hook first and match its style. Add **warnings, not blocks** — a hook that blocks
commits gets bypassed, and then it protects nothing.
Warn when:
- files under `server/src/**/Controllers/**` or `**/Handlers/**` changed but nothing under
`docs/integration/` did → *"API surface changed — update `docs/integration/domains/…` and refresh
the OpenAPI snapshot."*
- `client/src/services/**` changed but no `docs/integration/` or `docs/flows/` change →
*"a service domain changed — does a flow doc need updating?"*
- a file under `docs/status/` or `docs/flows/` is committed with a `Last verified:` date more than
~30 days old → *"this doc claims to be verified as of <date>."*
- root `CLAUDE.md`, `client/CLAUDE.md`, or `server/CLAUDE.md` exceeds its line budget →
*"the rulebook is regrowing; move reference material to `docs/rules/`."*
Document each warning in `.githooks/README.md` and in `docs/rules/documentation.md`.
### 5. Stamp the freshness convention
Ensure every file under `docs/status/` and `docs/flows/` carries
`> Last verified: <date> against <commit>` as its second line, and that
`docs/rules/documentation.md` names exactly which files must carry it and who updates it.
---
## Verification
- [ ] No sentence in `frontend-designer` describes pre-iteration-1/2 behaviour — spot-check the
layout, icon, and form sections against real components.
- [ ] No skill restates a rule that `docs/rules/` owns; each links instead.
- [ ] The three skills' trigger descriptions don't overlap (a task should match exactly one).
- [ ] The pre-commit hook runs and its new warnings fire on a deliberate test commit — and **never**
block one.
- [ ] Every `docs/status/` and `docs/flows/` file has a `Last verified:` line.
## Definition of done
The skills describe the app that exists, and the next time someone changes an endpoint without
touching a doc, something says so.
## Handoff
_(filled in by the agent that runs this phase)_