12 KiB
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:
- 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.
- 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— 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/*anddev/phases/frontend/*(32 files, ~1 MB): these are prompts that were already executed. Dispositionarchive. But scan each for decisions and constraints stated in the prompt that are not visible in the code — those arelive facts: yesand 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.mdimplemented.md), thenarchive.
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) thenarchive(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-isat root (it is the deploy procedure and it is current) — but Phase 2 fixes its staleuser-secretsreference and Phase 2'stopology.mdlinks 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. Decidekeep-as-isif the tool is still used, elsedelete; check.gitignorefirst.
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-secretsis required (18 files) vsuser-secretswas removed and the store isn't read (root CLAUDE.md §6, commit5885280).dev/contracts/describes the API (frozen 2026-07-13) vsserver/src(through 2026-07-28).- Design language in .claude/skills/frontend-designer/SKILL.md §§1–7 vs 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:
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. 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.mdhas a row for every.mdfile the survey walked; the count matchesfind . -name "*.md" -not -path "./node_modules/*" … | wc -l(~260 at baseline).- No row has an empty
dispositionorowner phase. - Every row with
live facts: yesnames the phase that will extract them. docs/integration/openapi/swagger.v1.jsonexists and its endpoint count is recorded.- Every stub index exists and says which phase fills it.
- Nothing outside
docs/was modified, except deletingPrompt.mdandtemp/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 |
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
-
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-writtendomains/*.mdinstead — that is where drift can hide, and nothing has ever checked them mechanically. -
Phase 3 fixes one stale bring-up doc, not two. The plan says
manual-testing-plan.mdandRUNBOOK.mdare both stale on secrets.RUNBOOK.mdwas updated in5885280and is correct — it even has a troubleshooting row for the error you now get. Onlymanual-testing-plan.md(last commitbd06ef0, the day before) still instructsdotnet 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 ishttp://, nothttps://, in ~18 places; thedev-certsstep is therefore dead; andRUNBOOK.mdbuilds 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. -
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 coversAppFrame,BottomBar,APP_FRAME_MAX_WIDTHand the Lucide-only registry. It is stale by exactly one iteration:client/CLAUDE.mdwas updated ate6a8f93(manual improvement 2), which changed 44 files, +3419/−2449 underclient/src. Diff against iteration 2, not against the whole overhaul. -
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.jsonwas never committed —.gitignore:1ignorestemp. Deleting it removed local clutter, not repo content. The_plan/README.mddiagnosis 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 amendsmessaging-notifications-admin.md. Phase 2 should merge, not move both (C-8).SET_VIA_USER_SECRETS_OR_ENVis still the placeholder string inappsettings.jsonand is enforced byStartupSecretsGuardand 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}/anddocs/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, andcurlto localhost returns 502 unless you pass--noproxy '*'.
Contradictions
14 logged in open-contradictions.md, including a corrections section covering the three seeded claims that did not reproduce as stated. Phase 0 resolved none, by design.