Bug ini ketemu bukan karena ada yang lapor, tapi karena saya menjalankan alur claim dari ujung ke ujung lewat Playwright MCP pada 2 Juli, lengkap dengan klik tautan verifikasi di Gmail sungguhan. Alurnya untuk sebuah situs keanggotaan: pengguna mengajukan claim atas sebuah profil, dapat token verifikasi, klik tautan di email, staf diberi tahu, lalu staf membuka post claim di wp-admin dan menyetujuinya lewat metabox "Claim review". Setelah approve, fungsi penautan profil jalan dan profil itu resmi punya pemilik.
Semua tahap sebelum staf berjalan mulus. Begitu saya membuka post claim di wp-admin, metabox "Claim review" tidak ada. Bukan kosong, bukan error, benar-benar tidak dirender. Artinya staf sama sekali tidak bisa menyetujui claim, karena tombol approve-nya tinggal di dalam kotak itu. Sesi QA itu menemukan tiga bug baru, dan yang ini yang paling memalukan, karena akarnya cuma satu argumen yang bergeser.
Kenapa ini terjadi
Tema ini sengaja memakai metabox yang ditulis tangan, bukan ACF, sebagai konvensi. Jadi registrasinya add_meta_box() polos di dalam berkas alur claim. Urutan parameter fungsi itu menurut dokumentasi adalah $id, $title, $callback, $screen, $context, $priority. Pemanggilan yang rusak melewatkan $screen dan langsung menaruh context dan priority, kira-kira seperti ini:
add_meta_box(
'mship_claim_review',
'Claim review',
'mship_render_claim_review',
'side',
'high'
);Yang saya maksud 'side' adalah context, kotaknya mau ditaruh di sidebar. Yang dibaca WordPress adalah $screen = 'side' dan $context = 'high'. Metabox terdaftar untuk sebuah screen yang secara harfiah bernama "side". Screen itu tidak pernah ada di wp-admin, jadi kotaknya tidak pernah dipanggil untuk dirender di mana pun.
Bagian yang membuat bug ini awet adalah add_meta_box() tidak memvalidasi apa pun. Nama screen yang tidak dikenal diterima begitu saja, context 'high' yang bukan nilai sah juga diterima. Tidak ada notice, tidak ada warning. Kode PHP-nya valid, php -l senang, dan halaman edit post claim tampil normal, hanya saja tanpa kotak yang paling penting. Kalau tidak ada yang mencoba benar-benar menyetujui claim sampai tuntas, bug ini bisa tinggal berbulan-bulan.
Perbaikannya
Kirim null untuk $screen, lalu geser context dan priority ke posisi yang benar:
add_meta_box(
'mship_claim_review',
'Claim review',
'mship_render_claim_review',
null,
'side',
'high'
);Dengan null, WordPress memakai screen yang sedang aktif saat pemanggilan. Kalau mau lebih eksplisit, nama post type juga bisa dikirim langsung di posisi $screen. Intinya sama: posisi keempat harus terisi sesuatu yang bermakna screen, jangan dilompati.
Selagi kotaknya dibuka lagi, saya tambahkan satu baris peringatan konflik yang terlihat langsung di dalam metabox. Kalau claim ini menyasar profil yang sudah punya pemilik, kotak menampilkan pemilik yang tercatat di meta _mship_claim_conflict beserta keterangan "NOT transferred", supaya staf tahu approve mereka tidak akan memindahkan kepemilikan. Nama akun yang tampil di baris "Matching account" maupun di peringatan itu diambil lewat helper display name, bukan slug login acak, karena saya sendiri sudah pernah mengeluh melihat slug itu di email.
Perbaikan ini di-deploy langsung lewat SSH dan di-commit bersama dua bug lain dari sesi QA yang sama: time-trap formulir yang rusak di halaman yang di-cache Cloudflare karena timestamp-nya terpanggang di HTML melewati jendela 1800 detik, dan tautan "View profile" di halaman akun yang mengarah ke rute editorial alih-alih rute profil komersial. Tiga bug, tiga penyebab berbeda, satu commit.
Yang saya verifikasi setelahnya
Setelah kotaknya tampil, saya ulangi approve dari wp-admin dan periksa peta kepemilikannya. Post claim menyimpan ID user yang ditautkan, profil menyimpan ID pemilik, flag claimed, dan post_author yang sama, lalu user menyimpan ID profilnya. Semua saling menunjuk.
Skenario konflik ikut diuji: claim dari user kedua atas profil yang sudah dimiliki, kalau disetujui, menulis _mship_claim_conflict berisi pemilik lama, tidak memindahkan kepemilikan, dan peringatan staf tampil di kotaknya. Penulisan kepemilikan sendiri dilakukan dari hook save_post_mship_claim dan dijaga current_user_can('edit_post'), jadi selalu ada manusia di wp-admin yang menekan approve, tidak pernah otomatis.
Satu catatan jujur: sehari kemudian, 3 Juli, ada bug lain di metabox yang sama. Approve pertama di metabox itu tidak pernah tersimpan, statusnya tetap verified, dan metabox tidak memberi umpan balik apa pun. Itu bug terpisah dari soal argumen 'side' ini, tapi polanya serupa: kotak yang gagal diam-diam.
Pelajaran
add_meta_box() punya enam parameter posisional dan tidak satu pun divalidasi. Melompati $screen tidak menghasilkan galat, hanya metabox yang terdaftar ke screen fiktif dan tidak pernah tampil. Kalau sebuah kotak admin hilang tanpa jejak, hitung argumennya dulu sebelum mencurigai hook atau capability.
Yang lebih penting: bug ini baru ketemu karena alurnya dijalankan sampai tahap manusia, bukan berhenti di "email terkirim". Tahap approve staf adalah tahap yang paling jarang diklik saat pengembangan, dan justru di situ kotaknya tidak ada.