8.5 KiB
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 | 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 | 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/ + 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 | 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 §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.yamland themiddleware.ts→proxy.tsquestion) 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 markedpartially delivered in refinement-phase-3need 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'sroadmap/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
> 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-… | 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 = NULLmeans whole-city — in both directions- Verification
statusis the source of truth;is_verifiedis 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_internalticket 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
openis 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
blockernames the flow it blocks. implemented.mdcovers 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)