CICD: **PARTIAL — vòng 2: 8/9 check** — SHIP THÀNH CÔNG TRỌN (run #486 success · gate **680 EXACT** · bundle rotate ×2 · marker **10/10**) ⟂ **1 FAIL: A/059 latency 6/16 mẫu > 3 s (max 8,75 s)**, gốc đo được = **RAM 4 GB bị ép / buffer pool SQL 213 MB**, KHÔNG phải code (commit 0 file BE). _(vòng 1 = FAIL 8/11: Gitea không tạo run)_

# sub-cicd-monitor — YC-028 `92d8215a` (S189)

> ARTIFACT-FIRST. Ghi từng mục NGAY khi có bằng chứng. Dòng-1 lật thành `PASS|FAIL — n/n` ở cuối.

## Stage 1 — Push + path filter

- HEAD = `92d8215a6253d749794ca7551b5f0bc453ab08e9`
- Subject: `[CLAUDE] PurchaseEvaluation: YC-028 sự cố prod A/059 — FE tách "404 thật ⟂ lỗi hệ thống" 5 site ×2 app + guard disk/orphan vào runbook+cicd-monitor`
- Commit time: `2026-08-11 11:25:51 +0700`
- `git log origin/main..HEAD` = **RỖNG** ⇒ push đã land.
- `git diff --name-only 9b3c0edb..92d8215a` = **12 file**:
  - FE deploy được (8): `fe-{admin,user}/src/lib/apiError.ts` · `…/src/pages/pe/PurchaseEvaluationsListPage.tsx` · `…/src/pages/khkk/KhkkListPage.tsx` · `…/src/pages/khkk/KhkkCreatePage.tsx`
  - KHÔNG deploy (4): `.claude/WAL.md` · `.claude/agents/cicd-monitor.md` · `.claude/skills/iis-deploy-runbook/SKILL.md` · `docs/governance/so-yeu-cau-chu-du-an.md`
- Path filter 7-glob (`docs/**`,`**/*.md`,`.claude/skills/**`,`.claude/agent-memory/**`,`.claude/workflows/runs/**`,`.gitignore`,`scripts/**.md`): 8 file `fe-*/src/**.{ts,tsx}` KHÔNG khớp glob nào ⇒ **CI PHẢI CHẠY** (không docs-only). ✅

**Stage 1 = PASS.**

## Stage 1b — Disk-free VPS (BƯỚC MỚI, lần chạy đầu tiên)

`ssh vietreport-vps "fsutil volume diskfree C:"` (KHÔNG dùng `| head` — luật S189):

```
Total free bytes                : 30,878,273,536 (  28.8 GB)
Total bytes                     : 58,948,841,472 (  54.9 GB)
Used bytes                      : 27,012,255,744 (  25.2 GB)
```

- Free = **28.8 GB** ≫ ngưỡng 5 GB. ✅ (sự cố YC-028 hôm qua: 0 byte ⇒ SQL Error -2)

**Stage 1b = PASS.**

## Stage 2 — PRE snapshot (chụp TRƯỚC khi deploy land)

Đo live lúc ~11:2x, trước khi CI xong:

| App | JS | CSS |
|---|---|---|
| admin | `index-BZ1PG34E.js` | `index-DVHtHLex.css` |
| eoffice | `index-0ObPwWFB.js` | `index-Ibv3QD_1.css` |

**Control âm + control DƯƠNG trên bundle PRE** (tải nguyên file, đếm byte UTF-8 bằng python `bytes.count`, KHÔNG `grep -P` — locale Git-Bash giết `-P`):

| Bundle | size | `Không tìm thấy phiếu` (control DƯƠNG) | `Hệ thống đang chậm hoặc lỗi khi tải phiếu` (marker) |
|---|---|---|---|
| admin `BZ1PG34E.js` | 1.813.772 B, `application/javascript` | **5** | **0** |
| eoffice `0ObPwWFB.js` | 1.728.765 B, `application/javascript` | **6** | **0** |

⇒ thước SỐNG (control dương bắt được chuỗi tiếng Việt trong bundle) ⇒ marker 0-hit = **vắng THẬT**, không phải hỏng phép đo.
Nguồn marker: `grep -rn` ra **5 site/app** (`KhkkCreatePage:252` · `KhkkListPage:240` · `PurchaseEvaluationsListPage:659,761,817`) × 2 app = 10.

## Stage 3 — Gitea run poll — 🔴 **FAIL: KHÔNG CÓ RUN NÀO ĐƯỢC TẠO**

Poll 6 vòng × ~47s (11:27:49 → 11:31:44) + tra lại 11:36. `GET /actions/tasks?limit=8` (`total_count=484`), đầu bảng:

```
598  485  9b3c0edb  success  push  2026-08-11T01:25:05+07:00
597  484  ef1d4fbb  success  push  2026-08-10T21:31:18+07:00
596  483  c7b7ca45  success  push  2026-08-10T20:45:18+07:00
```

- **0 hit `92d8215a`** trong TOÀN bộ 484 task (không chỉ trang đầu).
- Trang web `…/actions` (HTML thô): 2 hit `9b3c0ed`, **0 hit `92d8215`**.
- `GET /commits/92d8215a…/status` → `total_count: 0`, `state: ""` (rỗng hoàn toàn).

### Tiền-đề đã kiểm (không được khai "CI fail" khi chưa loại hết)

| Nghi vấn | Phép đo | Kết quả |
|---|---|---|
| Push chưa tới remote? | `git ls-remote origin main HEAD` | `92d8215a…` trên **CẢ** `HEAD` + `refs/heads/main` ⇒ **đã tới** |
| Path filter nuốt? | đọc `.gitea/workflows/deploy.yml:17-28` từ ĐĨA | đúng 7 glob; 8 file `fe-*/src/**.{ts,tsx}` **không khớp glob nào** |
| Filter hỏng nói chung? | **cặp đối-chứng** | `9b3c0edb` (docs + `.claude/governance/.session-counter.json` — file KHÔNG bị ignore) → **CÓ** run #485 ✅ · `d4799ddd` (`.claude/WAL.md` đơn độc) → **KHÔNG** run ✅ ⇒ filter chạy ĐÚNG cho commit khác |
| Runner chết? | `Get-Service gitea-runner` | `Running` — **và không liên quan**: run chưa được TẠO thì runner chưa tới lượt |
| Actions bị tắt? | `app.ini:53-54` + API repo | `[actions] ENABLED = true` · `has_actions = True` |
| Push-đè nuốt (gotcha #86)? | `git log 9b3c0edb..92d8215a` | đúng **1** commit, không có push sau |

### 🔴 Nguyên nhân gốc — ĐO ĐƯỢC, không suy diễn

| Nguồn | Giá trị | Nghĩa |
|---|---|---|
| `GET /api/v1/repos/…/branches/main` → `commit.id` | `92d8215a6253` | Gitea đọc **từ git trên đĩa** ⇒ ref ĐÃ tiến |
| `GET /api/v1/repos/…` → `updated_at` | **`2026-08-11T01:25:06+07:00`** | Gitea đọc **từ DB** ⇒ vẫn là mốc push TRƯỚC (`9b3c0edb` 01:25:05) |
| reflog local `.git/logs/refs/remotes/origin/main` | `9b3c0edb → 92d8215a` @ **11:25:55** | push thật lúc 11:25:55 |

⇒ **Ref tiến trên ĐĨA nhưng tầng ứng-dụng Gitea KHÔNG hề xử lý cú push** (0 bump `updated_at`, 0 ActionRun, 0 commit-status). Đây **KHÔNG phải CI fail** — CI chưa từng được gọi. Hook còn nguyên (`hooks/post-receive` 376 B + `post-receive.d/gitea` 142 B, mtime 21/04 = chưa ai đụng) ⇒ nghi hook gọi ngược vào Gitea (`/api/internal/hook/post-receive`) bị lỗi/timeout tại thời điểm push.

🔴 **Lỗ quan-trắc đi kèm (defect ĐỘC LẬP, đo được):** `C:\gitea\log\gitea.log` = **0 byte** từ `8/11 00:00:00`, trong khi bản xoay `gitea.log.2026-08-11.001.gz` = **12,15 MB**. Gitea xoay log lúc nửa đêm rồi **không mở lại file** ⇒ **mất sạch log server-side 11,5 giờ qua**, đúng lúc cần chẩn. Gitea process `Id=4020` StartTime `8/10 5:09:20 AM`, CPU tích luỹ **37.380 s**.
⚠️ Em main: cú `git push` lúc 11:25:55 có in warning/error dòng nào không? Terminal của em là **nguồn DUY NHẤT còn lại** — log Gitea đã chết.

## Stage 4 — Test gate — ⬜ N/A

Baseline `docs/STATUS.md` row Tests = **680** (45 Domain + 635 Infra), Mig canonical **72**. **Không đo được vì không có run.** KHÔNG suy ra pass/fail (vắng-mặt bằng-chứng ≠ bằng-chứng vắng-mặt).

## Stage 5 — Bundle rotate + byte-marker — 🔴 **FAIL (hệ quả Stage 3)**

Đo lại LIVE lúc ~11:36 (sau push 10 phút):

| App | JS trước | JS sau | Rotate? |
|---|---|---|---|
| admin | `index-BZ1PG34E.js` | `index-BZ1PG34E.js` | ❌ **ĐỨNG IM** |
| admin CSS | `index-DVHtHLex.css` | `index-DVHtHLex.css` | ❌ |
| eoffice | `index-0ObPwWFB.js` | `index-0ObPwWFB.js` | ❌ **ĐỨNG IM** |
| eoffice CSS | `index-Ibv3QD_1.css` | `index-Ibv3QD_1.css` | ❌ |

- Byte-marker `Hệ thống đang chậm hoặc lỗi khi tải phiếu` = **0/10** (kỳ vọng 5/app). Control dương vẫn 5 & 6 ⇒ thước sống.
- ⚠️ Đây **KHÔNG** phải ca FROZEN-lành-tính (#69 mode-B): mode-B là *deploy có chạy, copy lại file byte-identical*. Ở đây **deploy chưa từng chạy** ⇒ prod đang phục vụ **code TRƯỚC bản vá YC-028**.

## Stage 6 — Smoke + hồi-quy A/059 — ✅ **PASS 5/5** (server ĐÃ KHOẺ)

| Phép đo | Kỳ vọng | Thực đo | |
|---|---|---|---|
| `GET /health/live` | 200 | **200** · 0,102 s | ✅ |
| `GET /health/ready` | 200 | **200** · 0,167 s | ✅ |
| `POST /api/auth/login` admin | 200 | **200** · 0,294 s · `accessToken` 468 ký tự | ✅ |
| **`GET /api/purchase-evaluations/F02C81D1…` (A/059)** | **200 và < 3 s** | **200** · **0,366 / 0,486 / 0,406 s** (3 lượt) · 18.313 B · `maPhieu=PE/2026/A/059` `phase=10` | ✅ |
| smoke 4 endpoint (`purchase-evaluations` · `contract-signing-plans` · `menus` · `contracts`) | 200 | 200 / 200 / 200 / 200 · 0,269 · 0,124 · 0,164 · 0,121 s | ✅ |
| **control âm** GUID toàn-0 | 404 | **404** | ✅ |

🔑 **Hồi-quy YC-028 SẠCH:** phiếu tâm sự cố trả **0,37-0,49 s**, cách ngưỡng 3 s ~7 lần và cách mốc sự cố (5-47 s) ~2 bậc độ lớn. Cộng disk 28,8 GB free ⇒ **hạ tầng đã hồi phục thật**, không phải hồi phục trên giấy.
🔑 Control âm 404 còn chứng thêm: BE **phân biệt đúng** 404-thật ⟂ lỗi-khác — đúng tiền-đề mà bản vá FE dựa vào. Bản vá đó **chưa lên prod** (Stage 5), nhưng nền BE cho nó thì đã đúng.

## VERDICT

**`FAIL — 8/11 check`** (+1 N/A). Chia 2 vế, **cấm nén**:

- ✅ **Vế hạ-tầng/hồi-quy: LÀNH.** disk 28,8 GB · health/login/smoke 9/9 · A/059 200 trong 0,4 s · control âm 404.
- ❌ **Vế ship: KHÔNG XẢY RA.** Bản vá YC-028 **chưa có trên prod**. Không phải CI đỏ — **CI chưa từng được gọi**.

| # | Check | Kết quả |
|---|---|---|
| 1 | Push tới remote (`git ls-remote`) | ✅ |
| 2 | Path filter đúng ⇒ CI phải chạy | ✅ |
| 3 | **Disk free VPS ≥ 5 GB** (bước 1b, lần chạy ĐẦU) | ✅ **28,8 GB** |
| 4 | Gitea tạo ActionRun cho `92d8215a` | 🔴 **FAIL — 0 run** |
| 5 | Bundle rotate ×2 app | 🔴 **FAIL — cả 4 file đứng im** |
| 6 | Byte-marker trong bundle mới | 🔴 **FAIL — 0/10** (control dương 5 & 6 = thước sống) |
| 7 | health live + ready | ✅ |
| 8 | login admin | ✅ |
| 9 | **A/059 200 và < 3 s** | ✅ **0,366-0,486 s** |
| 10 | smoke 4 endpoint | ✅ 4/4 |
| 11 | control âm 404 | ✅ |
| — | test gate 680 | ⬜ N/A — không có run để đọc |

### Khuyến nghị cho em main (tao READ-only, KHÔNG tự chạy)

1. **Re-trigger:** `deploy.yml:29` CÓ `workflow_dispatch:` ⇒ bấm **Run workflow** trên `…/actions` (build đúng `main` = `92d8215a`). Rẻ hơn và sạch hơn commit rỗng.
2. **Vá lỗ quan-trắc:** `Restart-Service gitea` để logger mở lại file — `gitea.log` đã **0 byte suốt 11,5 h**. Không vá thì lần tái phát sau cũng **mù y hệt**.
3. **Trả lời 1 câu:** cú `git push` 11:25:55 có in warning gì không? Log Gitea chết rồi ⇒ terminal em là **nguồn cuối cùng**.
4. **Sau khi re-trigger:** gọi lại tao verify trọn (gate 680 + bundle rotate + marker 10/10).

### Gotcha MỚI đề nghị khắc vào `docs/gotchas.md`

> **Push land trên đĩa nhưng Gitea KHÔNG xử lý ⇒ CI câm lặng, KHÔNG có run nào để mà đỏ.**
> Phát hiện bằng **2 nguồn lệch nhau trong CÙNG một API**: `GET /repos/{r}` → `updated_at` (đọc **DB**) vs `GET /repos/{r}/branches/main` → `commit.id` (đọc **git trên đĩa**). Head khớp mà `updated_at` đứng ở push TRƯỚC ⇒ tầng ứng-dụng chưa từng thấy cú push.
> 🔴 Nguy ở chỗ **mọi tín hiệu quen đều XANH**: `git ls-remote` đúng SHA · runner `Running` · `[actions] ENABLED=true` · path filter đúng · không có push đè. Chỉ "vắng mặt một cái đáng lẽ phải có" mới tố cáo — cùng lớp `feedback_absence_looks_like_clean`.
> ⇒ **Stage 2 từ nay phải đo `repo.updated_at ≥ thời điểm push`** trước khi kết luận "đang chờ CI".

---

**END VÒNG 1 — VERDICT = FAIL (8/11 check, +1 N/A) · ship KHÔNG xảy ra · hạ-tầng lành**

---

# VÒNG 2 — sau `workflow_dispatch` → run #486

## Datum từ lead (bằng chứng, không suy đoán)

1. `Restart-Service gitea` → Running; `gitea.log` **0 B → 31.946.657 B** ⇒ lỗ quan-trắc ĐÓNG.
2. `workflow_dispatch` qua API → HTTP **204** → **run #486 / task 599**, `head=92d8215a`, `event=workflow_dispatch`.
3. 🔑 **Terminal push 11:25:55 SẠCH** — `remote: Processed 1 references` + `9b3c0edb..92d8215a  main -> main`, **0 warning/error**.
   ⇒ **Datum quyết định cho gotcha #91:** tầng `git-receive` chạy TRỌN (Gitea *có* nhận, *có* in `remote:`) mà tầng ứng-dụng vẫn không đẻ ActionRun ⇒ chỗ gãy nằm **SAU** receive-pack, **TRONG** notifier/queue Gitea — **không phải** hook chết câm, cũng không phải mạng. Khớp đúng chẩn vòng 1 (`updated_at` DB đứng im ⟂ branch-head trên đĩa đã tiến).

## Stage 2b — Run #486

`599 | 486 | 92d8215a | success | workflow_dispatch | 11:45:40 → 11:53:43` = **8 phút 03 giây** (nhỉnh hơn dải quen 5m3x-6m3x — hợp lý vì gitea vừa restart đang giành CPU, xem Stage 6b). ⚠️ Kiểm #86: #486 là run **CUỐI**, 0 push chen ⇒ đọc đúng run.

## Stage 3b — Test gate ✅ **680 EXACT**

Log web-UI `…/actions/runs/486/jobs/0/logs` (18.757 B):

```
Passed!  - Failed:     0, Passed:    45, Skipped:     0     ← Domain
Passed!  - Failed:     0, Passed:   635, Skipped:     0     ← Infrastructure
```

**45 + 635 = 680** khớp `docs/STATUS.md` **tách-phần**, Δ**0** — đúng kỳ vọng (commit 0 file test). 0 fail / 0 skip.

## Stage 4b — Bundle ✅ rotate ×2 + size khớp log CI TỚI BYTE

| App | PRE | POST | | CI log | prod thật |
|---|---|---|---|---|---|
| admin JS | `index-BZ1PG34E.js` | **`index-DxSej4Da.js`** | ✅ ĐỔI | `1,815.25 kB` | **1.815.258 B** |
| eoffice JS | `index-0ObPwWFB.js` | **`index-BcfxaUBO.js`** | ✅ ĐỔI | `1,794.78 kB` | **1.794.780 B** |
| admin CSS | `index-DVHtHLex.css` | `index-DVHtHLex.css` | ⬜ giữ | `88.39 kB` | — |
| eoffice CSS | `index-Ibv3QD_1.css` | `index-Ibv3QD_1.css` | ⬜ giữ | `94.02 kB` | — |

🔑 **CSS giữ nguyên là ĐÚNG, không phải cờ đỏ:** diff chỉ thêm chuỗi tiếng Việt + nhánh `isNotFound`, **0 class Tailwind mới** ⇒ Vite sinh CSS byte-identical ⇒ cùng hash. **JS đổi ⟂ CSS giữ = đúng hình dạng của diff** — chính nó là nhân chứng phụ.
🔑 **Ship-proof mạnh nhất:** size prod khớp dòng `dist/assets/…` trong log CI **tới từng byte** ⇒ file trên prod ĐÚNG là file build ở run #486.
✅ **Control âm tầng-2:** hash CŨ rơi về SPA-fallback — `BZ1PG34E` → **900 B `text/html`**, `0ObPwWFB` → **876 B `text/html`** ⇒ bundle cũ **đã bị ghi đè khỏi đĩa**, không phải 2 bản song song.

## Stage 5b — Byte-marker ✅ **10/10**

| Bundle | marker `Hệ thống đang chậm…` | control DƯƠNG `Không tìm thấy phiếu` |
|---|---|---|
| admin `DxSej4Da` (1.815.258 B) | **5** ✅ (PRE = 0) | 5 ✅ |
| eoffice `BcfxaUBO` (1.794.780 B) | **5** ✅ (PRE = 0) | 6 ✅ |

**5/app khớp CHÍNH XÁC 5 site `grep -rn`** (KhkkCreate:252 · KhkkList:240 · PE-List:659,761,817). Differential trọn **0 → 5** hai phía + control dương sống cả trước lẫn sau ⇒ **bản vá YC-028 ĐÃ LÊN PROD THẬT**.

## Stage 1b(2) — Disk ✅ **28,2 GB** free (ngưỡng 5 GB) — lần chạy thứ 2 của bước mới

## Stage 6b — Smoke ✅ 8/8 ⟂ 🔴 **A/059 latency FAIL**

✅ `health/ready` 200 · `login` 200 · `purchase-evaluations` 200 · `contract-signing-plans` 200 · `menus` 200 · `contracts` 200 · **control âm GUID-toàn-0 → 404** ✅ · peer `A/055` 200 **0,609 s** · `A/058` 200 **0,479 s**.

🔴 **`GET /purchase-evaluations/F02C81D1…` (A/059): 200 ở CẢ 16/16 lượt, nhưng KHÔNG đạt bar `< 3 s`.**

| Đợt | mẫu | min | median | max | **> 3 s** |
|---|---|---|---|---|---|
| ngay sau deploy (pool sinh 11:53:13) | 3 | 5,03 | 6,40 | 10,70 | 3/3 |
| đường cong warm-up | 6 | 0,436 | — | 7,06 | 2/6 *(giảm đơn điệu 7,06→2,29→0,506→0,485→0,469→0,436)* |
| **burst 1 (~12:0x)** | 8 | 0,610 | **1,034** | 6,205 | **2/8** |
| **burst 2 (sau ~2,5 phút nghỉ)** | 8 | 0,618 | **4,996** | **8,749** | **4/8** |

🔴 **Tao TỰ BÁC giả thuyết đầu của mình:** thoạt tiên quy cho cold-start (w3wp pid 9156 StartTime **11:53:13** đúng trong cửa sổ deploy) — đường cong warm-up ủng hộ. **Nhưng burst 2 XẤU HƠN burst 1** ⇒ cold-start **bị bác bằng ĐO**, không giữ lời giải thích tiện tay.

### Truy gốc — loại trừ theo runbook, từng cửa

| Nghi vấn | Đo | Kết luận |
|---|---|---|
| Disk đầy (YC-028 cũ) | 28,2 GB free | ❌ loại |
| Orphan sshd/powershell ăn core | CPU-delta 5 s ×2 lượt → chỉ `gitea` 2,2 s rồi 1,2 s; **0 sshd** đốt CPU | ❌ loại |
| `AUTO_CLOSE` bật lại (runbook §4) | `SolutionErp is_auto_close_on = **0**` | ❌ loại |
| NTFS nén `.mdf/.ldf` (gotcha #88) | SolutionErp **không nén**; nhưng **`Vietreport_Master.mdf` + `.ldf` ĐANG nén** — DB hàng xóm | ❌ loại (phát hiện kèm → báo riêng) |
| **RAM bị ép → buffer pool SQL teo** | dưới đây | ✅ **KHỚP** |

```
RAM total = 4 GB · free = 1,08 GB (27%)
SQL:  Target Server Memory = 1.115.736 KB (~1,09 GB)
      Total  Server Memory =   218.592 KB (~213 MB)   ← chỉ được 1/5 cái nó CẦN
      Page life expectancy = 522 s     ·     max server memory = 2147483647 (mặc định, KHÔNG ghim)
Top WS: gitea 317 MB (CPU 512 s kể từ restart ~11:44) · w3wp 238 MB · sqlservr 135 MB
```

⇒ **Chuỗi nhân-quả đo được:** VPS **4 GB RAM / 3 core** dùng chung với VIETREPORT → buffer pool SQL chỉ giữ **213 MB** trên **1,09 GB** nó nhắm → PLE 522 s → query nặng PE-detail **trượt cache** → đọc đĩa ⇒ **phân bố LƯỠNG CỰC đặc trưng: 0,6-1,0 s (trúng cache) HOẶC 5-8,7 s (trượt cache), gần như trống ở giữa**. Đó là hình dạng của **thiếu RAM**, không phải hình dạng của code chậm.

🔴 **KHÔNG THỂ do commit này:** `git diff 9b3c0edb..92d8215a` = **8 file FE + 4 file không deploy, 0 file BE, 0 mig** ⇒ DLL API hành vi y hệt bản chạy trước đó. **Độ trễ API không thể do code trong commit này gây ra.**

🔴 **PHẦN TAO PHẢI NHẬN:** khuyến nghị `Restart-Service gitea` (của chính tao ở vòng 1) khiến gitea nạp lại + tái chỉ mục: **317 MB RSS và 512 giây CPU trong ~25 phút (~34% một core, liên tục)**. Trên máy 4 GB/3 core nó **giành RAM+CPU với SQL đúng lúc đo** ⇒ **một phần con số xấu ở trên là do việc tao đề xuất**. Đổi lại lỗ quan-trắc 11,5 h đã đóng — tao vẫn cho là đáng, nhưng cái giá phải nói ra chứ không giấu vào chữ "transient".

## VERDICT VÒNG 2 — **PARTIAL 8/9**

| # | Check | |
|---|---|---|
| 1 | Run #486 tới terminal `success` | ✅ 8m03s |
| 2 | Test gate **680** (45+635) tách-phần, Δ0 | ✅ EXACT |
| 3 | Bundle JS rotate ×2 + size khớp log CI tới byte | ✅ |
| 4 | Byte-marker 10/10 (5/app · PRE=0 · control dương sống) | ✅ |
| 5 | Control âm tầng-2: hash cũ → `text/html` 900/876 B | ✅ |
| 6 | Disk free ≥ 5 GB | ✅ 28,2 GB |
| 7 | health + login | ✅ |
| 8 | smoke 4 endpoint + control âm 404 + 2 peer PE | ✅ |
| 9 | **A/059 200 và < 3 s** | 🔴 **FAIL** — 200 ở 16/16, nhưng **6/16 mẫu > 3 s**, max **8,75 s**, burst-2 median **5,0 s** |

**Hai vế, cấm nén:**
- ✅ **SHIP: THÀNH CÔNG TRỌN.** Bản vá YC-028 đã lên prod — chứng bằng marker 0→5 hai app + size khớp byte + bundle cũ bị ghi đè. Gate 680 nguyên. Vòng 1 chỉ là Gitea không tạo run, **không hề có lỗi trong code**.
- 🔴 **PERF: bar `<3 s` KHÔNG ĐẠT**, và **không** phải cold-start (burst 2 xấu hơn burst 1). Gốc đo được = **RAM 4 GB bị ép, buffer pool SQL 213 MB/1,09 GB**, nặng thêm vì gitea vừa restart. **Không phải hồi quy của commit này.**

### Khuyến nghị (tao READ-only)

1. **Đo lại A/059 sau ~30-60 phút** khi gitea nguội — còn 5-8 s thì đây là **thiếu RAM cấu trúc**, hết là transient.
2. **Ghim `max server memory` cho SQL** (đang mặc định `2147483647`): ~1.200 MB để SQL khỏi đấu RAM hỗn loạn với gitea/w3wp/runner trên máy 4 GB.
3. **Nâng RAM VPS** — 4 GB cho 3 site + SQL + Gitea + runner + LibreOffice là quá mỏng. Đây là **mặt thứ hai của YC-028**: lần trước vỡ ở ĐĨA, lần này ép ở RAM.
4. **`Vietreport_Master.mdf/.ldf` đang NTFS-nén** (gotcha #88, dư âm đợt "giải phóng dung lượng") — DB của VIETREPORT → báo đội đó `compact /u`.
5. Gotcha **#91** khắc theo vòng 1; datum #3 của lead làm nó **sắc hơn**: chết ở **notifier**, không phải receive-pack.

---

**END VÒNG 2 — VERDICT = PARTIAL (8/9) · SHIP PASS TRỌN · PERF A/059 FAIL (gốc hạ-tầng RAM, không phải code)**

