# Session 26 — 2026-05-21 — PE List tree view UI iteration + RAG Global MCP setup

**Dev:** Claude (em main + 4 sub-agents Investigator/Implementer/Reviewer/CICD Monitor) + bro pqhuy
**Duration:** ~5h (start ~17:00 → end ~22:00 GMT+7)
**Base commit:** `506cada` (S25 chốt cuối Plan AF)
**Final commits cumulative:** `0bf6c7e..d99069a` (6 commits Plan AG series push remote)
**+ Infrastructure:** `D:\.claude-rag\` RAG global server setup (out-of-tree, không commit)

---

## 🎯 Làm được

### Plan AG series — PE List tree view UI iteration (UAT bro Tra Sol)

#### Plan AG (`0bf6c7e`) — Phase 1 tree view 2-level Project > Gói thầu > PE

Trigger UAT 2026-05-21 screenshot bro Tra Sol + anh Kenny: UI Duyệt NCC PE List "đám rừng" flat list + đề xuất "khoanh sẵn thư mục gói thầu như mail".

🟦 **Investigator audit 5Q** (~30K spawn) confirm: Project entity ready Phase 2 ProjectPackage table, PE.TenGoiThau text free-form (variation risk), shadcn fe-user thiếu Accordion/Collapsible (fallback HTML `<details>/<summary>` native), Mig 31 stable, Phase 2 naming `AddProjectPackageTable`.

🟨 **Implementer Case 2 cookie-cutter mirror 2 app** (~16K spawn) deliver:
- Chunk A useMemo group nested `ProjectGroup{goiThauList[]}` + sort vi locale + fallback "(Dự án đã xoá)" + "(Chưa phân loại)"
- Chunk B UI `<details>/<summary>` HTML native 2-level + Tailwind named groups `group/proj` + `group/gt` chevron rotation + `[&::-webkit-details-marker]:hidden`
- Chunk C localStorage Set<string> persist key `pe_list_expanded_groups`

🟥 **Reviewer pre-commit** (~25K spawn) verify 5-category + 12 adversarial deep checks PASS 0 blocker.

🟩 **CICD Monitor Run #222** (~12K spawn) bundle hash 2 app rotated `C8TvDy7r→CWHIdoFo` admin + `BvcWrq2z→Bg2FNeIz` user. Stage 4c API shape preserved.

#### Plan AG2 (`c5429c0`) — Simplify 1-level + widen Panel 1

Bro feedback "Plan AG 2-level cầu kỳ quá, gói thầu thì ko cần thiết phải treedow". Em main solo refactor:
- Drop `GoiThauGroup` nested type
- useMemo group 1-level: `Map<projectId, ProjectGroup{items[]}>`
- Panel 1 widen `lg:grid-cols-[340px_1fr_360px]` → `[400px_1fr_360px]`
- Single PE project → flat card (no `<details>`); Multi PE → tree
- localStorage key rename `pe_list_expanded_projects`

#### Plan AG3 (`fbad4a9`) — Drop single-PE flat consistent UI

Bro screenshot follow-up "nếu có 1 thì cũng để tương tự luôn nhé, đừng để khác các thằng kia". Em main solo drop `if (pg.items.length === 1)` branch → mọi dự án dù 1/N phiếu đều render `<details>` folder collapsed. Diff -110 LOC (clean).

#### Plan AG4 (`2bf0118`) — BE+FE bổ sung Drafter + Department

Bro feedback "bổ sung thêm người tạo + phòng ban tạo vào danh sách phiếu". Em main solo cross-stack:

**BE 4 file:**
- `PurchaseEvaluationDtos.cs` DTO +4 fields `DrafterUserId/DrafterName/DepartmentId/DepartmentName`
- `PurchaseEvaluationFeatures.cs` ListHandler + InboxHandler projections JOIN Users + Departments LEFT (cả 2 nullable theo PE entity)
- `CreateContractFromEvaluationFeatures.cs` ApprovedHandler mirror JOIN

**FE 4 file × 2 app mirror §3.9:**
- `types/purchaseEvaluation.ts` PeListItem +4 fields
- `PurchaseEvaluationsListPage.tsx` PE card row render `👤 {drafterName} · {departmentName}` giữa Mã phiếu và Supplier

Verify: `dotnet test SolutionErp.slnx` 111/111 PASS unchanged. `npm build` × 2 app clean 0 TS err.

#### Plan AG5 (`083b601`) — Extend tree 3-level Project > Năm > NCC > PE

Bro chốt "Folder cấp dưới dự án là theo năm và dưới năm là theo NCC nhé". Em main solo refactor:
- `type SupplierGroup{supplierId, supplierName, items[]}` (italic "(Chưa chọn NCC)" cho PE chưa DaDuyet)
- `type YearGroup{year, suppliers[], totalCount}` extract `new Date(p.createdAt).getFullYear()`
- `type ProjectGroup{projectId, projectName, years[], totalCount}`
- 3 cấp nested `<details>` với Tailwind named groups `group/proj` + `group/year` + `group/sup`
- Sort: Project A-Z vi · Year DESC · NCC A-Z vi · PE createdAt DESC
- localStorage 3-level key format `projectId / projectId::y{year} / projectId::y{year}::s{supplierId}`

#### Plan AG6 (`d99069a`) — Compact card 3-row gọn đẹp

Bro feedback "Cho thông tin bên trong này nó gọn đẹp lại nhé". Em main solo:
- `py-2.5` → `py-2` (compact vertical padding)
- Drop Type label "Duyệt NCC" badge (redundant với page header)
- Combine row mã phiếu + time `PE/2026/A/035 · 10:40 19/05/2026`
- Combine row drafter + department + contract `👤 Drafter · Phòng ban   [✓ HĐ]` (conditional)
- Separator `slate-300` nhẹ hơn để mắt không bị rối

### Plan AI — RAG User-level Global MCP setup (Approach A)

Bro plan setup RAG cho 5 dự án cùng máy localhost share infrastructure. Em main + Investigator deep research 4 study cases (Cursor + Cline + Continue + Sourcegraph) → kết luận User-level Global MCP pattern (1 dev N project, không phải team VPS pattern).

#### Phase 0 — Pre-flight check (15 phút)

✅ Python 3.11.3 OK · ✅ Docker installed nhưng SKIP per bro chốt no Docker · ❌ VOYAGE_API_KEY chưa set → bro set User scope length 46 prefix pa-Mi... · ✅ Disk D:\\ 32GB free (acceptable) · ✅ pip packages install fastmcp 3.3.1 + voyageai 0.3.7 + qdrant-client 1.18.0 + watchdog 6.0.0 + chromadb 1.5.9 (bonus) + python-dotenv 1.2.2.

#### Phase 1 — Qdrant Windows native binary (30 phút)

Bro chốt KHÔNG Docker → em verify Qdrant GitHub releases qua WebFetch:
- ✅ Qdrant v1.18.0 (released 2026-05-11) **CÓ Windows native binary** `qdrant-x86_64-pc-windows-msvc.zip` 28.3 MB chính thức
- Download + extract `D:\.claude-rag\qdrant-bin\qdrant.exe`
- Tạo config.yaml: storage_path `D:\.claude-rag\data\qdrant-storage`, http_port 6333, on_disk_payload true, telemetry_disabled true
- Start background hidden: PID 67240, health check 200 "healthz check passed"

#### Phase 2 — FastMCP server code ~1100 LOC Python 9 file

```
D:\.claude-rag\
├── server.py (210 LOC) — FastMCP entry + 6 tool handlers
├── bootstrap.py (150 LOC) — initial corpus embed CLI
├── README.md
└── lib/
    ├── __init__.py
    ├── projects.py (140 LOC) — auto-detect cwd → project_id từ .claude/rag.json + registry tracking
    ├── chunking.py (120 LOC) — Markdown chunking + Anthropic Contextual Retrieval prepend "From <doc> > <heading>:"
    ├── embed.py (140 LOC) — Voyage AI wrapper (embed + rerank + retry exponential backoff + SHA256 cache)
    ├── retrieval.py (230 LOC) — 3-layer pipeline (Vector Qdrant + BM25 SQLite FTS5 + RRF k=60 + Voyage rerank-2.5)
    └── watcher.py (100 LOC) — Watchdog file watcher với debounce 2s
```

**6 MCP tools exposed:**
- `search_memory(query, scope, top_k, use_rerank)` — current project + shared_global hybrid search
- `cross_project_search(query, top_k)` — search ALL registered project collections
- `search_code(query, file_pattern, top_k)` — BM25-heavy code symbol search
- `store_memory(content, source_path, tags)` — add on-the-fly memory chunk
- `promote_to_shared(chunk_id)` — promote project-local → shared_global (v0 stub)
- `list_projects()` — registry overview + Qdrant collection stats

#### Phase 3 — Register MCP user-level (15 phút trial 5 lần)

**Trick CLI `claude mcp add` syntax:** `-e KEY=VAL` flag là variadic — phải có `--` separator ngay sau env list trước `<name>` để terminate parsing.

Final command working:
```bash
claude mcp add -s user -e "VOYAGE_API_KEY=$VK" -- rag-unified python "D:\.claude-rag\server.py"
```

Output: `rag-unified: python D:\.claude-rag\server.py - ✓ Connected`.

#### Phase 4 — Bootstrap SOLUTION_ERP corpus (5 phút)

`.claude/rag.json` ở SOLUTION_ERP project root:
```json
{
  "project_id": "solution_erp",
  "display_name": "SOLUTION_ERP — Quản lý HĐ NCC",
  "corpus_paths": ["docs/**/*.md", ".claude/agent-memory/**/MEMORY.md", ".claude/skills/**/SKILL.md"],
  "extra_corpus": ["C:\\Users\\pqhuy\\.claude\\projects\\D--Dropbox-CONG-VIEC-SOLUTION\\memory\\*.md"],
  "share_to_global": true,
  "search_scope_default": ["self", "shared_global"],
  "contextual_retrieval": true
}
```

Bootstrap output:
```
[1/4] Scanning corpus... Found 126 files
[2/4] Chunking + contextual prepend... Total chunks: 2392
      Estimated tokens: ~484,508 (Voyage free tier: 200M/month)
[3/4] Voyage-4-large embedding + Qdrant upsert + SQLite BM25... Upserted 2392 chunks in 60.9s
[4/4] Update registry...
✓ Bootstrap complete: solution_erp ready (2392 chunks)
```

### Bonus: File MD onboarding guide xuất

`docs/guides/multi-agent-setup-guide.md` (~750 lines markdown) — full guide cho 1 master README + 4 agent definition templates + MEMORY.md seed cho dự án mới. Bro paste vào dự án mới (NamGroup/DH Y Dược/Ashico/Vipix detected từ Claude Desktop config epitaxy) để setup 4 sub-agent + RAG infra.

---

## E2E verified

### Plan AG series verify

| Plan | Commit | BE test | FE build × 2 | SHA256 mirror | CICD Run |
|---|---|---|---|---|---|
| AG | `0bf6c7e` | 111/111 PASS unchanged | PASS 0 TS err | ✅ `21001E90...` | #222 PASS bundle rotate |
| AG2 | `c5429c0` | 111/111 unchanged | PASS | ✅ `37520D01...` | Run #223 PASS (em main verify) |
| AG3 | `fbad4a9` | 111/111 unchanged | PASS | ✅ `749FF703...` | Run #224 PASS |
| AG4 | `2bf0118` | **111/111 PASS** dotnet test verify cross-stack | PASS | ✅ verified | Run #225 PASS |
| AG5 | `083b601` | 111/111 unchanged | PASS | ✅ `E5FE4979...` | Run #226 PASS |
| AG6 | `d99069a` | 111/111 unchanged | PASS | ✅ `3645307C...` | Run #227 PASS |

### Plan AI RAG verify 4 query thực tế

```
Query 1: "gotcha 45 PE button TraLai mismatch"  → rerank 0.641 (Reviewer MEMORY Plan AB)
Query 2: "pattern admin opt-in per-NV flag"     → rerank 0.836 (Session 23 t1 Plan K)
Query 3: "EF migration backfill SQL reorder"    → rerank 0.766 (Session 21 t5 Refactor Allow)
Query 4: "multi-agent setup 4 sub-agents"       → rerank 0.879 (Session 21 t1 cicd-monitor + new guide)
```

---

## 🐛 Bug gặp + fix

| Bug | Fix |
|---|---|
| Bash shell không inherit User-scope env var từ PowerShell parent | Workaround: `VK=$(powershell -NoProfile -Command "...")` mỗi Bash command + `export VOYAGE_API_KEY="$VK"` |
| `claude mcp add -e KEY=VAL` 5 lần FAIL "Invalid environment variable format: rag-unified" | Trick: thêm `--` separator ngay sau env list trước `<name>` để terminate variadic `-e` flag |
| Qdrant upsert 2392 chunks batch lớn FAIL WinError 10053 "connection aborted host machine" | Batching 64 chunks/upsert + `wait=True` trong `lib/retrieval.py:UPSERT_BATCH` |
| SQLite FTS5 `sqlite3.OperationalError: no such column: in` cho query có dấu `-` ("opt-in") | `_sanitize_fts5_query()` strip non-alphanumeric + quote token-by-token `f'"{t}"'` + fallback empty result trên OperationalError |
| HuggingFace symlinks warning Windows non-developer mode | Non-critical (cache work OK degraded efficiency) — note `HF_HUB_DISABLE_SYMLINKS_WARNING=1` env var optional suppress |

---

## 📚 Docs updates

| File | Update |
|---|---|
| `docs/STATUS.md` | Last updated S26 chốt cuối (cumulative wrap 6 plan AG series + Plan AI Phase 0-4) |
| `docs/HANDOFF.md` | TL;DR S26 chốt cuối với 3 patterns NEW reusable cross-project |
| `docs/changelog/sessions/2026-05-21-s26-pe-tree-view-rag-setup.md` | File này — session log đầy đủ |
| `docs/guides/multi-agent-setup-guide.md` | NEW ~750 lines, onboarding 4 dự án future |
| `.claude/agent-memory/investigator/MEMORY.md` | +2 entry S26 (Plan AG audit 5Q + Plan AI RAG research 4 study cases) |
| `.claude/agent-memory/implementer/MEMORY.md` | +1 entry S26 (Plan AG Chunk A+B+C + Pattern 19 HTML details + Tailwind named groups + localStorage Set) |
| `.claude/agent-memory/reviewer/MEMORY.md` | +1 entry S26 (Plan AG pre-commit PASS 0 blocker + 5 polish em main solo self-review) |
| `.claude/agent-memory/cicd-monitor/MEMORY.md` | +1 entry S26 (Run #222 verify + Run #223-#227 em main self-verify pattern). Memory ~74KB CRITICAL CURATE next |
| Memory user-level `feedback_rag_hybrid_pattern.md` | Update section "Implementation actual achievements S26" với stack chốt + Phase 0-4 + 7 bài học extra |
| Memory user-level `MEMORY.md` index | Update entry RAG Hybrid với stack mới Voyage-4-large + rerank-2.5 + Qdrant Windows native |

---

## 🤝 Handoff S27+

### Pending priority HIGH

1. **Memory CRITICAL CURATE** 4 agent — cicd-monitor 74KB OVER 50KB hard threshold (archive Run #186-#221 verbose → `archive/2026-05-runs.md`)
2. **Plan AI Phase 5 bootstrap 4 project còn lại** (NamGroup + DH Y Dược + Ashico + Vipix) — ~30 phút/project, copy `.claude/rag.json` template + bootstrap.py CLI
3. **Plan B Contract V2 wire** (defer carryover từ S25) — mirror PE Mig 22-23 pattern proven 1× S17 + Investigator/Implementer Case 2 pre-allocated

### Pending priority MEDIUM

4. **Plan AI Phase 6** file watcher real-time auto re-embed + Windows Task Scheduler auto-start Qdrant khi boot
5. **Xuất `rag-onboarding-guide.md`** cho 4 project khác paste config (defer sau Phase 5 ổn 1-2 tuần UAT)
6. **Test debt catch-up Plan C bundle** (S22+1 + S25 + S26 bug fix chưa add regression test — UAT mode defer per §7)

### Pending priority LOW

7. Benchmark RAG recall@10 golden dataset 100 query thật (gap optional)
8. Disaster recovery weekly backup Qdrant data → Dropbox (gap optional)
9. Gotcha #48 SQLite tie-break + #49 dual-phase UI confusion add `docs/gotchas.md` (carry từ S25)

---

## 📊 Thông số cumulative S26

| Metric | S25 chốt | S26 chốt | Δ |
|---|---|---|---|
| DB tables | 59 | 59 | 0 |
| Migrations | 31 | 31 | 0 (no schema change) |
| Endpoints | ~146 | ~146 | 0 (same shape, +4 fields DTO ListItem) |
| FE pages | 35 | 35 | 0 (logic enhanced PE List) |
| Unit tests | 111 | 111 | 0 (UAT mode defer per §7) |
| Gotchas | 49 | 49 | 0 |
| Memory user-level | 23 | 23 | 0 (RAG entry updated stack mới) |
| Skills project-local | 6 | 6 | 0 |
| Sub-agents | 4 | 4 | 0 (5 spawn S26: Inv 2 + Imp 1 + Rev 1 + CICD 1) |
| Commits remote | `e23f51c..506cada` | `e23f51c..d99069a` | **+6** (`0bf6c7e..d99069a`) |
| Docs files | — | +1 | `multi-agent-setup-guide.md` |
| Infrastructure | — | +1 | `D:\.claude-rag\` RAG global (out-of-tree) |
| RAG corpus indexed | 0 | **2,392 chunks** | SOLUTION_ERP bootstrap |
| Voyage tokens used | 0 | ~484K | 0.24% free tier 200M/month |

### Multi-agent ROI S26

| Agent | Spawn | Token cost | Catch |
|---|---|---|---|
| 🟦 Investigator | 2× | ~70K | Plan AG audit 5Q + Plan AI RAG distribution research 4 study cases |
| 🟨 Implementer | 1× | ~16K | Plan AG Case 2 cookie-cutter mirror 2 app + Pattern 19 NEW |
| 🟥 Reviewer | 1× | ~25K | Plan AG pre-commit PASS 0 blocker + 5 polish em main solo verified |
| 🟩 CICD Monitor | 1× | ~12K | Run #222 PASS bundle hash 2 app rotate verified |
| 👤 Em main solo | continuous | ~280K (estimate) | Plan AG2-AG6 polish iteration + Plan AI Phase 0-4 setup + docs/MD writes |
| **Total** | **5 spawn** | **~403K** | ~28% solo equivalent — ROI tốt cho heavy session |
