Add application codebase: PDF annotation for e-Court

Next.js 14 + Drizzle/PostgreSQL + SSE realtime sync — highlight,
freehand, comment, bookmark + ฟีเจอร์ต่อยอด F1–F19 (edit/move, undo/redo,
shapes, redaction, export PDF/CSV, reply, resolve, search, summary,
textbox, stamp, version history)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2026-09-10 14:29:40 +07:00
parent 6fd0c3174f
commit eddcec28c7
60 changed files with 15055 additions and 0 deletions

View file

@ -0,0 +1,28 @@
---
name: implement-feat
description: Implement task F1–F19 จาก docs/PLAN-FEAT.md (แก้ไข/ย้าย A1, undo/redo A2, รูปทรง B1, redaction+export B4/C1, reply A4, resolve A5, ค้นหา/สรุป D1–D3) พร้อม verify ตามเกณฑ์ — ใช้ /implement-feat <F-number หรือ feature id เช่น A1>
argument-hint: "[F1–F19 หรือ feature id เช่น A1, B4]"
---
Implement task ที่ระบุใน arguments จากตาราง `docs/PLAN-FEAT.md` §4 (ถ้าไม่ระบุ ให้ถามก่อน)
## ขั้นตอน
1. **อ่านก่อนเสมอ:** `docs/PLAN-FEAT.md` ทั้งไฟล์ + `CLAUDE.md` (invariants) + rules ใน `.claude/rules/` ที่เกี่ยวกับไฟล์ของ task นั้น — แผนเปลี่ยนได้ อย่าจำจากครั้งก่อน
2. **Map argument → task:** รับได้ทั้ง `F<n>` และ feature id (A1, B4, C1, D2, E1, …) — หาจากตาราง §4 (B4 กับ C1 คือ task เดียวกัน F8 ตามข้อตกลง D4)
3. **ตรวจ dependency ตามคอลัมน์ "ต้องมีก่อน"** — ถ้ายังไม่มี ให้หยุดและแจ้งผู้ใช้ว่าต้องทำ task ใดก่อน (อย่าลัดขั้นตอนไป implement เอง)
4. **Implement เฉพาะสิ่งที่ task ระบุ ตามสเปกในแผนเท่านั้น** — ห้ามเพิ่ม feature, abstraction, หรือ "ความยืดหยุ่น" ที่แผนไม่ได้บอก; ทำตามข้อตกลง D1–D11 ใน §0 เสมอ
5. **แตะ schema (`db/schema.ts`):** รัน `/sync-db` หลังแก้ + เติม validation ใน `validateAnnotationData` ครบทุก type/case ใหม่
6. **Sync invariant/rules ตามตาราง §6 ของแผน** — แก้ CLAUDE.md/PLAN.md/`rules/*.md` ตามแถวของ task นั้น (นี่คือส่วนหนึ่งของงาน ไม่ใช่งานเพิ่มเติม)
7. **เจอ edge case ที่แผนไม่ครอบคลุม (ดู §5 ก่อน):** หยุดเขียนโค้ด → อัปเดต `docs/PLAN-FEAT.md` ก่อน (+ `CLAUDE.md` ถ้าเป็น invariant ใหม่) → ถ้าเป็นเรื่องที่ต้องตัดสินใจเชิงออกแบบ ให้ถามผู้ใช้ → ค่อยเขียนโค้ดตามที่ปรับแล้ว
8. **Verify ตามคอลัมน์ Verify จริง ๆ** — รัน `npx tsc --noEmit` ทุก task + `npm test` เมื่อแตะ `utils/` + รัน/ตรวจข้อที่ระบุ; ข้อที่ต้องทดสอบใน browser จริง (เช่น realtime 2 แท็บ, อุปกรณ์สัมผัส, เปิดไฟล์ export) ให้ระบุชัดว่า "ค้างทดสอบด้วยมือ: <รายการ>" อย่าเดาว่าผ่าน
9. **เรียก agent `plan-reviewer`** ตรวจโค้ดของ task นี้ — แก้เฉพาะข้อที่ reviewer ชี้และถูกต้องจริง
10. **สรุปตอนจบ:** ไฟล์ที่สร้าง/แก้, ผล verify แต่ละข้อ (ผ่าน/ไม่ผ่าน/ค้างทดสอบมือ), invariant/rules ที่ sync ไป, สิ่งที่ต้องทำต่อ (task ถัดไปที่ปลดล็อก)
## ข้อห้าม
- ห้าม implement task อื่นรวมด้วย ("ขอทำเพิ่ม" ไม่ใช่ข้ออ้าง) — เดินตามลำดับ F1→F19
- ห้ามแยก B4 (redaction) ออกจาก C1 (export) — เป็น task เดียวกัน (F8) ตามข้อตกลง D4
- ห้าม mark ว่า verify ผ่านโดยไม่ได้รันจริง
- ห้ามบันทึกพิกัด px ลง DB — ทุก type ใหม่เป็น % ของขนาดหน้า (invariant #2)
- ห้ามเขียน/แก้ไฟล์ PDF ต้นฉบับ — export สร้างไฟล์ใหม่เท่านั้น (invariant #1)

View file

@ -0,0 +1,22 @@
---
name: implement-task
description: Implement task ตามลำดับใน docs/PLAN.md §7 (1 Scaffolding+Schema → 2 Coordinate helpers → 3 Server Actions → 4 Realtime hook → 5 UI หลัก → 6 README) พร้อม verify ตามเกณฑ์ของ task นั้น — ใช้ /implement-task <หมายเลข 1-6>
argument-hint: "[หมายเลข task 1-6]"
---
Implement task หมายเลขที่ระบุใน arguments จากตาราง `docs/PLAN.md` §7 (ถ้าไม่ระบุ ให้ถามก่อน)
## ขั้นตอน
1. **อ่านก่อนเสมอ:** `docs/PLAN.md` ทั้งไฟล์ + `CLAUDE.md` (invariants) + rules ใน `.claude/rules/` ที่เกี่ยวกับไฟล์ของ task นั้น
2. **Implement เฉพาะไฟล์ที่ task ระบุ ตามสเปกแผนเท่านั้น** — ห้ามเพิ่ม feature, abstraction, หรือ "ความยืดหยุ่น" ที่แผนไม่ได้บอก (อ้าง Task order: ทำทีละ task ไม่กระโดด)
3. **เจอ edge case ที่แผนไม่ครอบคลุม:** หยุดเขียนโค้ด → อัปเดต `docs/PLAN.md` ก่อน (+ `CLAUDE.md` ถ้าเป็น invariant ใหม่) → ถ้าเป็นเรื่องที่ต้องตัดสินใจเชิงออกแบบ ให้ถามผู้ใช้ → ค่อยเขียนโค้ดตามที่ปรับแล้ว
4. **Verify ตามคอลัมน์ Verify ของ task นั้นจริง ๆ** — รันคำสั่งจริง ตรวจผลลัพธ์จริง ถ้ามีข้อที่ต้องทดสอบด้วยมือใน browser ให้ระบุชัดว่า "ค้างทดสอบด้วยมือ: <รายการ>" — ถ้า task แตะ `utils/` ให้รัน `npm test` (vitest — pure utils) เสมอ
5. **เรียก agent `plan-reviewer`** ตรวจโค้ดของ task นี้ — แก้เฉพาะข้อที่ reviewer ชี้และถูกต้องจริง
6. **สรุปตอนจบ:** ไฟล์ที่สร้าง/แก้, ผล verify แต่ละข้อ (ผ่าน/ไม่ผ่าน/ค้างทดสอบมือ), สิ่งที่ต้องทำต่อใน task ถัดไป
## ข้อห้าม
- ห้าม implement task ถัดไปด้วย ("ขอทำเพิ่ม" ไม่ใช่ข้ออ้าง)
- ห้ามเปลี่ยนไฟล์ของ task อื่นที่ไม่เกี่ยวกับ task นี้
- ห้าม mark ว่า verify ผ่านโดยไม่ได้รันจริง

View file

@ -0,0 +1,17 @@
---
name: sync-db
description: Sync Drizzle schema ลง PostgreSQL container judes-note-db + seed ไฟล์ตัวอย่าง — ใช้หลังแก้ db/schema.ts หรือตอน setup ครั้งแรก
---
## ขั้นตอน
1. **Push schema:** รัน `npx drizzle-kit push` (อ่าน config จาก `drizzle.config.ts`) — รายงาน output จริง ถ้าชนของเดิมให้แสดงและถามผู้ใช้ก่อน destructive ทางเลือก
2. **Seed ตัวอย่าง (เฉพาะเมื่อตาราง `files` ว่าง):** INSERT ไฟล์จาก `public/samples/` โดย `pdf_url = '/samples/<ชื่อไฟล์>'` (ไฟล์และที่มาดูใน PLAN.md §0 ตาราง "ไฟล์ตัวอย่าง") — ใช้ SQL จาก README ถ้ามีแล้ว รันผ่าน `docker exec judes-note-db psql -U postgres -c "..."`
3. **รายงานผลแต่ละขั้นตามจริง** — ขั้นไหนไม่ได้ทำบอกสาเหตุ อย่าเดา
## ข้อควรระวัง
- `DATABASE_URL` ชี้ที่ container `judes-note-db` (postgres:17-alpine, พอร์ต 54322 — ไม่ใช่ Supabase) — ถ้า container ไม่รันอยู่ ให้สั่ง `docker start judes-note-db` หรือแจ้งผู้ใช้ตามคำสั่ง docker run ใน README
- ห้ามลบ volume `judes-note-db-data` เว้นแต่ผู้ใช้สั่งชัดเจน (มีข้อมูล annotation จริงหายได้)
- ไม่ต้องตั้ง realtime publication/replica identity อีกต่อไป (SSE sync ผ่าน `lib/annotate-events.ts` ไม่ผ่าน DB trigger)