Refactor tidak bergejala — kesalahan Claude tak terlihat. Tiga pengaman: test, commit atomik, klik manual.
Refactor adalah tugas di mana Claude paling berbahaya. Bug punya gejala — tombol tidak bereaksi, nilai undefined, stack trace — jadi kamu bisa tahu apakah perbaikan Claude benar. Refactor tidak. "Masih jalan" bisa berarti "test masih pass" sementara perilaku diam-diam berubah, kamu tidak sadar, dan production meledak seminggu kemudian.
Baru-baru ini saya melakukan refactor yang cukup besar dengan Claude di how2claude: memigrasi pembayaran kripto x402 dari PaymentHandler + FacilitatorClient buatan sendiri (139 baris) ke gem x402-rails, dan sekaligus mengekstrak pemetaan field Purchase.create! / Subscription.create! — yang terduplikasi di dua controller — ke method kelas model. Satu commit, 4 file diubah, 2 dihapus, 2 ditambah.
Prompt saya satu kata: "refactor."
Bisa sesingkat itu karena ada pengaman di sekitarnya.
Saat branch ini sampai ke titik itu, ada 221 test. Semua path kritis di alur pembayaran tertutup.
Tindakan default Claude sebelum refactor bukan "lihat test dulu." Jadi saya suruh dia jalankan bin/rails test dulu, pastikan hijau, baru menyentuh apa pun.
Setelah refactor, jalankan lagi. Masih hijau. Itu bukan berarti tidak ada regresi — itu berarti perilaku yang diketahui tidak rusak.
Kalau codepath kamu tidak punya cakupan test, suruh Claude tulis test minimal yang mengunci perilaku sekarang. Jalankan, commit. Setelah itu refactor. Kalau tidak, yang dia lakukan bukan refactor, itu rewriting — dan kamu tidak punya cara memverifikasi ekivalensi.
Refactor ini sebenarnya dua hal:
Purchase / Subscription: controller → method kelas modelAda yang ketiga di frontend: menulis ulang alur signing sisi JS dengan viem + x402-fetch.
Saya suruh Claude pecah berdasarkan batas alami: backend + ekstraksi model satu commit (9f3e239), frontend commit terpisah (93746d8). Setiap commit membawa deskripsi lengkap, daftar file, dan alasan perubahannya.
Keuntungan:
- Diff tetap mudah dibaca. Satu commit, satu hal.
- Granularitas rollback. Kalau production kena bug frontend, git revert 93746d8 hanya rollback frontend, backend tetap.
- Perhatian Claude sendiri tetap fokus. Satu commit satu hal — perhatiannya juga hanya meliputi hal itu.
Setelah refactor selesai, saya suruh Claude berhenti dan tunjukkan git diff --staged. Jangan jalankan test. Jangan jalankan app. Baca diff dulu.
Sinyal yang saya pindai:
app/services/x402/payment_handler.rb dihapus seluruhnya — oke, itu tujuan dari migrasi ke gem. Tapi kalau dia menghapus sesuatu yang tidak saya minta disentuh, saya berhenti dan tanya.Purchase.create!(wallet_address: verify_result["payer"], ...) → Purchase.record_x402!(payment:, settlement:) sekarang membaca payment[:payer]. Sumbernya berubah (request.env dari gem vs return value client lama), tapi field-nya harus dipetakan satu-satu.Jebakan 1: Stimulus controllers gem diam-diam tidak ter-load
Gem x402-rails membawa Stimulus controllers sendiri. Claude menulis kode, test hijau semua. Saya klik manual tombol bayar — tidak bereaksi.
Alasan: config/importmap.rb punya pin untuk @hotwired/stimulus yang menunjuk ke file vendor yang tidak ada, dan importmap diam-diam membuang pin itu. Controllers dari gem tidak pernah ter-load. Test tidak bisa menangkap ini karena bin/rails test tidak mengeksekusi JS.
Jebakan 2: YAML mem-parsing 0x... sebagai integer
wallet_address: 0x833589... — tanpa kutip. YAML melihat awalan 0x, membacanya sebagai integer heksadesimal. Facilitator menerima non-string dan menolak. Claude tidak berhenti memikirkan aturan parsing YAML saat menulis config.
Kedua jebakan ketangkap karena saya meng-klik tombol beneran. Test pass bukan sama dengan fitur bekerja. Verifikasi manual setelah refactor tidak opsional.
Refactor adalah skenario "biarkan Claude yang nyetir" dengan risiko tertinggi. Pengaman bukan untuk Claude. Itu untukmu — supaya saat Claude salah, kamu menangkapnya dalam 5 menit, bukan saat kebakaran di production.