Skip to content

File .rejected: Keputusan Manusia Kalahkan Status Otomatis

Adityo Guni Waluyo

Registri topik riset saya cuma punya status turunan, sampai file .rejected ngasih keputusan manusia tempat di rantai prioritas.

Ringkasan

Jadi gini, registri topik riset nggak punya tempat buat keputusan tolak, jadi topik yang udah ditolak manual tetep nongol mulu. Solusinya gampang: bikin file .rejected yang ditulis manual, tool cuma boleh baca dan nampilin alasannya. Ini sejalan sama pola rustup, pyenv, nvm, dan git: mesin boleh usul, tapi keputusan manusia harus dihormati dan kelihatan.

Pagi tadi saya jalankan ulang scan buat registri topik riset, dan topik yang keputusannya udah saya ambil manual tetap nongol di daftar kandidat. Tebakan pertama saya klasik: pasti generator JSON-nya salah parse. Saya cek, nggak ada yang rusak. Masalahnya justru kebalikannya. Registri cuma punya status turunan (draft, skilled dari file penanda .converted) dan nggak punya satu slot pun buat keputusan "topik ini saya tolak". Derivasi mesin jadi satu-satunya sumber kebenaran, dan keputusan manusia nggak dikasih tempat duduk.

Perbaikannya cuma satu file kecil: .rejected di dalam folder topik. Isinya bebas, ditulis manusia, dan tool nggak pernah menulisnya sendiri. Pas scan nemu file itu, status topik berubah jadi rejected, isinya masuk ke field rejected_reason, lalu tampil di output show. Sengaja saya bikin nggak retroaktif: topik lama tetap draft. Backfill belasan folder lama buat keputusan yang konteksnya udah berganti itu kerjaan kosong.

Cara bacanya juga udah kebayang dari awal. Output show sekarang punya satu status lagi di urutan paling bawah, dan kolom catatan buat topik rejected nggak lagi nampilin catatan lama, tapi alasan penolakan yang saya tulis sendiri. Skrip penghitung yang biasa saya pakai buat ngecek sinyal konversi juga otomatis melewati topik rejected, jadi angka sinyal nggak digelapkan sama topik yang memang udah mati.

Rantai preseden yang ditulis apa adanya

Ngubah keputusan manusia jadi data yang dihormati ternyata bukan ide aneh. Ekosistem tooling udah lama kebagian jatah ini. rustup misalnya, mendokumentasikan urutan prioritas toolchain secara eksplisit dalam lima tingkat: shorthand di command line, variabel lingkungan, directory override, file rust-toolchain.toml, lalu toolchain default. Yang pertama ketemu, dia yang menang [1].

pyenv pakai pola serupa buat memilih versi Python: variabel PYENV_VERSION kalahin file .python-version di direktori sekarang, yang kalahin file versi di folder induk, sampai akhirnya ke file versi global [2]. nvm nggak jauh beda; kalo nggak ada versi yang dikasih di command line, dia ambil dari file .nvmrc, dan pencariannya jalan naik ke folder-folder induk [3].

Bahkan git ikutan. Pas memutuskan sebuah path diabaikan apa nggak, git ngecek pola dari beberapa sumber dengan urutan prioritas yang didokumentasikan, dan di dalam satu tingkat, pola yang cocok terakhir yang menang [4]. Aturan di registri saya sebenernya versi ringkasnya: .rejected mengalahkan .converted, dua-duanya mengalahkan draft kosong. Bedanya cuma satu, saya nggak punya env var dan folder induk, jadi rantainya pendek.

Marker itu ekspresi keputusan, bukan output

Ada godaan biarin tool nulis file penanda secara otomatis. Maintainer nvm pernah ditanya hal serupa: apa nvm use sekalian nulis .nvmrc secara default. Jawabannya nggak, dan alasannya tajam: orang yang pakai nvm belum tentu mau versi yang sama dipakai developer lain di proyek itu [5]. File penanda itu ekspresi keputusan. Kalo ditulis mesin, dia bukan keputusan lagi, cuma sisa efek samping.

Di registri saya konsekuensinya konkret. File .rejected cuma bisa muncul karena saya nulis manual, lengkap dengan tanggal dan alasan bebas. Formatnya nggak ada yang rumit: tanggal, spasi, sisanya teks bebas. Konvensi lama file .converted nyimpen tanggal plus jumlah file; jumlah file itu sengaja nggak saya tiru, karena yang penting di sini bukan datanya, tapi keputusannya. Tool cuma boleh baca, nggak boleh nulis. Field rejected_reason juga tampil di output, jadi pas beberapa minggu lagi saya lupa kenapa sebuah topik ditolak, alasannya ada di tempat keputusannya disimpan.

Override yang lolos dalam diam itu bom waktu

Pelajaran kedua datang dari rustup. Tim Ratatui punya CI yang pasang toolchain beta lewat action, sementara repo mereka punya rust-toolchain.toml yang isinya lain. Yang menang si file, dan kekalahannya itu senyap, pesannya cuma level info yang gampang banget kelewat [6]. Mereka minta pesan itu dinaikin jadi warning, biar override kelihatan sebelum makan waktu orang berjam-jam.

Dari situ saya ngunci aturan mainnya: override boleh, tapi nggak boleh diam. Pas show nemu status rejected, dia nggak cuma skip topik itu, tapi nampilin alasannya di kolom catatan. Kalo suatu saat file .rejected nutupin status .converted yang ternyata masih relevan, saya mau lihat konfliknya di permukaan, bukan nemunya bertahun-tahun kemudian.

Mesin boleh usul. Manusia yang veto. Dan veto itu harus kelihatan, bukan bisikan yang hilang di antara baris kode.

Sources

[1] https://rust-lang.github.io/rustup/overrides.html

[2] https://github.com/pyenv/pyenv/blob/master/README.md

[3] https://github.com/nvm-sh/nvm/blob/master/README.md

[4] https://git-scm.com/docs/gitignore

[5] https://github.com/nvm-sh/nvm/issues/2849

[6] https://github.com/rust-lang/rustup/issues/4504

Artikel terkait