Files
baya-monorepo/docs/_plan/phase-0-inventory-and-scaffold.md
T
2026-07-29 23:20:46 +03:30

222 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.