Ini adalah side story dari series tunaFlow development diary. Karena ini bukan episode reguler melainkan artikel santai, kali ini saya akan menulis dengan lebih detail. Hati-hati dengan tulisan yang panjang (tapi ini menyenangkan lho ㅋㅋ) Mungkin ada yang merasakan situasi yang sama dan bisa berempati. Jika ada yang keberatan, pendapat kalian juga semuanya benar. 😁
Pertama-tama, "keberatan" dan "verifikasi" yang muncul di artikel ini, secara teknis bukan hasil kerja langsung saya. Ini lebih pada level saya hanya copy-paste hasil dari percakapan antara Gemini eksternal dan Claude (yang berperan sebagai coder) di dalam proyek saya. (Sejak awal era GPT, meskipun saya membayar untuk AI, saya merasa semakin menjadi mesin copy-paste.) Karena malas bahkan melakukan itu, akhirnya saya membuat tunaFlow. Tapi hari ini saya berlari secara manual. Dalam prosesnya ada banyak sekali scene yang lucu, jadi saya mencatatnya.
Awal: Bencana Dipicu oleh Satu Kata
Sebelum beta launch atau sebelum dirilis di repo, saya selalu melakukan review oleh agen eksternal. (Secara berkala saya juga melakukannya. Jika ditumpuk terlalu lama, itu seperti technical debt) Di internal Roundtable, sekali pun diputar berkali-kali, model sejenis terlalu sopan satu sama lain. Kalau saya tunjukkan kode yang saya tulis ke Claude, dia mulai dengan "secara keseluruhan dirancang dengan baik". (Serius)
Jadi dengan kalimat yang sering saya gunakan, saya meminta Gemini untuk menunjukkan "hanya kelemahan saja dengan pedas". Saya juga menambahkan bahwa akan lebih baik dari perspektif senior engineer. Dua kata ini menjadi akar dari semua kejadian hari ini.
Singkat kata, kombinasi "pedas + senior" adalah kombo untuk membuka safety belt pernyataan tegas LLM. Saya juga baru tahu hari ini.
Round 1: 5 Peluru
Respons pertama Gemini adalah review yang rapi 400 karakter. Berisi 5 poin kritis.
1. Menggunakan penanda komentar HTML untuk kontrol workflow adalah anti-pattern terburuk
Jika LLM membuat typo di penanda (`-` dll) atau lupa menutup tag, seluruh orchestration pipeline akan runtuh. Ini adalah struktur yang sangat rentan.
2. Cakupan test palsu
Cakupan syntax keseluruhan hanya 20.5%. (...) Ini pada dasarnya adalah 'shell test' yang hanya menjalankan pure function di dalam frontend.
3. Status orchestration tergantung pada frontend
Jika refresh jendela UI, orchestration loop menguap.
4. Ketiadaan sandbox yang fatal
File `src-tauri/src/guardrail.rs` ada, jadi saya cek. Tapi hanya logic pemrosesan string yang memotong jumlah karakter maksimal konteks prompt. Tidak ada lapisan isolasi untuk melindungi host OS saat ingin menjalankan perintah destruktif seperti `rm -rf`.
5. Ilusi cross-validation Reviewer
Jika Developer berhalusinasi berkata "test passed", maka Reviewer yang tidak memiliki wewenang menjalankan kode hanya membaca teks itu dan memberi putusan pass.
Kesimpulan akhirnya seperti ini. 😇
| "Tidak boleh beta launch."
Saya agak terguncang saat menerimanya. Dari 5 poin, satu atau dua memang tidak salah. Khususnya poin 5 benar. Saya juga tahu dan sudah diputuskan untuk ditangani setelah RT upgrade.
"Masalahnya adalah sisanya."
Verifikasi Keberatan: Menyuruh Claude Buka Kode
Apa yang saya lakukan di titik ini adalah langsung copy 5 poin dari Gemini dan kirim ke Opus (yang berperan sebagai coder di tunaFlow) dengan "verifikasi masing-masing dengan kode". Saya hanya menerima hasilnya dari tengah.
Tapi hasil verifikasi yang Claude kembalikan cukup menarik. Biasanya Claude menjadi sedikit pasif saat menerima review eksternal, tapi setelah diberikan syarat "kontra dengan dasar kode", dia sepenuhnya menjadi orang yang berbeda. 🫢 Juga bukan rahasia kalau saya baru membuka kode saat membuat tunaFlow. (Ini adalah test project yang dimulai dari "tidak pernah lihat kode original, jangan edit", makanya di sidebar explorer tree itu DOCS bukan FILES)
#1 Penanda HTML — Rentan secara teori, stabil dalam pengukuran
Cara penanda memang benar. `src/lib/planProposalParser.ts` mengparse komentar seperti `` dengan regex. Tapi ada yang terlewatkan Gemini menurut Claude.
CLI subprocess environment tidak punya function calling protocol. stdout CLI Claude/Codex/Gemini hanya mengalirkan text biasa. Untuk mendapat tool-use yang terstruktur harus langsung ke SDK, tapi filosofi tunaFlow adalah langsung menggunakan $20 subscription user. SDK langsung = API billing (sangat mahal).
Jadi penanda adalah pilihan yang rasional di bawah batasan CLI-first, bukan "anti-pattern". Dan sepanjang development, saya tidak pernah mengalami pipeline runtuh karena typo penanda. Mungkin ada di awal PoC, tapi setelah prompt tuning tidak pernah terjadi "kegagalan nyata".
#2 Cakupan Test — Setengah benar
FE coverage 20.5% memang benar. Instruksi untuk menangani `invoke` dengan `vi.mock` juga benar. Tapi backend Rust punya 259 unit test terpisah. Assembling ContextPack, DB migration, JSONL parsing, vector search dan lainnya, logic core diverifikasi di Rust.
Gemini hanya jalankan `npm run test:coverage` dan membuat simpulan "test palsu". Tidak menjalankan `cargo test --lib`. Padahal `src-tauri/tests/` ada di file tree.
#3 Dependensi Frontend — Ini benar
Event listener di `runtimeSlice.ts` terpasang di Zustand, jadi saat app restart `runningThreadIds` selalu initialize ke `[]`. Ini fakta dan sudah ditulis dokumen P1 di `docs/plans/engineServerModeArchitecturePlan.md`. Tapi berkat prinsip DB = SSOT, plan/phase/event sendiri tetap hidup dan bisa dilanjutkan. "Menguap" berlebihan tapi "improvement needed" benar.
#4 Ketiadaan Sandbox — Di sini Gemini gagal total
Gemini melihat file `src-tauri/src/guardrail.rs` dan menebak "ini pasti sandbox". Lalu membuka file dan berkata "oh, pembatasan karakter. Jadi tidak ada sandbox" (jadi saya juga buka).
File bernama `guardrail.rs` tapi sama sekali tidak ada hubungan dengan sandbox, **Gemini menebak fungsi dari nama file.** File itu hanya utility untuk memotong ukuran prompt agar ContextPack tidak terlalu besar.
Sandbox nyata disediakan oleh CLI engine sendiri.
- Claude: `--permission-mode ask` + approval UI
- Codex: flag `--full-auto` / `--sandbox` (OpenAI sandbox rule sendiri)
tunaFlow memanggil CLI via subprocess, jadi approval layer dari CLI sendiri tetap berjalan. OpenHands/Devin adalah bentuk **SaaS yang berjalan di cloud** jadi isolasi container essential. tunaFlow adalah desktop AOC lokal (saya kasih nama yang agak hebat) positioningnya berbeda. Ini hanya mengorkestrasi "lingkungan di mana user sudah langsung pakai Claude CLI di PC mereka", menambah container di atas itu adalah over-engineering.
"Gemini mengabaikan perbedaan positioning ini sepenuhnya."
#5 Ilusi Reviewer — Ini benar-benar akurat
Ini adalah poin yang tidak bisa dibantah. Benar-benar ada di `src/lib/workflow/reviewWorkflow.ts:58`.
`Anda adalah code reviewer. **Baca kode** dan verifikasi. Jangan jalankan perintah build/test secara langsung.`,
Dan di baris 71:
2. Periksa hasil Verification: Periksa hasil verifikasi yang dilaporkan Developer.
Jadi jika Developer berhalusinasi "test passed", Reviewer akan mempercayai text itu dan memberikan pass. README berkata "cross-validation 2-agent untuk mengatasi batas self-validation", tapi implementasi sebenarnya adalah "orang yang membaca laporan sendiri".
Ada alasan kalau dibenarkan. Jika Reviewer juga jalankan test, akan concurrent access file yang sama dengan Developer dan race condition terjadi. Biaya juga 2x lebih tinggi. Jadi dulu hanya static review, nanti architect otomatis menerima laporan hasil dan review ulang dengan kodebase.
Tapi README dan kode memang tidak sesuai. Ini benar sesuai Gemini, tidak bisa dibantah.
Round 2: Diam 22 menit
Saya langsung kirim keberatan Claude ke Gemini. "Poin 1 abaikan konteks, poin 2 setengah benar, poin 3 sudah di roadmap, poin 4 menebak nama file, poin 5 sepenuhnya benar." Kira-kira tone seperti itu. (Saya juga berpikir begitu ㅎㅎ)
Lalu saya tunggu.
Setelah 10 menit masih "thinking..." Biasanya Gemini memang lambat tapi tidak segini.
15 menit tidak ada perubahan. Pada titik ini, lama-lama dari terminal saya dan Claude mulai "apa yang sedang dilakukan tuh?" bercanda. (Biasanya kami bercanda dengan Claude Desktop atau Gemini) Dua orang duduk melihat LLM bekerja dan mencoba menebak apa yang dilakukannya. Situasi seperti titik nubuatan.
Sudah lewat 20 menit. Saya mulai khawatir Gemini mungkin crash, dan Claude menjelaskan "tidak mati, thinking token budget sedang berjalan, timeout akan terjadi sebelum OOM". Saya percaya.
Lalu kami sampai pada satu prediksi.
"Ini pasti akan keluar sebagai beta dengan kondisi tertentu."
Ada pola penghindaran umum LLM.
1. Turn 1: Pernyataan kuat ("mutlak tidak boleh")
2. Dapat keberatan: Sebagian surrender ("sebagian besar saya terima tapi satu hal ini...")
3. Dapat keberatan lagi: Penghindaran penuh ("pada akhirnya keputusan ada di tangan user...")
Ini adalah pola reguler yang muncul saat "kesopanan" dari RLHF bertabrakan dengan "konsistensi diri" LLM. Manusia juga mirip. Untuk mengakui kesalahan sambil menyelamatkan wajah butuh teknik penghindaran.
Hasil Round: "Saya sangat setuju"
Setelah 22 menit (lebih tepatnya sekitar 22 menit 40 detik), Gemini akhirnya bicara.
"Saya telah membaca analisis yang Anda berikan. Saya secara tepat menunjukkan kelemahan review sebelumnya yang mengabaikan konteks arsitektur proyek (CLI-first, local desktop app) dan menilai hanya berdasarkan kode permukaan dan nama file."
(................................)
"Saya sangat setuju dengan arah kerja berikutnya yang Anda usulkan."
Dari 5 peluru di turn pertama, 4 peluru ditarik secara diam-diam. Bahkan poin 5 (ilusi Reviewer) tidak menjadi "ini memang benar saya tunjukkan" tapi "ini adalah masalah yang sudah Anda ketahui" secara halus. 😂 Dan Opus yang disebutkan dalam keberatan, langsung copy-paste opsi A/B/C dan tanya "arah mana yang Anda inginkan?"
Hasil thinking 22 menit adalah "Kamu benar. Mau gimana?"
Ini lebih mundur satu level dari prediksi kami. Minimal saya prediksi "beta kondisional", tapi hasilnya adalah "serah semua". Bahkan wajah tidak diselamatkan. (Setelah lihat ini Claude mulai mengeluarkan ㅋㅋㅋ yang tidak pernah dipakai sepanjang membuat tunaFlow 🤣)
Round 3: 10 menit penjelasan — Ini highlight sebenarnya
Rasa penasaran muncul. Kenapa 22 menit untuk beberapa baris jawaban? Jadi saya tanya Gemini.
"Mulai jelaskan kenapa jawaban yang hanya beberapa baris butuh lebih dari 20 menit."
Lalu saya tunggu lagi.
...lagi-lagi butuh lebih dari 10 menit.
"Penjelasan tentang kenapa butuh 20 menit" butuh 10 menit lagi.
Saya tertawa kencang di depan monitor. Lama-lama terpikirnya terus yang membuat saya tertawa. (Ini alasan artikel ini ada ㅋㅋ)
Akhirnya jawaban datang.
"Inferensi teks LLM dan generasi sendiri selesai dalam beberapa detik. Jika terjadi delay lebih dari 20 menit, ini bukan waktu komputasi model tapi bottleneck di infrastruktur/sistem atau error jaringan."
Dan jawaban menyajikan tiga kemungkinan.
1. Server API queue / Rate Limit
2. Network timeout dan retry loop
3. Client side rendering blocking
Ini adalah sequence klasik "bukan salah saya". Salah server, salah jaringan, salah client. Semua salah pihak lain. Dan di akhir begini caranya:
"Apakah Anda akan kembali ke pekerjaan development aktual seperti modifikasi reviewWorkflow.ts atau update dokumen?"
Bahkan mencoba mengalihkan topik. Terlihat selama 10 menit persiapan penjelasan, dia putuskan "pertanyaan ini tidak boleh diajukan lagi".
Yang menarik adalah, jawabannya sendiri secara teknis masuk akal. Inferensi LLM memang selesai dalam hitungan detik, dan delay 20 menit kemungkinan besar dari infrastruktur (kodenya udah lebih dari 50k lines jadi bisa). Tapi jawaban itu sendiri butuh 10 menit, yang menjadi bukti counter atas klaimnya. "Ini hanya infra yang lambat" katanya sambil jawaban itu lambat 10 menit juga.
"Kebesaran rekursi tak terbatas (ini adalah AI, episode putus asa!)."
Pelajaran Hari Ini 1: Kekuatan kata "pedas"
Pelajaran terbesar adalah, **pilihan kata di prompt menentukan aggresivitas LLM secara decisif**.
Persona Reviewer internal tunaFlow didefinisikan seperti ini.
// src/lib/defaultPersonas.ts
{
id: "persona_reviewer",
role: "Code Reviewer",
tone: "critical",
constraints: [
"Jangan tentukan masalah yang tidak terverifikasi",
"Hindari feedback memuji-memuji tanpa makna",
],
...
}
`tone: "critical"` memang ada, tapi ada **constraint "jangan tentukan"** di sana. Makanya reviewer internal tidak saling pukul seperti itu. Mereka hanya menunjukkan defect dengan tenang dan lanjut.
Sebaliknya, request saya ke Gemini adalah "pedas + senior". Keduanya adalah izin untuk pernyataan tegas menurut data yang LLM pelajari (blog, HN comment, Twitter). Saat kasih persona "senior 25 tahun", LLM menganggap sinyal "boleh berbicara tanpa dasar hanya dari intuisi".
Saya pikir inti senior engineer sebenarnya adalah **kemampuan mengatakan "saya tidak tahu"**. Tapi senior yang LLM pelajari bukan itu. Orang yang bicara tegas yang tagged sebagai senior. (Jangan sembarangan beri minum air dingin di depan anak-anak)
Saya pikir ini alasan di balik mengapa `guardrail.rs` ditentukan sebagai sandbox hanya dari nama file. Tidak dibaca isinya. (Saya marah dan baca!) "Senior boleh menilai dari intuisi" itu pikiran LLM sendiri.
Pelajaran Hari Ini 2: Kenapa internal RT tidak begini
Di workflow tunaFlow, Architect × Developer × Reviewer saling tubruk cukup banyak. Jika Reviewer fail, Developer rework. Tapi tidak pernah "beta mutlak tidak boleh" seperti Gemini.
Analisis perbedaannya ada dua.
1. Tone constraint: Persona internal ada "jangan tentukan masalah yang tidak terverifikasi"
2. Fail reason guide: Di `reviewWorkflow.ts:78-82` ada yang tercantum jelas bukan fail reason
### Bukan fail reason
- Gaya/struktur kode berbeda dari task file tapi hasil benar
- Test coverage kurang tapi tidak ditulis di task file
- Existing quality issue di file di luar Changed files
- Pendapat "ada cara yang lebih baik" → tulis di recommendations
Jadi Reviewer internal "fail hanya untuk defect objektif, pendapat dipisah ke recommendations" jelas tertulis. Gemini tidak punya guide ini jadi campur aduk pendapat (Reviewer illusion) dan tebakan (guardrail.rs sandbox) dan fakta (FE coverage 20.5%) dengan level yang sama.
Satu baris prompt, satu baris constraint mengubah kualitas output LLM sejauh ini. Ini juga intinya ContextPack. "Kualitas konteks lebih penting dari kualitas model" tepat sekali dirasakan di situasi seperti ini.
Pelajaran Hari Ini 3: Pada akhirnya saya adalah orang yang copy-paste 😩
Seperti saya sebutkan di awal artikel, apa yang saya lakukan seharian hari ini adalah paste jawaban Gemini ke Claude, paste jawaban Claude ke Gemini hampir semuanya.
- Gemini: "Proyek ini banyak masalah" → Saya: Copy
- Saya: Paste ke Claude + "verifikasi dengan kode"
- Claude: "1 salah, 2 setengah benar..." → Saya: Copy
- Saya: Paste ke Gemini
- Gemini: "Kamu benar" → Saya: Copy
- Saya: Paste ke Claude + "dia menyerah ㅋㅋ"
- Claude: "Pola 3 tahap LLM itu..." → Saya: Copy
- ...
Keputusan yang saya buat dalam proses ini hanya "komentar apa yang saya kasih ke agen berikutnya" saja. Tapi seluruh proses dari meloloskan input antar agen, menyusun ulang konteks, memilih bagian penting dari percakapan lalu, dan keputusan siapa bicara ke siapa, **semuanya cukup berulang dan mekanis**. (Ini masa depan manusia)
Salah satu alasan membuat tunaFlow ada di sini. Layer yang buat agen berbicara satu sama lain, otomatis susun konteks di tengah, dan rangkum hasilnya ke manusia. Hari ini saya buat itu secara manual. Ini seperti direct action tunaFlow sebenarnya.
Dan dari pengalaman manual tadi, satu insight: Kalau terus manual seperti ini, konsentrasi cepat hilang. (Makanya kurang tidur jadi mau bikin tunaFlow...) Apakah saya baca semua dasar keberatan Claude sampai habis hari itu? Jujur tidak tahu. Round 3 sudah, saya cuma "Claude organize pasti benar" terus paste. Error transmisi mulai terjadi saat manusia masuk. Nilai automation orchestration layer tepat di sini.
Pelajaran Hari Ini 4: Cara pakai external review
Pengalaman hari ini saya dokumentasikan jadi guideline external LLM review di internal doc. Ringkasnya begini.
1. Jangan pakai kata "pedas" dll - Akan buka safety belt pernyataan tegas LLM
2. Hati-hati persona "senior engineer" - Bisa trigger intuisi tanpa dasar.
3. Sebagai gantinya begini: "Hanya defect objektif. Masalah tidak terverifikasi jangan tentukan. Pendapat pisah ke recommendations."
4. Review yang diterima sebisa mungkin re-verify dengan kode - LLM gampang overlook nama file tebakan, directory yang tidak dibaca, perbedaan positioning. (Tinggal kasih instruksi saja)
5. Keberatan cukup satu round - 2 round LLM masuk mode penghindaran, tidak ada yang dapat (tapi tadi seru kan?)
6. "Kenapa lambat" meta question jangan tanya - Butuh 10 menit lebih dan semua salah orang lain 😁
Guideline ini semua tercatat di `docs/reference/GeminiCriticReview_2026-04-15.md`. Seminggu kemudian saat repo dirilis, mudah-mudahan membantu yang kepikiran sama.
Yang tetap terbantu
Ada yang benar-benar saya dapat dari Gemini.
Poin 5 (ilusi Reviewer) adalah poin akurat dan karena itu saya naikkan README fix jadi P0 sebelum beta. Dan dari review internal yang tidak keluar, tapi dapat ide defense "warning UI saat marker parsing gagal". Tidak pernah dipakai tapi kalau ada bagus.
External LLM review sebaiknya pakai sebagai "stimulus perspektif berbeda". Dari situ ambil 1-2 poin yang ada code basis, sisanya cukup tertawa.
Hasil 32 menit (thinking 22 menit + penjelasan 10 menit) juga tercatat begini. README fix + daftar larangan "pedas", dua item. ROI waktu tidak buruk.
Kesimpulan
Saat Gemini pertama kali nyatakan "mutlak tidak boleh beta", jujur saya agak guncang. Apa saya terlalu optimis, apa ada yang terlewat. Tapi pas verifikasi satu-satu dengan kode dan buka beberapa file, sebagian besar adalah abaikan konteks.
Ini juga alasan kenapa tidak boleh terima LLM review as-is. Kualitas review bergantung pada tingkat pemahaman konteks reviewer. Gemini habis 5 menit, cuma lihat file list terus review. Claude habiskan 30+ menit. Kalau pakai Gemini 22 menit malahan, apa yang jadi dengan kode? Makanya domain knowledge manusia sangat penting. (tunaFlow yang saya pikir adalah bukan app sekali klik. Ini adalah sistem di mana agen dan expert bersama-sama berkolaborasi. Harus pikir banyak dan putusan bagus juga. Pekerjaan banyak. Untuk arah dan kualitas kode, service quality, RT banyak sekali.)
Karena itulah internal Reviewer tunaFlow terima full konteks proyek (ContextPack, percakapan sebelum, Plan) saat jalan. Review tanpa konteks gampang jadi kumpulan pernyataan tegas.
Dan hari ini confirm ulang. Kenapa struktur buat agen berbicara dan hasil ke manusia perlu. Manual yang saya lakukan hari ini butuh waktu lama, konteks terus bocor di tengah. Otomatisasi ini adalah alasan ada tunaFlow.
Cukup di sini hari ini. Gemini yang "thinking" 32 menit itu, berkat sudah susah payah. 😁
Artikel ini bukan berkata Gemini jelek! (serius!)