making the mess clean plans added
This commit is contained in:
@@ -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 103–421 are a project-structure listing and lines 421–1100 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 sits at [temp/swagger.json](../../temp/swagger.json) (07-06). |
|
||||
| **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 | 1–2 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 | 2–4 sessions | `docs/flows/` — the biggest phase |
|
||||
| 4 | [Backlog reconciliation](phase-4-backlog.md) | 0, 3 | 1–2 sessions | `docs/status/` |
|
||||
| 5 | [Roadmap & tech requirements](phase-5-roadmap.md) | 4 | 1 session | `docs/roadmap/` |
|
||||
| 6 | [Archive & prune](phase-6-archive.md) | 1–5 | 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 | not started | | |
|
||||
| 1 Rules consolidation | not started | | |
|
||||
| 2 Integration & dependency | not started | | |
|
||||
| 3 Flow atlas | not started | | |
|
||||
| 4 Backlog reconciliation | not started | | |
|
||||
| 5 Roadmap | not started | | |
|
||||
| 6 Archive & prune | not started | | |
|
||||
| 7 Skills & guardrails | not started | | |
|
||||
@@ -0,0 +1,148 @@
|
||||
# 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 (1–7) 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) §§1–7**
|
||||
vs **[client/CLAUDE.md](../../client/CLAUDE.md) "Theme System" / "Anti-patterns"** — overlapping, possibly divergent.
|
||||
- **Both** vs **the reality after iterations 1–2** (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 0–13 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
|
||||
|
||||
_(filled in by the agent that runs this phase — file counts, surprises, anything that changes a later
|
||||
phase's scope)_
|
||||
@@ -0,0 +1,175 @@
|
||||
# Phase 1 — Rules consolidation
|
||||
|
||||
**Depends on:** Phase 0 · **Can run in parallel with:** Phase 2 · **Size:** 1–2 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. | ~200–400 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 103–421 are a structure listing, 421+ is reference |
|
||||
| [server/CLAUDE.md](../../server/CLAUDE.md) | 75 KB | 11 sections; lines 89–603 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 1–2 (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 15–25 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
|
||||
|
||||
_(filled in by the agent that runs this phase)_
|
||||
@@ -0,0 +1,149 @@
|
||||
# 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
|
||||
|
||||
_(filled in by the agent that runs this phase — especially: the drift list, since Phase 4 turns the
|
||||
`phantom` and `drifted` rows into backlog items)_
|
||||
@@ -0,0 +1,203 @@
|
||||
# Phase 3 — The flow atlas (verified)
|
||||
|
||||
**Depends on:** Phase 0, Phase 2 · **Blocks:** Phase 4 · **Size:** 2–4 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` + 4–6 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 | C1–C3, 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 | D1–D5 |
|
||||
| 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 (11–15, 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
|
||||
|
||||
- [ ] `testing-setup.md` was executed, not transcribed — the agent booted the API and the client.
|
||||
- [ ] Every flow file has a status backed by a code trace, or an explicit `UNVERIFIED` mark.
|
||||
- [ ] The mock-vs-real map was derived from code and disagreements with `mocks-registry.md` are logged.
|
||||
- [ ] No flow file restates an API shape that `docs/integration/` already owns.
|
||||
- [ ] The index accounts for all 22 client service domains and all 14 business areas — anything with
|
||||
no flow is either intentional or a Phase 4 backlog item.
|
||||
- [ ] Every flow file carries a `Last verified:` line.
|
||||
|
||||
## 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
|
||||
|
||||
_(filled in per slice — which flows are done, which are `UNVERIFIED` and why, and the running list of
|
||||
gaps found, which is Phase 4's primary input)_
|
||||
@@ -0,0 +1,158 @@
|
||||
# Phase 4 — Backlog reconciliation
|
||||
|
||||
**Depends on:** Phase 0, Phase 3 (and consumes Phase 2's drift list) · **Blocks:** Phase 5 · **Size:** 1–2 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 0–13 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 150–250 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: 3–6 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
|
||||
|
||||
- [ ] Every one of the 18 hardening items has a verdict backed by a code check — none carried over
|
||||
unexamined.
|
||||
- [ ] Every REQ-001…067 is classified; the count of `open` is explicit.
|
||||
- [ ] Every "Follow-ups for later phases" section across the 50 reports was read and harvested.
|
||||
- [ ] Both iteration notes are fully accounted for, bullet by bullet.
|
||||
- [ ] No `BL-###` duplicates another; every one names its origin id(s).
|
||||
- [ ] Every `blocker` names the flow it blocks.
|
||||
- [ ] `implemented.md` covers all 14 business areas and all 23 flows.
|
||||
|
||||
## Definition of done
|
||||
|
||||
"What's left?" is answered by one file, and every number in it was checked rather than inherited.
|
||||
|
||||
## Handoff
|
||||
|
||||
_(filled in by the agent that runs this phase — item counts by severity, and anything that turned out
|
||||
to be worse than the old ledgers claimed)_
|
||||
@@ -0,0 +1,121 @@
|
||||
# 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.7–9.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
|
||||
|
||||
_(filled in by the agent that runs this phase)_
|
||||
@@ -0,0 +1,124 @@
|
||||
# Phase 6 — Archive & prune
|
||||
|
||||
**Depends on:** Phases 1–5 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
|
||||
|
||||
_(filled in by the agent that runs this phase)_
|
||||
@@ -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 1–2
|
||||
- [.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)_
|
||||
Reference in New Issue
Block a user