Menulis requirements.md yang Membuat AI Berhenti Menebak
Kegagalan generasi kode hampir tidak pernah soal model
Ketikkan "buatkan aplikasi web untuk memantau pendaftaran penghuni dan okupansi kos" ke agen AI mana pun hari ini, dan Anda akan mendapat sesuatu yang berjalan. Ada tabel unit, ada formulir pendaftaran, ada kartu besar bertuliskan persentase okupansi. Masalahnya muncul di minggu kedua, ketika pemilik properti bertanya kenapa angka okupansi di dasbor berbeda dengan hitungan manualnya, dan kenapa satu unit bisa dibooking dua calon penghuni sekaligus.
Model tidak salah. Model mengisi kekosongan. Setiap detail yang tidak Anda tuliskan akan diisi dengan asumsi paling umum secara statistik dari jutaan repositori publik, dan asumsi paling umum itu jarang cocok dengan proses bisnis organisasi Anda. Pada kasus okupansi, asumsi bawaannya hampir selalu unit terisi dibagi total unit, padahal unit yang sedang direnovasi tidak boleh masuk penyebut. Selisihnya kecil di layar, besar di laporan bagi hasil.
Karena itu titik ungkit terbesar dalam pengembangan berbantuan AI bukan pemilihan model antara Claude atau GPT, melainkan kualitas satu berkas: requirements.md di akar repositori. Berkas ini dibaca manusia saat review, dan dibaca mesin sebagai konteks setiap kali agen dijalankan. Ia adalah kontrak.
Prinsip kerja artikel ini. Sebuah aturan bisnis dianggap belum tertulis sampai ia punya nomor, pemilik, pernyataan yang dapat difalsifikasi, dampak yang terlihat di layar, dan nama tes yang membuktikannya. Empat elemen pertama adalah pekerjaan analis. Elemen kelima adalah yang membuat AI dapat memverifikasi dirinya sendiri.
Titip kelola membuat satu angka punya tiga arti
Sebelum masuk ke struktur berkas, ada satu karakteristik domain yang menentukan hampir seluruh isi spesifikasi ini. Bayangkan situasi aplikasi berikut
Koozz tidak memiliki properti yang dipantaunya. Pemilik kos atau apartemen menitipkan asetnya melalui program titip kelola, dan hubungan komersialnya mengambil salah satu dari tiga bentuk. Bentuk itulah yang menentukan siapa menanggung risiko unit kosong, dan karena itu menentukan pula angka mana yang paling berarti di layar. Ini yang disebut
| Skema kerja sama | Penanggung risiko unit kosong | Yang paling dicari pemilik di dasbor |
|---|---|---|
| Bagi hasil | Pemilik dan Koozz secara proporsional | Okupansi harian dan trennya, karena langsung menentukan penerimaannya |
| Sewa jaminan | Koozz sepenuhnya | Bukti unit terawat dan riwayat penghuni; okupansi bersifat informatif |
| Management fee dan bagi hasil | Pemilik | Okupansi berikut lama unit menganggur sejak terakhir dihuni |
Konsekuensinya konkret. Dasbor tidak boleh menampilkan susunan angka yang sama untuk semua pemilik. Pada skema sewa jaminan, menonjolkan okupansi rendah justru menimbulkan kecemasan atas risiko yang bukan miliknya. Pada skema bagi hasil, menyembunyikan okupansi harian sama saja menahan informasi yang menjadi haknya. Ini bukan preferensi tampilan, melainkan turunan dari perjanjian, dan karena itu ditulis sebagai aturan bernomor, bukan sebagai catatan desain.
Isolasi data adalah kewajiban kontraktual. Pada aplikasi internal biasa, kebocoran data antar pengguna adalah bug keamanan. Pada aplikasi titip kelola, pemilik A melihat okupansi properti pemilik B adalah pelanggaran perjanjian dengan konsekuensi hukum. Perbedaan bobot itu harus muncul di spesifikasi, yaitu sebagai aturan bernomor dengan uji negatif wajib, bukan sebagai baris di daftar praktik baik.
Karakter tiga pihak ini juga mengubah tabel aktor. Pemilik Properti bukan pengguna internal dengan hak akses terbatas, melainkan pihak eksternal yang berhak penuh atas datanya sendiri dan tidak berhak sama sekali atas data lainnya. Batas itu tegas, dan agen AI tidak akan menebaknya benar tanpa diberi tahu.
Garis besar: dua belas blok yang wajib ada
Jika Anda hanya punya waktu lima menit, ini checklistnya. Urutan penting karena blok berikutnya merujuk kosakata yang didefinisikan blok sebelumnya.
| # | Blok | Pertanyaan yang dijawab | Tanpa ini, AI akan |
|---|---|---|---|
| 1 | Konteks dan tujuan | Masalah apa yang diselesaikan, ukuran keberhasilannya apa | Menambah fitur yang tidak diminta |
| 2 | Glosarium domain | Satu istilah berarti apa, dalam bahasa apa | Mencampur Room, Kamar, dan Unit di satu proyek |
| 3 | Aktor dan hak akses | Siapa boleh melakukan apa | Menampilkan data pemilik A kepada pemilik B |
| 4 | Ruang lingkup | Apa yang tidak dibangun sekarang | Membangun modul pembayaran yang belum dibutuhkan |
| 5 | Model domain | Entitas, atribut, relasi, kardinalitas | Menormalisasi ulang skema di setiap iterasi |
| 6 | Aturan bisnis bernomor | Batasan apa yang tidak boleh dilanggar | Menaruh validasi hanya di controller |
| 7 | Siklus hidup dan status | Status apa saja, transisi mana yang sah | Membuat kolom Status bertipe string bebas |
| 8 | Inventaris layar | Ada layar apa, tiap layar melayani siapa | Membuat satu halaman CRUD generik per tabel |
| 9 | Kontrak interaksi | Setiap aksi punya prakondisi dan efek apa | Menampilkan tombol yang aksinya gagal di server |
| 10 | Definisi metrik | Angka di dasbor dihitung dari apa | Memilih rumus paling umum, bukan rumus Anda |
| 11 | Persyaratan non fungsional | Performa, audit, keamanan, lokalisasi | Mengabaikan jejak audit sampai audit datang |
| 12 | Kriteria penerimaan | Kapan pekerjaan dinyatakan selesai | Menyatakan selesai saat kode berhasil dikompilasi |
Blok 10 adalah tambahan khusus untuk aplikasi pemantauan. Pada aplikasi transaksional biasa, tempatnya diisi katalog pesan galat. Pada aplikasi yang produk utamanya adalah angka di layar, definisi metrik jauh lebih berisiko salah tafsir. Semua bisa diletakkan di Github untuk kemudahan perubahan
Anatomi tiap blok, dengan contoh KOOZZ MONITOR
Konteks dan tujuan
Tiga paragraf maksimum. Sebutkan pemilik proses, volume transaksi, dan satu metrik keberhasilan yang terukur. Metrik ini mencegah agen menambah fitur di luar arah produk.
Koozz mengelola properti kos dan apartemen milik pihak ketiga
melalui program titip kelola. Saat ini 34 properti dengan 780
unit dipantau melalui berkas spreadsheet terpisah per properti,
sehingga angka okupansi baru diketahui pemilik pada akhir bulan.
Tujuan: pemilik properti dapat melihat okupansi harian unitnya
secara mandiri, dan waktu dari pendaftaran calon penghuni sampai
keputusan turun dari 3 hari menjadi kurang dari 1 hari kerja.Glosarium domain
Ini blok yang paling sering dilewati dan paling mahal akibatnya. Tentukan bahasa penamaan kode secara eksplisit, lalu kunci istilahnya. Rekomendasi untuk konteks Indonesia: nama entitas domain memakai istilah bisnis asli, sedangkan kata teknis tetap Inggris.
| Istilah | Definisi | Nama kelas | Bukan |
|---|---|---|---|
| Properti | Satu bangunan kos atau apartemen yang dititipkan pemilik kepada Koozz | Properti | Property, Building, Gedung |
| Unit | Satu kamar atau satu unit apartemen yang dapat dihuni satu kontrak | Unit | Room, Kamar, Slot |
| Pendaftaran | Pengajuan calon penghuni atas satu unit pada rentang tanggal tertentu | Pendaftaran | Booking, Application, Order |
| Kontrak | Perjanjian sewa aktif antara penghuni dan Koozz atas satu unit | Kontrak | Lease, Sewa, Agreement |
| Okupansi | Rasio unit terisi terhadap unit layak huni, lihat BR-041 | Okupansi | Occupancy, Utilisasi |
| Unit layak huni | Unit berstatus Tersedia, Dibooking, atau Terisi | UnitLayakHuni | Total unit, Kapasitas |
| Titip kelola | Program penyerahan pengelolaan properti dari pemilik kepada Koozz berdasarkan perjanjian | PerjanjianTitipKelola | Management, Kerja sama, Kemitraan |
| Pemilik Properti | Pihak eksternal pemilik sah properti yang dititipkan, berhak penuh atas data propertinya sendiri | PemilikProperti | Owner, Klien, Mitra |
| Skema kerja sama | Bentuk komersial titip kelola: bagi hasil, sewa jaminan, atau management fee | SkemaKerjaSama | Plan, Paket, Tier |
Aktor dan matriks hak akses
Tuliskan sebagai matriks, bukan paragraf. Matriks dapat diterjemahkan langsung menjadi kebijakan otorisasi ASP.NET Core, dan setiap sel kosong menjadi kasus uji negatif. Perhatikan kolom Pemilik Properti, karena isolasi data antar pemilik adalah risiko keamanan terbesar di aplikasi ini.
| Aksi | Calon Penghuni | Penghuni | Pengelola Unit | Manajer Area | Pemilik Properti |
|---|---|---|---|---|---|
| Melihat katalog unit tersedia | Ya | Ya | Ya | Ya | Ya |
| Mengirim pendaftaran | Ya | Ya | Tidak | Tidak | Tidak |
| Memverifikasi dokumen pendaftar | Tidak | Tidak | Ya | Ya | Tidak |
| Mengonfirmasi booking unit | Tidak | Tidak | Ya | Ya | Tidak |
| Mencatat check in dan check out | Tidak | Tidak | Ya | Tidak | Tidak |
| Menandai unit dalam pemeliharaan | Tidak | Tidak | Ya | Ya | Tidak |
| Melihat dasbor okupansi | Tidak | Tidak | Properti tugasnya | Area tugasnya | Properti miliknya |
| Mengubah skema kerja sama | Tidak | Tidak | Tidak | Ya | Tidak |
Tiga sel yang berbunyi "properti tugasnya" atau "properti miliknya" wajib punya uji yang membuktikan bahwa permintaan atas properti milik pihak lain mengembalikan 404, bukan 403. Mengembalikan 403 membocorkan keberadaan properti tersebut.
Ruang lingkup
Daftar di luar lingkup lebih berpengaruh terhadap keluaran AI daripada daftar di dalam lingkup. Tanpa larangan eksplisit, agen cenderung membangun modul pendukung yang tampak masuk akal, dan modul pembayaran adalah godaan terbesar pada domain properti.
Di luar lingkup rilis 1.0:
- Payment gateway dan pencatatan transaksi keuangan
- Perhitungan bagi hasil dan penerbitan laporan pemilik
- Integrasi listing marketplace properti
- Chat antara calon penghuni dan pengelola
- Aplikasi mobile native
- Multi bahasaModel domain
Sajikan sebagai daftar entitas dengan atribut, tipe, dan batasan, ditutup dengan pernyataan relasi. Hindari menyalin diagram gambar ke dalam berkas markdown, karena agen membaca teks jauh lebih andal daripada citra.
### Pendaftaran
| Atribut | Tipe | Batasan |
|------------------|-------------|----------------------------------|
| Id | Guid | PK |
| NomorPendaftaran | string(18) | Unik, format DFT-YYYYMM-NNNN |
| CalonPenghuniId | Guid | FK Pengguna, wajib |
| UnitId | Guid | FK Unit, wajib |
| TanggalMasuk | DateOnly | >= hari ini + 1 |
| DurasiBulan | int | lihat BR-021 |
| Status | enum | lihat blok 07 |
Relasi:
- Properti 1..* Unit
- Unit 0..* Pendaftaran
- Unit 0..1 Kontrak aktif pada satu waktu
- Pendaftaran 1..* RiwayatStatus (append only, tidak boleh diubah)
- Properti 1..* SnapshotOkupansi (satu baris per hari)Aturan bisnis bernomor
Setiap aturan mendapat identitas permanen berformat BR-nnn. Nomor tidak pernah didaur ulang, bahkan ketika aturan dicabut. Identitas ini yang nanti menghubungkan requirement ke kode dan ke tes. Format tiap aturan mengikuti blok hero di awal artikel.
Siklus hidup dan tabel transisi
Jangan menuliskan status sebagai daftar. Tuliskan sebagai tabel transisi, karena yang menentukan benar tidaknya implementasi adalah transisi yang tidak boleh terjadi. Aplikasi ini punya dua siklus hidup yang saling terkait, yaitu status pendaftaran dan status unit, dan keterkaitan itu wajib dinyatakan.
| Dari | Peristiwa | Ke | Pelaku | Efek pada unit |
|---|---|---|---|---|
| Draf | Kirim | Diajukan | Calon penghuni | tidak ada |
| Diajukan | Dokumen lengkap | Terverifikasi | Pengelola Unit | tidak ada |
| Diajukan | Tolak | Ditolak | Pengelola Unit | tidak ada |
| Terverifikasi | Konfirmasi booking | Dibooking | Pengelola Unit | Tersedia menjadi Dibooking |
| Dibooking | Check in | Aktif | Pengelola Unit | Dibooking menjadi Terisi |
| Dibooking | Lewat 2x24 jam tanpa check in | Kedaluwarsa | Sistem | Dibooking kembali menjadi Tersedia |
| Aktif | Check out | Selesai | Pengelola Unit | Terisi menjadi Tersedia |
| Aktif | Pemutusan dini | Dihentikan | Manajer Area | Terisi menjadi Tersedia |
Tambahkan dua kalimat penutup yang bernilai tinggi bagi agen. Pertama, transisi selain yang tercantum di tabel ini harus melempar TransisiTidakSahException. Kedua, status unit hanya boleh berubah sebagai efek transisi pendaftaran atau melalui aksi pemeliharaan yang eksplisit, tidak pernah melalui pembaruan langsung. Kalimat kedua mencegah agen membuat endpoint yang menyetel status unit secara bebas.
Mendetailkan proses bisnis di antarmuka
Blok 8 dan 9 adalah tempat sebagian besar tim gagal. Mereka menuliskan aturan bisnis dengan rapi, lalu menyerahkan antarmuka sepenuhnya kepada AI, dan menerima hasil berupa tabel dengan tombol Edit dan Hapus di setiap baris. Antarmuka bukan turunan otomatis dari model data. Antarmuka adalah tempat proses bisnis menjadi terlihat.
Inventaris layar
Beri setiap layar identitas SCR-nn, sebutkan aktor yang dilayani, dan sebutkan pertanyaan tunggal yang dijawab layar itu. Layar yang tidak dapat merumuskan pertanyaan tunggalnya adalah layar yang perlu dipecah.
| Kode | Layar | Aktor | Pertanyaan yang dijawab |
|---|---|---|---|
| SCR-01 | Dasbor okupansi | Pengelola, Manajer, Pemilik | Berapa unit kosong sekarang, dan sejak kapan |
| SCR-02 | Katalog unit | Semua | Unit apa yang tersedia mulai tanggal saya |
| SCR-04 | Formulir pendaftaran | Calon penghuni | Apakah pendaftaran saya memenuhi syarat sebelum dikirim |
| SCR-06 | Antrean verifikasi | Pengelola, Manajer | Mana yang harus saya putuskan hari ini, dan risikonya apa |
| SCR-09 | Laporan okupansi | Manajer, Pemilik | Bagaimana tren okupansi properti saya tiga bulan terakhir |
Enam kondisi wajib per layar
Ini pola yang mengubah kualitas keluaran AI secara paling drastis dengan usaha paling kecil. Untuk setiap layar, tuliskan enam kondisi berikut. Jika Anda tidak menuliskannya, agen hanya akan mengimplementasikan kondisi pertama.
| Kondisi | Contoh pada SCR-01 Dasbor okupansi |
|---|---|
| Normal | Angka okupansi, penyebut yang dipakai, dan tren 30 hari |
| Memuat | Placeholder berukuran sama dengan kartu final, tanpa pergeseran tata letak |
| Kosong | "Properti ini belum memiliki unit terdaftar." Tautan ke pendaftaran unit. |
| Galat | "Data okupansi gagal dimuat. Coba muat ulang." Tombol Muat ulang. |
| Data belum lengkap | Jika snapshot hari ini belum terbentuk, tampilkan angka terakhir disertai keterangan waktu, bukan angka nol |
| Tanpa hak akses | Properti milik pihak lain mengembalikan 404, bukan 403 |
Kondisi kelima adalah yang paling sering hilang pada aplikasi pemantauan. Dasbor yang menampilkan nol persen karena job semalam gagal jauh lebih berbahaya daripada dasbor yang jujur mengatakan datanya belum diperbarui.
Kontrak interaksi
Untuk setiap aksi pengguna, tuliskan lima hal: prakondisi, efek pada data, efek pada layar, umpan balik yang dilihat pengguna, dan aturan bisnis yang berlaku. Ini format yang membuat agen menghasilkan handler yang benar sekaligus komponen UI yang konsisten.
#### ACT-06-03 Konfirmasi booking unit
Layar : SCR-06
Prakondisi : Status = Terverifikasi; pengguna berperan Pengelola
pada properti terkait; unit berstatus Tersedia
Efek data : Pendaftaran -> Dibooking; Unit -> Dibooking;
RiwayatStatus bertambah 1 baris; batas check in
ditetapkan 2x24 jam sejak sekarang
Efek layar : Baris keluar dari antrean dengan animasi 200ms;
penghitung antrean berkurang 1; kartu okupansi
SCR-01 tidak berubah karena unit belum Terisi
Umpan balik : Toast "DFT-202609-0117 dibooking sampai 8 Sep 17:40."
Aturan : BR-007, BR-012, BR-021
Kegagalan : Jika unit sudah dibooking pendaftar lain sejak halaman
dimuat, tampilkan ERR-007 inline pada baris dan
jangan pindahkan baris
Perhatikan baris Efek layar. Menyebutkan secara eksplisit bahwa kartu okupansi tidak berubah adalah instruksi berharga. Tanpa itu, agen sering menaikkan angka okupansi saat booking, padahal menurut BR-041 unit Dibooking belum dihitung sebagai terisi. Inkonsistensi seperti ini yang membuat pemilik properti kehilangan kepercayaan pada dasbor.
Mendetailkan aturan logika aplikasi
Gunakan tabel keputusan, bukan paragraf bersyarat
Aturan berlapis yang ditulis sebagai prosa akan diterjemahkan menjadi rantai if bersarang yang salah di cabang terakhir. Aturan yang sama ditulis sebagai tabel keputusan menghasilkan implementasi yang benar dan lengkap, karena tabel memaksa Anda mengisi setiap kombinasi.
| Tipe properti | Durasi diminta | Skema kerja sama | Alur persetujuan | Aturan |
|---|---|---|---|---|
| Kos | 3 sampai 12 bulan | apa pun | Pengelola Unit | BR-009 |
| Kos | kurang dari 3 bulan | apa pun | Ditolak otomatis | BR-021 |
| Apartemen | 6 sampai 12 bulan | Bagi hasil | Pengelola Unit | BR-009 |
| Apartemen | 6 sampai 12 bulan | Sewa jaminan | Pengelola, lalu Manajer Area | BR-009 |
| Apartemen | lebih dari 12 bulan | apa pun | Manajer Area dengan justifikasi | BR-022 |
| Apartemen | kurang dari 6 bulan | apa pun | Ditolak otomatis | BR-021 |
Definisi metrik adalah aturan bisnis, bukan detail teknis
Ini bagian yang membedakan aplikasi pemantauan dari aplikasi transaksional. Angka di dasbor terlihat seperti hasil kalkulasi, sehingga tim sering menganggapnya urusan implementasi. Padahal setiap angka menyimpan keputusan bisnis: apa penyebutnya, kapan dihitung, dan apa yang terjadi pada data yang datang terlambat.
| Aturan | Keputusan yang dikunci |
|---|---|
| BR-041 | Penyebut okupansi adalah unit layak huni, bukan total unit |
| BR-042 | Snapshot harian diambil pukul 23:59 WIB dan disimpan permanen, tidak pernah dihitung ulang dari data historis |
| BR-043 | Unit Dibooking tidak dihitung sebagai terisi pada okupansi, tetapi dihitung sebagai terkomitmen pada metrik pipeline |
| BR-044 | Perubahan status unit setelah pukul 23:59 masuk snapshot hari berikutnya, tidak mengoreksi snapshot kemarin |
| BR-045 | Lama unit menganggur dihitung sejak check out terakhir, bukan sejak unit dibuat |
| BR-046 | Susunan angka pada dasbor pemilik ditentukan oleh skema kerja sama propertinya |
BR-042 dan BR-044 bersama sama menutup pertanyaan yang paling sering muncul di rapat: kenapa laporan bulan lalu berubah setelah dibuka ulang. Jawabannya harus tertulis sebelum kode ditulis, bukan sesudah.
BR-046 adalah tempat karakteristik titip kelola masuk ke dalam logika aplikasi. Tuliskan sebagai tabel, karena ini keputusan bisnis dengan tiga cabang yang masing-masing punya konsekuensi berbeda pada tata letak.
| Skema properti | Angka utama SCR-01 | Angka pendamping | Tidak ditampilkan |
|---|---|---|---|
| Bagi hasil | Okupansi harian | Tren 30 hari, jumlah unit terkomitmen | - |
| Sewa jaminan | Jumlah unit terawat dan kontrak berjalan | Okupansi sebagai keterangan sekunder | Peringatan okupansi rendah |
| Management fee dan bagi hasil | Okupansi harian | Lama unit menganggur terpanjang (BR-045) | - |
Perhatikan kolom terakhir. Menyembunyikan peringatan okupansi rendah pada skema sewa jaminan bukan penyembunyian informasi, melainkan penyesuaian dengan pihak yang menanggung risikonya. Alasan itu perlu ikut tertulis di requirements, karena tanpa alasan, aturan seperti ini akan dianggap salah oleh peninjau berikutnya dan dihapus.
Empat lapis validasi, dan siapa memiliki apa
Tanpa instruksi eksplisit, agen akan menaruh semua validasi di satu tempat, biasanya di controller atau di komponen Blazor. Nyatakan pembagian lapisnya di requirements.
| Lapis | Tanggung jawab | Contoh |
|---|---|---|
| Antarmuka | Mencegah pengguna mengirim yang pasti salah | Durasi di bawah minimum tidak dapat dipilih pada SCR-04 |
| Aplikasi | Validasi bentuk permintaan dan otorisasi | FluentValidation pada KirimPendaftaranCommand, filter properti menurut pemilik |
| Domain | Menjaga invarian, tidak boleh dilewati | Pendaftaran.KonfirmasiBooking() menolak unit yang tidak Tersedia |
| Basis data | Menjamin integritas terakhir | Unique filtered index: satu unit hanya boleh punya satu pendaftaran berstatus Dibooking atau Aktif |
Baris terakhir penting untuk domain ini. Aturan "satu unit satu penghuni aktif" tidak cukup dijaga di kode, karena dua permintaan bersamaan bisa lolos bersama. Nyatakan indeks uniknya di requirements agar agen membuat migrasi yang benar.
Bentuk kode yang dihasilkan
Dengan spesifikasi di atas, keluaran yang Anda harapkan dari agen terlihat seperti ini. Entitas menjaga invariannya sendiri, dan nomor aturan ikut masuk ke dalam kode sebagai jejak.
public sealed class Pendaftaran
{
private readonly List<RiwayatStatus> _riwayat = new();
public StatusPendaftaran Status { get; private set; }
public DateTimeOffset? BatasCheckIn { get; private set; }
public Result KonfirmasiBooking(Unit unit, DateTimeOffset sekarang)
{
if (Status is not StatusPendaftaran.Terverifikasi)
return Result.Gagal("ERR-TRANSISI",
$"Pendaftaran berstatus {Status} tidak dapat dibooking.");
// BR-007 unit harus tersedia pada saat konfirmasi
if (unit.Status is not StatusUnit.Tersedia)
return Result.Gagal("ERR-007",
"Unit sudah tidak tersedia. Muat ulang daftar.");
unit.Tandai(StatusUnit.Dibooking); // BR-043
BatasCheckIn = sekarang.AddHours(48); // BR-031
Ubah(StatusPendaftaran.Dibooking, sekarang, "Booking dikonfirmasi");
return Result.Sukses();
}
}
Dan perhitungan metriknya, yang menjadi fungsi murni agar mudah diuji terhadap tabel angka di BR-041.
public static Okupansi Hitung(IReadOnlyCollection<Unit> unit)
{
// BR-041 unit Pemeliharaan dan TidakAktif keluar dari penyebut
var layakHuni = unit.Count(u => u.Status is StatusUnit.Tersedia
or StatusUnit.Dibooking
or StatusUnit.Terisi);
if (layakHuni == 0) return Okupansi.TidakTerdefinisi;
var terisi = unit.Count(u => u.Status is StatusUnit.Terisi);
return new Okupansi(terisi, layakHuni);
}
Nilai TidakTerdefinisi adalah pilihan sadar. Properti tanpa unit layak huni tidak berokupansi nol persen, melainkan tidak punya angka okupansi. Perbedaan itu harus muncul juga di layar, dan itulah kondisi Kosong pada SCR-01.
Membagi pekerjaan ke tiga alat
Ketiganya bukan alternatif satu sama lain. Masing-masing kuat pada fase yang berbeda, dan urutan pemakaiannya menentukan berapa banyak pekerjaan ulang yang Anda tanggung.
Claude Design, fase antarmuka
Pakai sebelum satu baris kode ditulis. Masukkan blok 8 dan 9 dari requirements, yaitu inventaris layar dan kontrak interaksi, lalu minta eksplorasi tata letak untuk SCR-01 dengan keenam kondisi wajibnya. Untuk dasbor, minta secara khusus perlakuan visual saat data belum diperbarui, karena inilah keputusan desain yang paling menentukan kepercayaan pengguna. Keluarannya bukan kode produksi, melainkan keputusan visual: hierarki angka, penempatan keterangan penyebut, bentuk grafik tren, dan design token. Bawa keputusan itu kembali ke requirements.md sebagai blok token warna, spasi, dan tipografi.
Claude Code, fase implementasi lintas berkas
Pakai untuk pekerjaan yang menyentuh banyak berkas sekaligus: membuat entitas domain beserta migrasi, menurunkan tabel transisi ganda menjadi state machine, membuat handler beserta validator dan tesnya. Pola prompt yang bekerja baik bersifat sempit dan merujuk nomor:
Baca requirements.md blok 06, 07, dan 10.
Implementasikan BR-041 sampai BR-044 sebagai fungsi murni di
src/KoozzMonitor.Domain/Okupansi.
Aturan:
- Buat unit test untuk setiap baris tabel angka pada BR-041
- Sertakan kasus properti tanpa unit layak huni
- Jangan mengubah berkas di luar folder Domain dan Domain.Tests
- Jangan menambah dependensi NuGet baru
- Tampilkan rencana perubahan berkas sebelum menulis
Tambahkan berkas CLAUDE.md di akar repositori yang menunjuk ke requirements.md dan mencantumkan perintah build serta test. Agen akan membacanya di setiap sesi, sehingga Anda tidak perlu mengulang konteks.
GitHub Copilot, fase di dalam IDE
Kekuatannya ada pada iterasi kecil berjarak dekat di Visual Studio 2026: melengkapi kasus uji yang kurang, menulis mapping antar DTO, membuat komponen Razor dari markup yang sudah ada polanya, dan refactor lokal. Buka berkas requirements.md di tab sebelah saat bekerja, karena berkas yang terbuka ikut masuk konteks. Manfaatkan pula berkas instruksi repositori untuk mengunci konvensi penamaan dan gaya pengujian.
Urutan yang menghemat waktu. Antarmuka lebih dulu di Claude Design, domain dan pengujian berikutnya di Claude Code, penyempurnaan terakhir di Copilot. Membalik urutan, yaitu membangun domain dulu lalu memaksakan antarmuka mengikutinya, adalah penyebab paling umum kerja ulang besar di pertengahan proyek.
Struktur solusi Visual Studio 2026
Cantumkan struktur target di requirements.md. Tanpa itu, agen akan memilih struktur berbeda pada setiap sesi.
KoozzMonitor/
├── KoozzMonitor.sln
├── requirements.md
├── CLAUDE.md
├── .github/copilot-instructions.md
├── docs/
│ ├── aturan-bisnis.md
│ ├── inventaris-layar.md
│ └── matriks-telusur.md
├── src/
│ ├── KoozzMonitor.Domain/ entitas, enum, invarian, metrik
│ ├── KoozzMonitor.Application/ command, query, validator
│ ├── KoozzMonitor.Infrastructure/ EF Core, repositori, job snapshot
│ └── KoozzMonitor.Web/ Blazor Server, komponen, endpoint
└── tests/
├── KoozzMonitor.Domain.Tests/
├── KoozzMonitor.Application.Tests/
└── KoozzMonitor.Integration.Tests/
Perintah pembuatannya, dijalankan sekali di folder kosong, lalu solusi langsung dapat dibuka di Visual Studio 2026 maupun Visual Studio Code:
dotnet new sln -n KoozzMonitor
dotnet new classlib -o src/KoozzMonitor.Domain
dotnet new classlib -o src/KoozzMonitor.Application
dotnet new classlib -o src/KoozzMonitor.Infrastructure
dotnet new blazor -o src/KoozzMonitor.Web --interactivity Server
dotnet new xunit -o tests/KoozzMonitor.Domain.Tests
dotnet new xunit -o tests/KoozzMonitor.Application.Tests
dotnet new xunit -o tests/KoozzMonitor.Integration.Tests
dotnet add src/KoozzMonitor.Application reference src/KoozzMonitor.Domain
dotnet add src/KoozzMonitor.Infrastructure reference src/KoozzMonitor.Application
dotnet add src/KoozzMonitor.Web reference src/KoozzMonitor.Infrastructure
Matriks telusur: pengait yang membuat semuanya bekerja
Satu tabel kecil di docs/matriks-telusur.md mengubah requirements dari dokumen menjadi alat verifikasi. Anda dapat meminta agen memelihara tabel ini setiap kali menambah aturan, dan meminta laporan aturan yang belum punya tes.
| Aturan | Layar | Berkas implementasi | Tes | Status |
|---|---|---|---|---|
| BR-007 | SCR-06 | Pendaftaran.KonfirmasiBooking | BookingTests.UnitSudahTidakTersedia | Lulus |
| BR-021 | SCR-04 | DurasiPolicy.Validasi | DurasiPolicyTests (6 kasus) | Lulus |
| BR-041 | SCR-01 | Okupansi.Hitung | OkupansiTests (5 kasus) | Lulus |
| BR-044 | SCR-09 | SnapshotJob | belum ada | Belum |
Lima hal yang paling merusak
Metrik tanpa definisi tertulis. Kartu besar bertuliskan persentase okupansi tanpa aturan penyebut adalah janji yang tidak dapat ditepati. Setiap angka di dasbor wajib punya nomor aturan.
Requirements yang tidak diperbarui setelah keputusan berubah. Begitu kode dan requirements berbeda, agen akan mengikuti requirements dan membatalkan pekerjaan Anda. Perbarui berkas dalam commit yang sama dengan perubahan kode.
Status disimpan sebagai string. Tanpa enum dan tabel transisi, tidak ada yang menghentikan nilai baru muncul diam diam melalui satu perbaikan cepat, dan okupansi akan salah menghitung status yang tidak dikenalinya.
Prompt raksasa "buatkan seluruh modul". Hasilnya terlihat lengkap dan sulit direview. Pecah per lapis, minta rencana perubahan berkas lebih dulu, dan batasi folder yang boleh disentuh.
Isolasi data antar pemilik properti dianggap fitur biasa. Kebocoran data satu properti ke pemilik lain adalah pelanggaran perjanjian titip kelola, bukan sekadar bug. Tuliskan sebagai aturan bernomor dengan uji negatif wajib, dan pastikan filternya berada di lapis Application, bukan di masing-masing query.
Penutup
Cara paling ringkas menilai apakah requirements.md Anda sudah memadai adalah tes berikut. Serahkan berkas itu kepada seorang engineer yang belum pernah mendengar proyek Anda, tanpa penjelasan lisan apa pun. Jika ia dapat menjelaskan kembali alur pendaftaran, menyebut transisi status yang dilarang, dan menghitung sendiri angka okupansi dari sekumpulan status unit tanpa bertanya, maka agen AI juga akan mampu.
Tidak ada komentar