Plan — Fix klasifikasi dokumen pendukung Berakhirnya
Konteks: Reproduksi via Playwright (UI http://localhost:47023/klasifikasi, sample sample-berakhirnya, txn PT BIS 4026062431700115). Deteksi paket sudah benar (banner "Terdeteksi: Berakhirnya Status Badan Hukum PT", tombol "Lanjut ke Ekstraksi" aktif), tetapi 4 dari 6 dokumen pendukung salah lane.
1. Hasil reproduksi
| Dokumen | Seharusnya | GPU classifier | Conf |
|---|---|---|---|
| Salinan Akta Berakhirnya | AKTA_BERAKHIRNYA |
✅ AKTA_BERAKHIRNYA |
0.9998 |
| Keputusan Sirkuler | BERITA_ACARA_RUPS |
✅ BERITA_ACARA_RUPS |
0.9997 |
| Pengumuman Koran Likuidasi | BUKTI_PENGUMUMAN_149 |
❌ OTHER |
0.9999 |
| Pengumuman Koran Ps.152 | BUKTI_PENGUMUMAN_152 |
❌ SURAT_KETERANGAN_BANK |
0.9565 |
| Laporan Pertanggungjawaban Likuidator | LAPORAN_LIKUIDASI |
❌ BERITA_ACARA_RUPS |
0.9996 |
| Surat Permohonan Berakhirnya | SURAT_PERMOHONAN |
❌ AKTA_BERAKHIRNYA |
0.6617 |
2. Akar masalah
Model classifier GPU (ahu-doc-classifier, engine hands-off) tidak punya kelas untuk dokumen pendukung Berakhirnya, dan alih-alih abstain ia mengembalikan label lain dengan confidence tinggi (confidently wrong). Tier koreksi di repo ini (backend/src/routes/klasifikasi.ts) justru di-gate pada confidence rendah, jadi jaring pengaman tidak pernah aktif.
confidently wrong] --> RA[refineAktaLabel] RA --> RS{refineSupportingLabel} RS -->|"label AKTA_* / BERITA_ACARA_RUPS
→ return early"| OUT[label salah dipertahankan] RS -->|"confidence >= 0.6
→ return early"| OUT RA --> LT{letter-confirm LLM tail} LT -->|"confidence >= 0.6 ATAU
label AKTA_* → skip"| OUT OUT --> BOARD[Lane salah di board]
Tiga blocker konkret di klasifikasi.ts:
refineSupportingLabel(≈line 138):if (label.startsWith("AKTA_") || label === "BERITA_ACARA_RUPS") return label;laluif (confidence >= config.classifierMinConfidence) return label;
→ Laporan Likuidasi (GPUBERITA_ACARA_RUPS@0.9996) dobel-blokir.- Letter-confirm LLM tail (≈line 498):
if (confidence < minConfidence && !refinedClassification.startsWith("AKTA_"))
→ Koran (OTHER/BANK@≥0.95) diblokir confidence tinggi; Surat Permohonan (AKTA_BERAKHIRNYA) diblokir prefixAKTA_. refineAktaLabeltidak membedakan surat permohonan (yang menyebut "berakhirnya status badan hukum") dari akta-nya → menahanAKTA_BERAKHIRNYA.
Yang penting: suggestByKeyword (head-anchored LAPORAN/PERMOHONAN, axis _149/_152) + classifyBerakhirnyaSupportingViaLlm sudah dirancang untuk keempat dokumen ini — hanya tidak pernah terpanggil.
3. Perbaikan yang diusulkan (semua di repo ini, bukan engine)
Prinsip: jalankan re-examination dokumen-pendukung berdasarkan bentuk dokumen (head-anchored keyword), bukan bergantung confidence GPU. Aman karena suggestByKeyword return null untuk apa pun yang tak match pola, dan hanya hit autoAcceptable yang diadopsi otomatis; sisanya jadi suggestion chip (operator yang apply).
3a. Ungate refineSupportingLabel untuk label rawan-salah
Ganti gate confidence dengan allowlist label GPU yang diketahui salah untuk paket Berakhirnya: OTHER, BUKTI_TRANSFER-SURAT_KETERANGAN_BANK, SURAT_KETERANGAN_BANK, dan BERITA_ACARA_RUPS. Untuk label-label ini, jalankan classifySupportingDoc tanpa syarat confidence; adopsi hanya bila autoAcceptable (mis. LAPORAN_LIKUIDASI head-anchored @0.85).
- Buang/khususkan early-return label === "BERITA_ACARA_RUPS" supaya BAR bisa diperiksa ulang → hanya berubah jika head jelas laporan (rule head-anchored dicek pertama; BAR asli tak match).
- Confidence rendah tetap seperti sekarang (tidak ada regresi untuk flow lain).
3b. Ungate letter-confirm + BUKTI_PENGUMUMAN suggestion
Jalankan classifySupportingDoc({ llm }) untuk label rawan-salah tanpa syarat confidence < min, dan teruskan namaPerseroanHint agar axis _149/_152 ter-anchor ke box PT pemohon. Hasil:
- Koran → suggestion BUKTI_PENGUMUMAN + fineLabel _149/_152 (chip amber, bukan auto).
- Laporan → auto-adopt LAPORAN_LIKUIDASI (autoAcceptable).
3c. Surat Permohonan yang tertukar jadi AKTA_BERAKHIRNYA
Tambah pengecekan head-anchored SURAT_PERMOHONAN khusus saat label AKTA_BERAKHIRNYA: bila head cocok pola permohonan (suggestByKeyword → SURAT_PERMOHONAN) → keluarkan suggestion chip (jangan auto-flip; akta asli tak match pola head permohonan). Ini menutup gotcha "surat menyebut berakhirnya".
3d. (Opsional) Scoping paket
Karena classify jalan per-file (belum tahu ini paket Berakhirnya), scoping cukup dari spesifisitas rule head-anchored — tidak perlu sinyal paket. Jika mau ekstra hati-hati, gate 3a–3c hanya aktif ketika AKTA_TXN_CLASSIFIER_URL/berakhirnya-env tersedia (sudah default).
4. File yang disentuh
backend/src/routes/klasifikasi.ts—refineSupportingLabel, blok letter-confirm (≈498), tambah cabang SURAT_PERMOHONAN untukAKTA_BERAKHIRNYA.- (Kemungkinan)
backend/src/services/supporting-doc-classifier.ts— hanya bila perlu param baru; kemungkinan besar tak berubah. - Tes:
backend/src/routes/__tests__/*klasifikasi*+services/__tests__/supporting-doc-classifier.test.ts— tambah kasus "confidently-wrong GPU label → refine/suggest benar".
5. Risiko & mitigasi
- Regresi flow lain (pendirian/perubahan): rule head-anchored spesifik + adopsi hanya autoAcceptable → risiko rendah. Dijaga test suite existing.
- Koran & permohonan tetap suggestion-only (autoAcceptable:false) sesuai desain spec (operator authoritative) — bukan auto-adopt. Berarti operator masih 1 klik apply per dokumen; kalau mau full-auto perlu keputusan terpisah (naikkan confidence rule / auto-adopt koran) — butuh konfirmasi.
- Engine tidak disentuh (sesuai CONVENTIONS): fix murni di orchestrator repo.
6. Validasi
Jalankan ulang harness Playwright (.pw-scratch/run-berakhirnya.mjs) → target: 6/6 lane benar/ter-suggest; bunx tsc --noEmit; bun test untuk klasifikasi.
7. Keputusan yang aku butuh
- Koran & Surat Permohonan: auto-adopt atau suggestion-chip? (spec bilang suggestion-only; auto lebih mulus tapi menyalahi desain).
- Boleh ubah early-return
BERITA_ACARA_RUPSdirefineSupportingLabel(perlu untuk Laporan)?