# HƯỚNG DẪN CÀI ĐẶT — BỘ APP QUY TRÌNH SƠN & PHA MÀU (CSDL A · CSDL B · CSDL D)

> **Dành cho agent AI trên máy Linux** (máy đích) — đọc hết file này rồi mới thao tác.
> Bộ này chuyển từ máy Windows của chủ nhân sang một máy Linux khác, chạy **cùng 3 web app nội bộ** + 3 worker gọi **AGY (Antigravity CLI)**.
> **Ngôn ngữ làm việc với chủ nhân: tiếng Việt.** Mọi báo cáo/tài liệu tạo ra phải là **DOCX** (chủ nhân không đọc `.md`).

---

## 0. TRƯỚC KHI CÀI — 4 việc BẮT BUỘC là do CHỦ NHÂN làm (không tự đoán)

1. **Đăng nhập AGY** — bộ app gọi `agy` headless. Nếu máy chưa từng đăng nhập, `agy` sẽ mở trình duyệt để chủ nhân đăng nhập Google. **Agent KHÔNG tự nhập credential.**
2. **Mật khẩu app** — 3 app đều có mật khẩu riêng (`apps/*/mat_khau.txt`). Bản bàn giao **giữ nguyên mật khẩu cũ**; muốn đổi thì hỏi chủ nhân rồi sửa file đó.
3. **Email thông báo** (tuỳ chọn) — mặc định **TẮT**. Bật thì cần Gmail API credential riêng của máy mới do chủ nhân cấp.
4. **Truy cập từ xa** (tuỳ chọn) — 3 app chỉ bind `127.0.0.1`. Muốn vào từ máy khác thì dùng SSH tunnel hoặc Tailscale funnel, do chủ nhân quyết.

⚠️ **Bộ file này chứa mật khẩu app + dữ liệu nội bộ công ty** (CSDL quy trình sơn, hệ màu, hồ sơ gỗ). Không đăng lên dịch vụ công khai, không commit vào git, không gửi cho agent ngoài.

---

## 1. BỘ NÀY GỒM NHỮNG GÌ (3 app · 2 luồng huấn luyện CSDL)

| App | Cổng | CSDL dùng | Luồng công việc |
|---|---|---|---|
| **Agent-Lab** | 8098 | `lab.db` + `CSDLD.db` + `CSDLB.db` (đọc) | Nạp **ảnh gỗ mộc + yêu cầu** → AGY 2 bước (phân tích gỗ/màu → đề nghị quy trình + công thức pha màu) → xuất **DOCX** + email |
| **CALIB (CSDL B)** | 8099 | `CSDLB.db` | Nhập **hỗn hợp màu + tỉ lệ %** → AGY đoán màu (hex, L\*a\*b\*) → chủ nhân tải **ảnh thực tế** → AGY đối chiếu **ΔE** + đề xuất **hệ số hiệu chỉnh** → nhập pass ⇒ **ghi vào CSDL B** |
| **HLQT (CSDL A)** | 8100 | `CSDLA.db` | Nạp **1 bản màu** → AGY chọn **đúng 1 quy trình** sát nhất từ CSDL A → chủ nhân nhập **quy trình thực tế đã làm** → AGY **đối chiếu** → đề xuất bổ sung CSDL A (quy trình mới + luật mới) → nhập pass ⇒ **ghi** |

**Điểm chung 3 app (bắt buộc hiểu đúng):**
- **Agent CHỈ ĐỀ NGHỊ. Dữ liệu chỉ được ghi vào CSDL khi có mật khẩu xác nhận của chủ nhân** (cơ chế `mat_khau.txt` + ô nhập pass trên web). Không có đường nào để agent tự ghi.
- **3 mốc tự động gửi email** cho người tạo việc: `p` = đã có đề nghị/dự đoán · `c` = đã có phân tích đối chiếu · `ghi` = đã ghi vào CSDL. (Email tắt ⇒ bỏ qua, không lỗi.)
- **Luôn backup trước khi ghi**: worker tự `shutil.copy2` CSDL thành `<tên>_bak_<YYYYMMDD_HHMM>.db` trước mỗi lần ghi.

### Cây thư mục bàn giao

```
BAN_GIAO_APP_LINUX/
├── HUONG_DAN_CAI_DAT.md          ← file này
├── apps/
│   ├── hlqt/     server_hlqt.py · worker_hlqt.py · goi_kien_thuc_hlqt.py · HDSD_HLQT.md
│   │             kien_thuc/CSDLA_GOI_CHO_AGY.md  (gói kiến thức cho AGY, ~250 KB)
│   │             mat_khau.txt · bi_mat.txt · pass_hlqt.txt · email_bao.txt · _tools/
│   ├── calib/    server_calib.py · worker_calib.py · HDSD_CALIB.md
│   │             mat_khau.txt · bi_mat.txt · pass_hieu_chinh.txt · email_bao.txt · _tools/
│   └── lab/      server_lab.py · worker_lab.py · dung_goi_kien_thuc.py · HDSD_AGENT_LAB.md
│                 kien_thuc/CSDL_KIEN_THUC_ABC.md (gói kiến thức A+B+C) · mat_khau.txt · bi_mat.txt · _tools/
├── data/         CSDLA.db · CSDLB.db · CSDLD.db · CSDLC.db · lab.db
├── cai_dat/      cai_dat.sh · sua_duong_dan.py · cau_hinh.json · chay_tat_ca.sh · dung_tat_ca.sh
│                 kiem_tra.sh · md2docx.py · gui_mail_kem_file.py
├── systemd/      btchem-hlqt.service · btchem-calib.service · btchem-lab.service
└── tai-lieu/     CSDLA_KIEN_THUC_HUAN_LUYEN.md · CSDLA_BOSUNG_QT_MOC.md · HDSD_CSDLD.md
```

**Dữ liệu trong 5 CSDL (để agent biết mình đang giữ gì):**
- `CSDLA.db` — **quy trình sơn**: `quy_trinh`, `buoc_quy_trinh`, `buoc_chuan` (34 bước chuẩn), `cong_thuc`, `danh_muc_mau`, `huan_luyen` + `huan_luyen_ca` (nhật ký huấn luyện), `phong_cach`, `nguon_quet`.
- `CSDLB.db` — **hệ màu stain/glaze**: `mau` (8 mã metal complex, có hệ số hiệu chỉnh), `phan_tan`, `lien_ket_gia`, `mau_bang_in`, `hon_hop` + `hieu_chinh_mau` (nhật ký hiệu chỉnh), `worker_nhip`.
- `CSDLD.db` — **hồ sơ gỗ**: `loai_go`, `yeu_to_anh_huong`, `map_buoc_quy_trinh`, `yeu_cau_chat_luong`, `hieu_chinh_theo_do_hut_mau`, `huong_dan_chup_anh`.
- `CSDLC.db` — **kinh nghiệm khách hàng** (Agent-Lab tham chiếu khi đề nghị).
- `lab.db` — **hàng đợi việc của Agent-Lab**: `viec`, `phan_hoi`.

---

## 2. CÀI ĐẶT (5 bước, ~10 phút)

### Bước 1 — Đặt bộ file & chạy script cài

```bash
sudo mkdir -p /opt/btchem && sudo chown -R "$USER":"$USER" /opt/btchem
unzip BAN_GIAO_APP_LINUX.zip -d /tmp/bg && cp -a /tmp/bg/BAN_GIAO_APP_LINUX/. /opt/btchem/
cd /opt/btchem && bash cai_dat/cai_dat.sh          # tạo venv + cài phụ thuộc + vá đường dẫn
```

`cai_dat.sh` làm 5 việc: tạo `venv` (`python3 -m venv venv`), cài `python-docx` (bắt buộc) + thư viện Gmail (tuỳ chọn), tạo `apps/*/viec` + `logs/`, chạy `sua_duong_dan.py`, và `chmod 600` các file mật khẩu.

> Nếu chủ nhân muốn thư mục khác: sửa `cai_dat/cau_hinh.json` (`root`) **trước khi** chạy `cai_dat.sh`.

### Bước 2 — Cài AGY (Antigravity CLI)

```bash
curl -fsSL https://antigravity.google/cli/install.sh | bash   # script tự kiểm SHA512, cài ở mức user
agy --version && agy models                                   # phải liệt kê được model
```
- Binary thường nằm ở `~/.local/bin/agy` (hoặc `/usr/local/bin/agy`). Nếu khác, **sửa `agy_bin` trong `cai_dat/cau_hinh.json` rồi chạy lại `python3 cai_dat/sua_duong_dan.py`**.
- Máy chưa đăng nhập: `agy -p "hello" --output-format json` sẽ yêu cầu **chủ nhân** đăng nhập Google (mở trình duyệt). Agent dừng ở đây và báo chủ nhân.
- Kiểm tra hạn mức: `agy -p "/usage" --output-format json`.
- **Model dùng cho 3 app** (giữ nguyên như máy cũ — sửa trong `worker_*.py` nếu chủ nhân muốn khác):
  `gemini-3.1-pro-high` cho HLQT · CALIB · Agent-Lab (việc phân tích màu/quy trình cần model mạnh), `--effort high`.
- `--project 2f54d0c6-f33f-4dae-b5b7-840339496ec7` = project "Du-an-A-Quy-trinh-son". ⚠️ `--project` **không báo lỗi khi sai tên** — đừng tin mỗi `status`.

### Bước 3 — Kiểm tra cấu hình đã vá đúng

```bash
cd /opt/btchem && grep -nE "AGY|\.db'|MAIL_SCRIPT|MD2DOCX|URL_PUBLIC" apps/*/worker_*.py apps/*/server_*.py | grep -v "^.*#" | head -30
```
Kỳ vọng: **không còn đường dẫn Windows** (`C:\...`, `%LOCALAPPDATA%`). Nếu còn, sửa `cau_hinh.json` rồi chạy lại `sua_duong_dan.py`.

### Bước 4 — Chạy 3 app (server + worker mỗi app)

Cách nhanh (chạy nền, log vào `logs/`):
```bash
cd /opt/btchem && bash cai_dat/chay_tat_ca.sh        # dừng: bash cai_dat/dung_tat_ca.sh
```
Cách chuẩn (tự khởi động lại khi reboot):
```bash
sudo cp systemd/*.service /etc/systemd/system/
sudo sed -i "s|__ROOT__|/opt/btchem|g; s|__USER__|$USER|g" /etc/systemd/system/btchem-*.service
sudo systemctl daemon-reload && sudo systemctl enable --now btchem-hlqt btchem-calib btchem-lab
systemctl status btchem-hlqt --no-pager
```

### Bước 5 — Kiểm tra sức khoẻ

```bash
cd /opt/btchem && bash cai_dat/kiem_tra.sh
```
Script kiểm: 3 app trả về trang đăng nhập (HTTP 200) · 6 tiến trình đang chạy · 5 CSDL mở được + đúng số bảng · `agy` gọi được · không còn đường dẫn Windows trong code.

Truy cập: `http://127.0.0.1:8100/` (HLQT — CSDL A) · `http://127.0.0.1:8099/` (CALIB — CSDL B) · `http://127.0.0.1:8098/` (Agent-Lab).
Hai app HLQT và CALIB chạy được **cả ở gốc và dưới tiền tố** (`/hlqt/`, `/calib/`) khi đặt sau reverse proxy.

---

## 3. CÁCH VẬN HÀNH TỪNG LUỒNG (đọc kỹ — đây là phần "công việc" của bộ app)

### 3.1 HLQT — huấn luyện CSDL A (quy trình sơn)
1. Vào `:8100`, nhập mật khẩu app.
2. **Tạo ca**: tải **ảnh bản màu** (mẫu sơn thực tế) + ghi chú yêu cầu. Hệ thống đẩy việc vào hàng đợi.
3. **Worker bước P** (đề nghị): gửi ảnh + **gói kiến thức** `apps/hlqt/kien_thuc/CSDLA_GOI_CHO_AGY.md` cho AGY ⇒ AGY chọn **đúng 1 quy trình** khả dĩ/sát nhất trong CSDL A + lý do. → email mốc `p`.
4. Chủ nhân xem, rồi **nhập quy trình THỰC TẾ đã làm** vào trang ca.
5. **Worker bước C** (đối chiếu): AGY so đề nghị ↔ thực tế ⇒ khác biệt chính, luật mới đề xuất, xung đột luật cũ. → email mốc `c`.
6. Chủ nhân nhập **mật khẩu xác nhận** trên trang ca ⇒ worker **ghi** quy trình mới + luật mới vào `CSDLA.db` (**backup trước**) và **tự dựng lại gói kiến thức** (`goi_kien_thuc_hlqt.py`) để lần đề nghị sau dùng luật mới. → email mốc `ghi`.

### 3.2 CALIB — huấn luyện/hiệu chỉnh CSDL B (hệ màu)
1. Vào `:8099`, nhập mật khẩu app.
2. **Tạo hỗn hợp**: chọn các màu CÓ TRONG CSDL B + **tỉ lệ %** từng màu. (Hiệu chỉnh mặc định: **kéo cùng thông số thước kéo với màu mẫu, pha cùng loại base, trên giấy trắng cùng loại** — người dùng chỉ nhập tỉ lệ %.)
3. **Worker bước P**: AGY đoán màu hỗn hợp (hex, L\*a\*b\*, phương pháp, độ tin cậy) từ bảng thông số màu + **hệ số cường độ** hiện có. → email `p`.
4. Chủ nhân **chụp ảnh màu thực tế** và tải lên trang chi tiết.
5. **Worker bước C**: AGY đọc ảnh, tính **ΔE** so với dự đoán, đề xuất **hệ số hiệu chỉnh** cho từng màu. → email `c`.
6. Chủ nhân nhập **pass hiệu chỉnh** ⇒ **ghi hệ số vào `CSDLB.db`** (backup trước). → email `ghi`.
   ⚠️ **Hệ số CHỈ được đổi khi có ẢNH HỖN HỢP THẬT** — không đổi theo cảm tính.

### 3.3 Agent-Lab — đề nghị quy trình + công thức pha màu
1. Vào `:8098`, nhập mật khẩu app. **Tạo việc**: tải **ảnh gỗ mộc** + ảnh mẫu màu (nếu có) + yêu cầu (loại gỗ, đặc tính, yêu cầu chất lượng, độ bóng, ghi chú).
2. **Worker bước 1**: AGY phân tích ảnh gỗ mộc + màu mẫu.
3. **Worker bước 2**: AGY dùng kiến thức `kien_thuc/CSDL_KIEN_THUC_ABC.md` (A + B + C) ⇒ **quy trình đề nghị** + **công thức pha màu** (chỉ dùng mã CÓ trong CSDL B; mã thiếu tồn kho phải ghi rõ).
4. Kết quả xuất **DOCX** (`cai_dat/md2docx.py`), lưu trong `apps/lab/viec/<mã việc>/`, gửi email kèm file nếu bật.
   ⚠️ **Luôn nêu rõ: đây là ĐỀ NGHỊ của phòng Lab, KHÔNG thay thế thẻ mẫu xác nhận của kỹ thuật viên thực tế.**

### 3.4 Khi dữ liệu được cập nhật — phải dựng lại gói kiến thức
- Sửa CSDL A (quy trình/luật) ⇒ chạy `apps/hlqt/goi_kien_thuc_hlqt.py` → sinh lại `kien_thuc/CSDLA_GOI_CHO_AGY.md`.
- Sửa CSDL A/B/C ⇒ chạy `apps/lab/dung_goi_kien_thuc.py` → sinh lại `kien_thuc/CSDL_KIEN_THUC_ABC.md` (+ `goi_kien_thuc.json` ghi số dòng từng nguồn).
- Cả 2 script chạy bằng **venv của bộ app**: `/opt/btchem/venv/bin/python apps/hlqt/goi_kien_thuc_hlqt.py`.

---

## 4. QUY TẮC AN TOÀN & KỶ LUẬT DỮ LIỆU (bắt buộc)

1. **Backup trước mọi lần ghi CSDL** — worker đã tự làm (`*_bak_<YYYYMMDD_HHMM>.db`). Trước thao tác thủ công thì tự copy: `cp data/CSDLA.db data/CSDLA.db_bak_$(date +%Y%m%d_%H%M)`.
2. **Không tự ghi CSDL** — chỉ ghi qua app + có mật khẩu xác nhận của chủ nhân.
3. **AGY là agent NGOÀI (dữ liệu gửi lên Google)** ⇒ chỉ gửi nội dung đã được phép. **Không đưa giá nguyên liệu, giá thành, tên khách hàng cụ thể, bí quyết công thức** vào prompt khi chưa hỏi chủ nhân.
4. **Ẩn danh hoá**: tài liệu kỹ thuật gửi đi không ghi tên riêng khách hàng/kỹ thuật viên.
5. **Không tin kết quả tự khai** — sau mỗi lần ghi, kiểm bằng truy vấn SQLite số dòng + mở lại trang web xem dữ liệu mới; `status: SUCCESS` của AGY **không** đồng nghĩa đã ghi đúng.
6. **Số liệu không được tự suy diễn**: nếu nguồn thiếu, ghi `[không đọc rõ]` rồi hỏi chủ nhân.
7. **Chủ nhân ghét trùng lặp**: không để 2 bản file trùng; file tạm phải dọn sau khi xong.

---

## 5. KHÁC BIỆT Windows → Linux (đã xử lý sẵn trong bộ này)

| Máy Windows (gốc) | Máy Linux (bộ này) |
|---|---|
| Python venv của Hermes + `python.exe` | `sys.executable` (worker tự lấy) ⇒ dùng `/opt/btchem/venv/bin/python` |
| `C:\Users\admin\AppData\Local\agy\bin\agy.exe` | `agy` theo `agy_bin` trong `cau_hinh.json` |
| `C:\Claw 2\...\CSDLA.db` (đường dẫn tuyệt đối) | `/opt/btchem/data/CSDLA.db` |
| `%LOCALAPPDATA%\hermes\skills\...\gui_mail_kem_file.py` | `/opt/btchem/cai_dat/gui_mail_kem_file.py` (email **tắt mặc định**) |
| `C:\Claw 2\QC\_md2docx.py` | `/opt/btchem/cai_dat/md2docx.py` |
| `Chay_*.bat` | không dùng (giữ làm tham chiếu) → dùng `cai_dat/chay_tat_ca.sh` hoặc systemd |
| URL funnel Tailscale | `url_public` trong `cau_hinh.json` |
| Mật khẩu file (mode thường) | `chmod 600` các file `mat_khau.txt`, `bi_mat.txt`, `pass_*.txt`, `email_bao.txt` |

---

## 6. KIỂM TRA SAU KHI CÀI — checklist cho agent (dán kết quả thật vào báo cáo)

- [ ] `bash cai_dat/kiem_tra.sh` → 3 app HTTP 200 · 6 tiến trình · 5 CSDL mở được
- [ ] `grep -rn "C:\\\\" apps/*/*.py` → **rỗng** (hết đường dẫn Windows)
- [ ] `agy models` liệt kê model (đã đăng nhập)
- [ ] Tạo **1 ca thử HLQT** với 1 ảnh màu + xem app trả đề nghị (không cần ghi CSDL)
- [ ] Tạo **1 việc thử Agent-Lab** → phải ra file `.docx` thật trong `apps/lab/viec/<id>/`
- [ ] Tạo **1 hỗn hợp thử CALIB** → phải ra dự đoán màu (hex + L\*a\*b\*)
- [ ] Xoá dữ liệu chạy thử sau khi kiểm (chủ nhân không muốn rác trong CSDL)

---

## 7. SỰ CỐ THƯỜNG GẶP

| Hiện tượng | Nguyên nhân & cách xử lý |
|---|---|
| App trả 401/không vào được | Sai mật khẩu — đọc `apps/<app>/mat_khau.txt` (chủ nhân có thể đã đổi) |
| Trang web trắng / nút không chạy | Thường do **thiếu `<base href>`** khi chạy dưới tiền tố — app đã tự xử lý; kiểm bằng cách mở ở gốc `http://127.0.0.1:<cổng>/` |
| Worker không xử lý việc | Kiểm log `logs/<app>-worker.log`; kiểm `worker_nhip`/`viec` trong CSDL; kiểm `agy` gọi được |
| Không có file DOCX | `md2docx.py` cần `python-docx` trong venv: `venv/bin/pip install python-docx` |
| Email không tới | Mặc định tắt — bật cần Gmail credential; kiểm `cai_dat/gui_mail_kem_file.py` chạy được: `venv/bin/python cai_dat/gui_mail_kem_file.py --help` |
| Ghi CSDL xong nhưng thấy số cũ | Phải dựng lại **gói kiến thức** (mục 3.4); kiểm số dòng bằng `sqlite3 data/CSDLA.db "select count(*) from quy_trinh"` |
| `--project` sai vẫn SUCCESS | AGY không validate tên project (rơi về mặc định) — kiểm bằng thư mục làm việc thật, đừng tin `status` |

---

## 8. LIÊN HỆ / BÀN GIAO NGƯỢC

- Chủ nhân: **anh Minh (Phó Giám đốc, BTChem)**. Mọi trao đổi bằng **tiếng Việt**, báo cáo bằng **DOCX**.
- Dữ liệu phát sinh ở máy Linux **không tự đồng bộ** về máy Windows: muốn gộp thì **copy file `.db`** về (`data/CSDLA.db`, `data/CSDLB.db`) rồi **so số dòng từng bảng trước/sau** để không mất dữ liệu.
- Quy ước đặt tên file mới giữ như máy gốc: `T<N>` cho tuần, hậu tố `_bak_<YYYYMMDD_HHMM>` cho bản sao.
