---
name: ice-doc-reader
description: อ่านและแปลงเอกสารเป็น Markdown ในเครื่อง 100% ด้วย anydoc (16 นามสกุล — Word/PowerPoint/Excel/OpenDocument/RTF/EPUB/CSV/PDF) + pdf-inspector คัดกรอง PDF ว่าหน้าไหนเป็นภาพอ่านข้อความไม่ได้ก่อนแปลง + ตรวจความสมบูรณ์ภาษาไทย (สระอำ/วรรณยุกต์) ที่เครื่องมือทั้งสองไม่มี. ⛔ ไม่ส่งไฟล์ออกนอกเครื่อง ไม่มี API ไม่มี cloud — ใช้กับสัญญา งบการเงิน TOR เอกสารลูกค้าได้ปลอดภัย. ใช้เมื่อต้องอ่าน/สกัดเนื้อหาจากเอกสารเข้าคลังความรู้หรือเข้า context. Triggers (TH): อ่านเอกสาร, แปลงเป็น Markdown, สกัดเนื้อหาจากไฟล์, อ่าน PDF, อ่าน docx, ดูด TOR, เอกสารลูกค้าเข้าคลัง, PDF สแกน, ต้อง OCR ไหม, ตรวจว่าอ่านได้ครบไหม. Triggers (EN): read document, convert to markdown, extract text from file, parse PDF, docx to md, scanned PDF, needs OCR, document ingestion.
---

> **Skill:** ice-doc-reader | **Version:** V01R03 | **Date:** 2026.08.07
> **V01R03 (รีวิว adversarial):** ปิดช่อง **silent failure ในตัวเครื่องมือเอง** — เดิม `.txt`/ไฟล์ว่าง/ไฟล์เสีย ให้ผลว่างเปล่าพร้อม exit 0 (= ความเสียหายเงียบชนิดเดียวกับที่ skill นี้ตั้งใจกัน) · ตอนนี้ exit 2 พร้อมข้อความชัด · PDF เสียไม่พ่น traceback · ไฟล์ข้อความอยู่แล้วบอกให้อ่านตรง
> **V01R02:** +**OCR ในเครื่อง** (macOS Vision · `--ocr`) — PDF สแกนอ่านได้โดยไม่ต้องส่งออกนอกเครื่อง · +**R2b บันไดทางออก 3 ระดับ** เมื่ออ่านไม่ได้ (ขอไฟล์ต้นฉบับ → OCR ในเครื่อง → ขออนุญาตส่งภายนอก)
> **คู่กับ:** `ice-doc-builder` (สร้างเอกสารออก) — ตัวนี้คือ**ขาเข้า** อ่านเอกสารเข้ามา
> **ผู้ใช้:** เสี่ยวป้อ (เก็บวัตถุดิบ) · กัปตัน (อ่าน source ก่อนทำ proposal) · สมนึก (อ่าน literature)
> · L0 ทุก persona · ใครก็ตามที่ต้องอ่านไฟล์เข้า context

---

# §0 หลักการ — ทำไมต้องมี skill นี้

การ "อ่านเอกสาร" ของ fleet เคยเป็นเรื่องต่างคนต่างเดา และมี**ความเสียหายเงียบ** 2 ชนิดที่ไม่มีใครจับได้:

| ความเสียหายเงียบ | เกิดยังไง | ผลที่ตามมา |
|---|---|---|
| **ข้อความไทยพัง** | `pdftotext` ทำสระอำแตก (`จำกัด` → `จ ำกัด`) · LibreOffice ก็เคยทำ | ค้นหาไม่เจอ · copy ไปใช้ต่อผิด · Turnitin/index เพี้ยน |
| **เนื้อหาหายทั้งหน้า** | PDF ที่เป็นภาพสแกน แปลงแล้วได้ข้อความว่าง **แต่ไม่มีใครบอก** | สรุป/อ้างอิงจากข้อมูลที่ขาด โดยคิดว่าครบ (เคสจริง: ไฟล์ 187 หน้า อ่านได้ 138 หน้า) |

⛔ **ทุกขั้นรันในเครื่อง 100%** — ไม่มี API key ไม่มี endpoint ไม่ส่งไฟล์ออกนอกเครื่อง
สัญญา งบการเงิน TOR ลูกค้า เอกสารภายใน ใช้ได้ปลอดภัย (ทั้ง 2 เครื่องมือเป็น Rust binary · MIT license)

---

# §1 เครื่องมือ — คำสั่งเดียวจบ

```bash
bash ~/.claude/agents/_lib/doc_to_md.sh FILE [-o OUT.md]
bash ~/.claude/agents/_lib/doc_to_md.sh --scan DIR        # กวาด PDF ทั้งโฟลเดอร์ก่อนดูดเข้าคลัง
bash ~/.claude/agents/_lib/doc_to_md.sh FILE --inspect-only   # ดูชนิด PDF อย่างเดียว ไม่แปลง
```

helper ทำ **3 ขั้นให้อัตโนมัติ** — agent ไม่ต้องจำลำดับ:

```
① คัดกรอง (PDF)   pdf-inspector → หน้าไหนเป็นภาพ อ่านข้อความไม่ได้ → เตือนก่อนแปลง
② แปลง            anydoc        → 16 นามสกุล → GitHub-Flavored Markdown
③ ตรวจไทย         ของเราเอง      → สระอำ/วรรณยุกต์รอดครบไหม  ← ⭐ สองตัวบนไม่มีข้อนี้
④ OCR (เมื่อสั่ง)  macOS Vision  → หน้าที่เป็นภาพ → ข้อความ · ⛔ ยังอยู่ในเครื่อง · ~1.8 วิ/หน้า
```

```bash
bash ~/.claude/agents/_lib/doc_to_md.sh FILE --ocr -o OUT.md    # เติมเนื้อหาจากหน้าที่เป็นภาพ
```

**exit code (V01R03):**

| code | ความหมาย | agent ต้องทำอะไร |
|---|---|---|
| `0` | สะอาด · หรือเป็นไฟล์ข้อความอยู่แล้ว (`.txt/.md/.json/.html`) → อ่านตรงได้ | ใช้ผลได้ |
| `1` | ไม่พบไฟล์ | ตรวจ path |
| `2` | **อ่านไม่ได้** — ไฟล์ว่าง · ไฟล์เสีย · ฟอร์แมตนอก 16 นามสกุล · แปลงแล้วว่างเปล่า | 🔴 **แจ้ง user + เข้าบันได R2b · ห้ามเดาเนื้อหา** |
| `3` | ข้อความไทยเสียหาย (สระอำแตก/วรรณยุกต์ลอย) | 🔴 หยุด ห้ามเข้าคลัง (R2) |
| `4` | ไม่พบ venv เครื่องมือ | สร้างใหม่ตาม §5 |

---

# §2 ⭐ กติกาบังคับ 5 ข้อ

**R1 — ใช้ helper นี้เป็นตัวแปลงมาตรฐาน ห้ามเขียนเองใหม่**
`python-docx` / `pdftotext` / `openpyxl` ยังใช้ได้เมื่อต้องการ **โครงสร้างระดับ XML** (เช่น ตรวจฟอนต์
ตรวจ merge cell) แต่ **การอ่าน "เนื้อหา" เป็นข้อความ/Markdown → ใช้ `doc_to_md.sh` เสมอ**
เหตุผล: มันตรวจภาษาไทยให้ด้วย ซึ่งเครื่องมือเดิมไม่มี

**R2 — 🔴 exit 3 (ข้อความไทยเสียหาย) = หยุด ห้ามเอาเข้าคลัง/ห้ามใช้อ้างอิง**
รายงาน user ว่าเสียหายกี่จุด แล้วขอไฟล์ต้นฉบับใหม่ หรือถามว่าจะรับตามนั้นไหม
**ห้ามซ่อมข้อความเอง** (เดาว่าคำเดิมคืออะไร = แต่งข้อมูล ผิด H3 anti-hallucination)

**R3 — 🔴 PDF ที่มีหน้าต้อง OCR = ต้องแจ้ง user เสมอ ห้ามเงียบ**
บอกให้ชัดว่า "ไฟล์ 187 หน้า อ่านข้อความได้ 138 หน้า · อีก 49 หน้าเป็นภาพ"
→ user ตัดสินว่าจะหา OCR แยก หรือทำงานจากส่วนที่อ่านได้ · **ห้ามสรุปเนื้อหาโดยไม่บอกว่าขาด**

**R4 — ผลลัพธ์ลงดิสก์ตามกติกาที่เก็บไฟล์**
Markdown ที่แปลงแล้ว → `<sub-project>/20-Output/_temp/` ถ้าเป็นของชั่วคราว ·
ถ้าเก็บเข้าคลังถาวร → `90-Brain/` หรือ `00-Context/_retrieved/` พร้อม **provenance**
(ที่มาไฟล์ · วันที่แปลง · ผลตรวจไทย) — กติกาเต็ม: `agents/reference/file-hygiene.md`

**R2b — ⭐ บันไดทางออกเมื่ออ่านไม่ได้ (คำสั่ง user 2026.08.06: "ถ้าอ่านแล้วอ่านไม่ได้ แจ้งนะ
ไม่ติดถ้าต้องให้ LLM ข้างนอกช่วย")**

เมื่อ local อ่านไม่ได้/ไม่ครบ → **แจ้ง user ทันที** พร้อมเสนอ 3 ทาง เรียงจากปลอดภัยที่สุด:

```
① ขอไฟล์ต้นฉบับที่เป็นข้อความจากผู้ส่ง   ← ดีที่สุด ไม่มีความเสี่ยง ได้ข้อความแม่นยำ 100%
② OCR ในเครื่อง (macOS Vision · --ocr)  ← ⛔ ยังไม่ออกนอกเครื่อง · รองรับไทย · ~1.8 วิ/หน้า
③ ส่งให้บริการ/LLM ภายนอกช่วยอ่าน       ← 🔴 ต้องขออนุญาต user **รายครั้ง** ก่อนส่งเสมอ
```

🔴 **ข้อ ③ ต้องบอก user ให้ชัดก่อนส่งว่า "เนื้อหาอะไรจะออกจากเครื่อง"** (ชื่อไฟล์ · กี่หน้า ·
เป็นเอกสารประเภทไหน — สัญญา/งบการเงิน/TOR) → user ตัดสินรายครั้ง
· **ห้ามส่งเองโดยไม่ถาม เด็ดขาด** แม้ user เคยอนุญาตไฟล์อื่นมาก่อน (อนุญาตครั้งเดียว ≠ อนุญาตตลอด)
· ข้อ ② มักพอแล้วสำหรับงานส่วนใหญ่ — ลองก่อนเสมอก่อนเสนอข้อ ③

**R5 — pdf-inspector เป็น optional แต่แนะนำเปิดเสมอสำหรับ PDF**
มันไม่แปลงอะไร แค่บอกว่าไฟล์อ่านได้จริงไหม · ใช้เวลา ~1 ms/ไฟล์ · **ก่อนดูด PDF เข้าคลัง
เป็นชุด ให้รัน `--scan DIR` ก่อนเสมอ** จะรู้ทันทีว่ามีไฟล์ไหนอ่านไม่ครบ

---

# §3 ความสามารถและข้อจำกัดที่วัดมาแล้ว

## 3.1 anydoc — ตัวแปลง

| | ข้อมูลที่ตรวจสอบเอง 2026.08.06 |
|---|---|
| ฟอร์แมต | 16 นามสกุล: `.doc .docx .docm` · `.ppt .pptx .pptm` · `.xls .xlsx .xlsm` · `.odt .ods .odp` · `.rtf` · `.epub` · `.csv` · `.pdf` |
| ความเร็ววัดจริง | TOR ไทย 1.39 MB (ไทย 58%) = **163 ms** · xlsx = 2 ms · pptx = 8 ms |
| เทียบของเดิม | เร็วกว่า `python-docx` 1.4× **และได้ตาราง+โครงสร้าง Markdown ครบ** (python-docx ได้แต่ย่อหน้า) |
| ภาษาไทย | ✅ **สระอำ 3,842 ตัวรอดครบ · แตก 0 · วรรณยุกต์ลอย 0 · NFC ตรงเดิม** |
| License | MIT · Rust binary ในเครื่อง |

⚠ **ข้อจำกัด:** ไม่มี OCR — PDF ที่เป็นภาพล้วนจะโยน `UnsupportedError` (helper รับมือให้แล้ว → ไปขั้น ④)

## 3.1b OCR ในเครื่อง — macOS Vision (V01R02)

| | ข้อมูลที่ตรวจสอบเอง 2026.08.06 |
|---|---|
| เครื่องมือ | **macOS Vision framework** ที่มากับระบบ (ไม่ต้องติดตั้ง engine เพิ่ม · ไม่ใช่ cloud) |
| ภาษาไทย | ✅ **สระอำแตก 0 · วรรณยุกต์ลอย 0** (ทดสอบใบเสนอราคาสแกนจริงของ Viriyah) |
| ความเร็ว | ~1.75 วินาที/หน้า ที่ 200 dpi |
| ผลจริง | PDF สแกนที่ anydoc อ่านไม่ได้เลย → **ได้ 3,108 ตัวอักษร** |
| เงื่อนไข | ต้องสั่ง `--ocr` เอง (ไม่ทำอัตโนมัติ เพราะช้ากว่าปกติ ~1000 เท่า) · ต้องมี `pdftoppm` |

⚠ OCR คือ**การเดาตัวอักษรจากภาพ** — แม่นสูงแต่ไม่ 100% · ห้ามใช้เป็น citation verbatim
โดยไม่ตรวจสายตา · เหมาะกับ "เข้าใจเนื้อหา" มากกว่า "อ้างอิงคำต่อคำ"

## 3.2 pdf-inspector — ตัวคัดกรอง (optional แต่แนะนำ)

| | ข้อมูลที่ตรวจสอบเอง |
|---|---|
| จำแนก PDF | `text_based` / `scanned` / `image_based` / `mixed` + คะแนนความมั่นใจ |
| ⭐ ความสามารถหลัก | **บอกรายหน้าว่าหน้าไหนต้อง OCR** (`pages_needing_ocr` แบบ 0-indexed) |
| อื่น ๆ | หน้าไหนมีตาราง/คอลัมน์ · ดึงข้อความพร้อมพิกัด · ตรวจไฟล์เข้ารหัส |
| ความเร็ววัดจริง | **กวาด 205 ไฟล์ PDF ใน 0.26 วินาที** (~1 ms/ไฟล์) |
| License | MIT · Rust binary ในเครื่อง · ไม่มี ML model |

⚠ **ข้อจำกัดที่ตรวจพบเอง (ไม่อยู่ใน README):** `has_encoding_issues` **เชื่อไม่ได้กับภาษาไทย** —
ทดสอบกับ PDF ที่ CMap พังจริง (วรรณยุกต์กลายเป็น `ท1า` `จ@า`) มันรายงาน `False`
→ **ต้องใช้ตัวตรวจไทยของเราคู่กันเสมอ** (helper ทำให้แล้ว)

## 3.3 ตัวตรวจภาษาไทย — ส่วนที่เราเขียนเอง

| ตรวจอะไร | ระดับ | เหตุผล |
|---|---|---|
| **สระอำแตก** (นิคหิต+สระอา แทน U+0E33) | 🔴 fail | ชัดเจนไม่กำกวม · ค้นหา/copy พลาดแน่นอน |
| **วรรณยุกต์ลอย** (ตามหลังช่องว่าง) | 🔴 fail | ผิดเสมอในภาษาไทย |
| **CMap น่าสงสัย** (ไทย+ตัวเลข+ไทย ใน PDF) | ⚠️ flag ให้คนดู | **ไม่ fail** เพราะแยกไม่ได้ 100% ว่าเป็น CMap พังหรือคำพิมพ์ผิดในต้นฉบับ |

> **บทเรียนที่หล่อกฎข้อ 3 (QA 2026.08.06):** ตอนแรกผมตั้งเป็น fail แล้วมันฟ้อง `ย้อนหลัง4ปี`
> ซึ่งเป็น**ภาษาไทยปกติ** และฟ้อง `จำนว0น` ซึ่ง**พิสูจน์แล้วว่ามีอยู่ในไฟล์ต้นฉบับจริง** (ผู้เขียนพิมพ์ผิดเอง)
> → ลดเป็น flag + รันเฉพาะ PDF (docx/pptx/xlsx ไม่มี CMap — เอากฎ PDF ไปใช้ผิดที่)
> **หลักการ: ตัวตรวจที่ฟ้องของถูกว่าผิด ทำลายความน่าเชื่อถือของตัวตรวจทั้งชุด**

---

# §4 ตัวอย่างการใช้ตามบทบาท

**เสี่ยวป้อ — ดูดเอกสารลูกค้าเข้าคลัง**
```bash
# ① กวาดก่อนเสมอ — รู้ทันทีว่ามีไฟล์ไหนอ่านไม่ครบ
bash ~/.claude/agents/_lib/doc_to_md.sh --scan "Projects/PWA/26-ERP&HCM Project"
# ② แปลงทีละไฟล์เข้าคลัง + provenance
bash ~/.claude/agents/_lib/doc_to_md.sh "TOR.pdf" -o "00-Context/_retrieved/TOR.md"
```

**กัปตัน — อ่าน source ก่อนเขียน spec (D-P1 READ)**
อ่าน RFP/BRD/TOR ที่ลูกค้าส่งมา → Markdown → อ่านเองเต็ม ๆ ก่อนออกแบบ
· ถ้า exit 3 หรือมีหน้าต้อง OCR → **แจ้ง user ก่อนเริ่ม ไม่ใช่ตอนส่งงาน** (ASK-FIRST)

**สมนึก — อ่าน literature/บทความ**
`.pdf` วารสาร · `.epub` หนังสือ · `.docx` ต้นฉบับ → Markdown เข้า `90-Brain/`
⚠ citation ต้อง verbatim — ตรวจ exit code ก่อนใช้อ้างอิงทุกครั้ง (R2)

---

# §5 เมื่อเครื่องมือใช้ไม่ได้

| อาการ | ทำอย่างไร |
|---|---|
| `exit 4` ไม่พบ venv | สร้างใหม่: `python3.12 -m venv ~/.claude/agents/_lib/.venv-doc && ~/.claude/agents/_lib/.venv-doc/bin/pip install firecrawl-anydoc pdf-inspector` |
| PDF เป็นภาพสแกนทั้งไฟล์ | anydoc ช่วยไม่ได้ — แจ้ง user ว่าต้องใช้ OCR แยก (skill นี้ไม่มี OCR โดยเจตนา) |
| ฟอร์แมตนอก 16 นามสกุล | บอกตรง ๆ ว่าอ่านไม่ได้ · **ห้ามเดาเนื้อหา** |
| ไฟล์เข้ารหัส/มีรหัสผ่าน | `EncryptedError` → ขอไฟล์ที่ไม่ล็อกจาก user |

---

*Skill: ice-doc-reader V01R01 | 2026.08.06 | ขาเข้าของเอกสาร (คู่กับ ice-doc-builder = ขาออก)*
*เครื่องมือ: `_lib/doc_to_md.sh` + `_lib/doc_to_md.py` · venv `_lib/.venv-doc` (anydoc + pdf-inspector · MIT · local-only)*
