Files
lcbp3/specs/200-fullstacks/235-ai-runtime-policy-refactor/checklists/cutover-validation.md
T
admin 0227b7b982
CI / CD Pipeline / build (push) Successful in 4m16s
CI / CD Pipeline / deploy (push) Successful in 11m51s
feat(ai-runtime): complete ai runtime policy refactor (ADR-035)
2026-06-12 08:07:15 +07:00

7.5 KiB

// File: specs/200-fullstacks/235-ai-runtime-policy-refactor/checklists/cutover-validation.md // Change Log: // - 2026-06-11: Initial cutover validation checklist for T032 and sidecar pytest

Cutover Validation Checklist: Feature 235

Purpose: ใช้ปิด T032 และเก็บหลักฐานสำหรับเลื่อนสถานะ validation จาก PARTIAL ไป PASS

หมายเหตุ

  • Checklist นี้อิง implementation ปัจจุบัน ของ Option B
  • อย่าใช้ตัวอย่างเก่าใน quickstart.md ที่ยังส่ง executionProfile / large-context จาก caller
  • คำสั่งด้านล่างเป็น PowerShell ตามกฎของ repo

1. Environment Ready

  • Backend รันที่ http://localhost:3001
  • Frontend รันที่ http://localhost:3000
  • OCR sidecar รันที่ http://192.168.10.100:8765
  • Ollama รันและมี tag np-dms-ai / np-dms-ocr
  • มี admin token สำหรับเรียก API
  • มี documentPublicId และ projectPublicId ที่มีอยู่จริงสำหรับทดสอบ rag-query
  • มีไฟล์ PDF ตัวอย่างสำหรับ OCR Sandbox

2. Automated Validation

2.1 Backend targeted tests

  • รัน:
pnpm --filter backend test -- --runInBand --testPathPatterns="ai.service.spec.ts|queue-policy.spec.ts|ai.controller.spec.ts|ai-policy.service.spec.ts|ocr-residency.spec.ts|vram-monitor.service.spec.ts"
  • Expected: ทุก suite ผ่าน

2.2 Backend build

  • รัน:
pnpm --filter backend build
  • Expected: build ผ่านไม่มี compile error

2.3 Sidecar pytest

  • รัน:
python -m pytest specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/tests -v
  • Expected: test_retrieval_fallback.py ผ่านครบ
  • ถ้า pytest ไม่พบ module: บันทึกว่า environment ยังไม่พร้อม และติดตั้ง dependency ก่อน rerun

3. Manual Gate 1: Policy Contract

ตั้งค่า token และ ids ก่อน:

$TOKEN = "<admin-jwt>"
$PROJECT_PUBLIC_ID = "<existing-project-public-id>"
$DOCUMENT_PUBLIC_ID = "<existing-document-public-id>"

3.1 Reject forbidden model

  • รัน:
$body = @{
  type = "rag-query"
  projectPublicId = $PROJECT_PUBLIC_ID
  payload = @{ query = "test policy contract" }
  model = @{ key = "typhoon2.5-np-dms:latest" }
} | ConvertTo-Json -Depth 5

Invoke-RestMethod "http://localhost:3001/api/ai/jobs" `
  -Method Post `
  -Headers @{
    Authorization = "Bearer $TOKEN"
    "Idempotency-Key" = "feature235-gate1-model"
    "Content-Type" = "application/json"
  } `
  -Body $body
  • Expected: HTTP 400

3.2 Reject forbidden executionProfile

  • รัน:
$body = @{
  type = "rag-query"
  projectPublicId = $PROJECT_PUBLIC_ID
  payload = @{ query = "test forbidden profile" }
  executionProfile = "quality"
} | ConvertTo-Json -Depth 5
  • Expected: HTTP 400

3.3 Reject forbidden parameter override

  • รัน:
$body = @{
  type = "rag-query"
  projectPublicId = $PROJECT_PUBLIC_ID
  payload = @{ query = "test forbidden temperature" }
  temperature = 0.9
} | ConvertTo-Json -Depth 5
  • Expected: HTTP 400

3.4 Valid rag-query

  • รัน:
$body = @{
  type = "rag-query"
  projectPublicId = $PROJECT_PUBLIC_ID
  documentPublicId = $DOCUMENT_PUBLIC_ID
  payload = @{ query = "สรุปเอกสารนี้" }
} | ConvertTo-Json -Depth 5

Invoke-RestMethod "http://localhost:3001/api/ai/jobs" `
  -Method Post `
  -Headers @{
    Authorization = "Bearer $TOKEN"
    "Idempotency-Key" = "feature235-gate1-valid"
    "Content-Type" = "application/json"
  } `
  -Body $body
  • Expected:
    • HTTP 201
    • modelUsed = "np-dms-ai"
    • effectiveProfile = "standard"
    • queueName = "ai-batch"

4. Manual Gate 2: Canonical Naming

4.1 Audit log check

  • ตรวจ row ล่าสุดใน ai_audit_logs
  • Expected:
    • effective_profile มีค่า
    • canonical_model เป็น np-dms-ai หรือ np-dms-ocr
    • ไม่มี runtime name หลุดออกในฟิลด์ user-facing

4.2 Admin Console check

  • เปิด http://localhost:3000/admin/ai
  • ตรวจ Overview / health / model cards
  • Expected:
    • เห็น np-dms-ai
    • เห็น np-dms-ocr
    • ไม่เห็น typhoon2.5-np-dms:latest
    • ไม่เห็น typhoon-np-dms-ocr:latest

4.3 OCR Sandbox badge check

  • เปิด OCR Sandbox ในหน้า admin AI
  • รัน OCR 1 รอบ
  • Expected:
    • badge หรือ result label แสดง np-dms-ocr
    • ไม่โชว์ runtime name โดยตรง

5. Manual Gate 3: Adaptive OCR Residency

5.1 High-pressure / deep-analysis behavior

  • ทำให้ main model กิน VRAM สูง หรือจำลอง workload ที่เข้าข่าย pressure
  • รัน OCR Sandbox หรือ OCR job
  • ตรวจ sidecar / backend logs
  • Expected:
    • keep_alive = 0
    • reason เป็น high-pressure หรือ deep-analysis-active

5.2 Headroom sufficient behavior

  • รัน OCR job ตอนที่ GPU headroom สูง
  • ตรวจ logs
  • Expected:
    • keep_alive > 0
    • reason เป็น headroom-sufficient

6. Manual Gate 4: Retrieval CPU Fallback

6.1 Force GPU pressure

  • warm model:
$warm = @{
  model = "np-dms-ai"
  prompt = "warmup"
  keep_alive = -1
} | ConvertTo-Json

Invoke-RestMethod "http://localhost:11434/api/generate" `
  -Method Post `
  -ContentType "application/json" `
  -Body $warm

6.2 Submit rag-query under pressure

  • ส่ง request แบบเดียวกับ Gate 1.4 แต่เปลี่ยน Idempotency-Key
  • Expected:
    • request enqueue สำเร็จ
    • job ไม่ fail hard

6.3 Verify fallback evidence

  • ตรวจ sidecar logs
  • Expected:
    • device=cpu หรือ device: cpu
    • reason เป็น gpu-headroom-below-threshold หรือ gpu-query-failed

7. Evidence to Attach

  • backend test output
  • backend build output
  • sidecar pytest output
  • screenshot หน้า /admin/ai
  • screenshot OCR Sandbox result
  • copy log line ของ residency decision
  • copy log line ของ CPU fallback
  • sample successful rag-query response body

8. Pass Criteria

  • Automated backend tests ผ่าน
  • Backend build ผ่าน
  • Sidecar pytest ผ่าน
  • Gate 1 ผ่านครบ
  • Gate 2 ผ่านครบ
  • Gate 3 ผ่านครบ
  • Gate 4 ผ่านครบ
  • หลักฐานถูกแนบหรือบันทึกไว้ใน feature folder

9. Follow-up After Completion

  • update tasks.md ให้ติ๊ก T032
  • update validation-report.md จาก PARTIAL เป็น PASS
  • ถ้าเจอ spec drift ให้ปรับ quickstart.md และจุดอ้างอิงที่ยังใช้ contract เก่า