# SANGGRALOKA ONE — Rencana PM & Kontrak Antar-Agent

Versi 1.0 · 6 Juli 2026 · Disusun PM (Claude Fable 5) atas perintah owner.
Status: **kontrak kerja internal** — semua agent WAJIB mematuhi file ini.

## 0. Apa ini

`sanggraloka-one/` = **copy dari `hotelfix.2/`** (backend PHP 3 lapis +
Android Kotlin, keduanya berfungsi) yang diperluas menjadi **SANGGRALOKA ONE**:
satu aplikasi berisi 3 modul — **FIX** (maintenance, sudah ada), **CREW**
(SDM/HRD, ditambahkan), **SELL** (Sales & Marketing, ditambahkan).

Sumber kebenaran (urutan prioritas):
1. `engineering/sanggraloka.md` — common knowledge resort & keputusan GM.
2. `hotelfix.2/docs/SPEK-HOTELFIX-MASTER.md` — modul FIX (sudah terpasang).
3. `hotelcrew/docs/SPEK-HOTELCREW-MASTER.md` — modul CREW (F1–F16).
4. `hotelsell/docs/SPEK-HOTELSELL-V1-SEDERHANA.md` (yang dibangun) +
   `SPEK-HOTELSELL-MASTER.md` (arah jangka panjang) — modul SELL.
5. `hotelfix.2/docs/ARSITEKTUR-BACKEND-PHP.md` — konvensi teknis WAJIB.
6. Prototipe berjalan `hotelsell/app/` — logika uploader/dashboard SELL
   yang sudah teruji, di-port ke pola 3 lapis.

## 1. ATURAN INTI (perintah owner — TIDAK BOLEH DILANGGAR)

1. **Core tidak berubah.** `login.php`, `logout.php`, `Auth`, `Session`,
   `Csrf`, mekanisme pilih-properti, dan pola `BasePage`/`UiBuilder`/
   `BaseModel` DIPAKAI APA ADANYA. Modul baru menumpang, tidak mengganti.
2. **Task manager SATU.** Papan task = halaman `tasks.php` tunggal yang
   menampilkan: `hr_tasks` (label sumber **CREW** / **SELL** via kolom
   `source_app`) **+ work_orders terbuka sebagai kartu label FIX**
   (read-only link ke `work-order.php`). Modul SELL/CREW DILARANG membuat
   sistem task/reminder sendiri — semua reminder (follow-up 3/5/7, kontrak
   H-60/H-30, KOL H-7/H-1/H+7) ditulis sebagai baris `hr_tasks`
   (`source_app='sell'` dst).
3. **Kalender SATU.** `calendar.php` (dept) dan `my-calendar.php` (pribadi)
   yang sudah ada DIPERLUAS untuk overlay: shift roster (`hr_roster`), cuti
   approved (`hr_leaves`), task due (`hr_tasks`), booking/event venue
   (`mkt_bookings`) sesuai role — bukan membuat kalender baru per modul.
4. **Satu database** MySQL: tabel CREW prefix `hr_`, SELL prefix `mkt_`,
   semua ber-`property_id`, migrasi bernomor lanjutan di `backend/db/migrations/`.
5. **Contoh konten cukup 1 divisi: HOUSEKEEPING.** Jobdesk/KPI/University
   di-seed hanya untuk HK (+ faculty GEN yang wajib semua); divisi lain
   mengikuti template yang sama lewat UI admin — JANGAN seed 43 posisi.
6. **Dilarang mengarang fakta resort**: kode kompetensi hanya dari dokumen
   `hotelcrew/docs/` yang ada; harga produk SELL dikosongkan (diisi S&M);
   angka standar yang tidak ada di spek ditandai `[ANGKA: tetapkan HOD/GM]`.
7. AI (F15 intake, F16 note-parser, Studio SELL) = **stub berpagar**: class
   Service dengan interface jelas + fallback form manual; pemanggilan API
   Claude nyata membaca key dari `config/config.php` (`anthropic_api_key`,
   boleh kosong → fitur menampilkan "belum dikonfigurasi", form manual tetap
   jalan). Tidak ada chatbot bebas di modul CREW (keputusan GM); Studio chat
   hanya di SELL (`studio.php`) dengan 2 persona terkunci.
8. **DESIGN TERPISAH DARI FUNCTIONALITY (perintah owner 7 Jul 2026).**
   Seluruh presentasi (chrome, komponen, warna, tipografi, CSS/JS) =
   **lapisan design** milik EKSKLUSIF agent **UX/IX** (§8). Module engineer
   (HR/SELL/Shell) **tidak pernah** menulis HTML/CSS mentah atau inline style
   dan **tidak pernah** menyentuh `src/View/` atau `public/assets/` — mereka
   hanya memanggil komponen `UiBuilder`. Kontrak antar-tim = signature method
   `UiBuilder` + token `tokens.css`. Konsekuensi: tim UX/IX bisa mendesain
   ulang tampilan kapan saja (drop-in, hanya HTML/CSS internal berubah) tanpa
   mengganggu module engineer, dan sebaliknya.
9. `sanggraloka.md` **hanya di-update PM** di akhir — agent tidak menyentuhnya.

## 2. Role & akses (perluasan, bukan penggantian)

Role existing (FIX) tetap: `super_admin, property_admin, dept_head,
technician, reporter, viewer`.
Role baru di `user_property_access.role` (satu role per user per properti):

| Role baru | Modul utama | Catatan |
|---|---|---|
| `gm` | semua (baca) + approval | menggantikan pemakaian `viewer` utk GM |
| `hr_admin` | CREW penuh + **zona merah payroll** | = HC Manager |
| `hr_staff` | CREW operasional (tanpa zona merah) | |
| `fc` | baca CREW/SELL + **zona merah payroll** | Financial Controller |
| `supervisor` | approval tk-1, inspeksi, coaching (dept-nya) | Coordinator |
| `employee` | self-service (absen, cuti, slip, belajar, task saya) | staf umum |
| `sales_manager` | SELL penuh + approve | HOD S&M |
| `sales` | SELL M1–M3, M5–M6 | |
| `ewm` | SELL booking/wedding + kanban | Asst. Event & Wedding Mgr |
| `design` | SELL M4–M6 | Graphic Design |

Catatan penyederhanaan v1 (disetujui PM): kolom `app` per §2.1 SPEK-HOTELCREW
TIDAK dibuat — karena sekarang memang satu aplikasi, satu role cukup;
`dept_head` existing berlaku lintas modul untuk departemennya. Flag Trainer =
kolom `users.is_trainer` (bool). Zona merah = role `hr_admin|fc|gm` + step-up
PIN 6 digit (`auth_stepup`; OTP WhatsApp = stub interface, menyusul).

## 3. Peta halaman (kontrak nama file — nav Layout ↔ file public HARUS sama)

### Sudah ada (FIX — jangan diubah kecuali disebut)
Semua file `public/*.php` existing tetap. Yang DIPERLUAS oleh Agent SHELL:
`tasks.php` (BARU — papan terpadu), `task.php` (BARU — detail task),
`calendar.php` + `my-calendar.php` (overlay), `index.php`/Dashboard (kartu
ringkas 3 modul sesuai role), `profile.php` (tab Profil Saya CREW: kompetensi,
jobdesk, kontrak, slip).

### Modul CREW (Agent HR — file BARU semua)
```
employees.php  employee.php        master karyawan (F1) + dokumen + kontrak
attendance.php                     rekap & exception absensi + sanggah (F2)
leaves.php                         cuti/ijin + saldo + approval berjenjang (F3)
roster.php                         roster builder grid + validasi + publish (F4)
jobdesks.php                       library jobdesk berversi + acknowledge (F5)
competencies.php                   skill matrix + sync ke `skills` FIX (F6)
university.php course.php          faculty, course, materi, test, e-cert (F7)
kpi-hr.php                         KPI dept & individu + publish bulanan (F8)
discipline.php                     coaching/SP + acknowledge ber-hash (F9)
payroll.php payroll-params.php     ZONA MERAH: run wizard + parameter (F10)
recruitment.php                    mini-ATS + test token kandidat (F11)
onboarding.php                     onboarding/offboarding/DW pool (F12)
engagement.php                     pengumuman, kudos, eNPS, grievance (F13/F14)
briefing-daily.php                 composer briefing pagi + risalah→cascade (F15)
ai-intake.php                      intake teks → draft task (stub AI + manual) (F15C)
guest-cards.php guest-upload.php   deck tamu hari ini + upload MOD (F16)
api/hr/v1/index.php                router API HR (me, attendance, leave, roster,
                                   university, tasks, briefings, guest-cards)
```

### Modul SELL (Agent SELL — file BARU semua)
```
sell-dashboard.php                 KPI, OTB+pickup+forecast, top agent, badge reminder
partners.php partner.php           M1 mitra & kontrak (reminder H-60/H-30)
products.php                       M2 katalog produk (21 experiences — harga kosong)
bookings.php booking.php           M2 booking + status + deposit
venue-calendar.php                 M2 kalender venue (bentrok ditolak; blackout)
quotes.php                         M3 KANBAN penawaran + aturan 3/5/7 + LOST wajib alasan
kol.php                            M4 KOL + visit + gerbang photo-release
studio.php                         M5+M7 chat AI 2 persona (stub bila key kosong)
marketing.php                      M6 keyword map + generator bulanan
review-queue.php                   M6 antrian approve konten (gerbang manusia)
sell-upload.php                    uploader report reservasi PMS (port dari hotelsell/app/upload.php)
```

## 4. Model data — pembagian migrasi (Agent DB)

File lanjutan dari 0007:
- `0008_hr_init.sql` — SEMUA tabel §4 SPEK-HOTELCREW (prefix `hr_` +
  `audit_logs` + `auth_stepup`) + ALTER: `users.employee_id` (nullable FK),
  `users.is_trainer` (bool default 0).
- `0009_mkt_init.sql` — tabel modul SELL sesuai SPEK-HOTELSELL-V1 §1–§7
  (`mkt_partners, mkt_contracts, mkt_products, mkt_bookings, mkt_payments,
  mkt_quotations, mkt_quote_log, mkt_kols, mkt_kol_visits, mkt_kol_docs,
  mkt_kol_results, mkt_event_ideas, mkt_menus, mkt_keywords,
  mkt_generated_content, mkt_ai_chats, mkt_ai_messages,
  mkt_reservations, mkt_otb_snapshots, mkt_upload_maps` — 3 terakhir port
  dari skema `hotelsell/app/data/hotelsell_mysql.sql`).
- `0010_seed_hr_hk.sql` — seed contoh divisi HK + GEN (lihat §1 butir 5)
  + shift master + roster contoh 1 minggu + 1 periode payroll param default
  (nilai tarif BPJS/PPh dari spek F10 — itu angka regulasi, boleh diisi).
- `0011_seed_mkt.sql` — seed 21 experiences sebagai produk (harga NULL),
  venue (Anandam, shala, farm, Meditera), 3 mitra contoh, alasan-LOST master.

Kunci teknis: InnoDB, utf8mb4, ENUM sesuai spek, index `(property_id, …)`,
`audit_logs` & `hr_attendance_logs` & `mkt_quote_log` tanpa UPDATE path
(append-only by convention), FK jelas. Kolom gaji di `hr_payroll_items`
bertipe TEXT (ciphertext — enkripsi level aplikasi oleh modul HR).

## 5. Pembagian agent & batas folder (REVISI 7 Jul 2026 — +lapisan design UX/IX)

**Prinsip baru (§1 butir 8): lapisan design terpisah total dari
functionality.** `src/View/` + `public/assets/` = milik EKSKLUSIF agent
UX/IX. Module engineer TIDAK menyentuhnya & TIDAK menulis HTML/CSS mentah —
hanya memanggil `UiBuilder`. Ini yang membuat dua kelompok kerja paralel
tanpa tabrakan file.

| Agent | Model | Folder yang BOLEH ditulis | Gelombang |
|---|---|---|---|
| DB Engineer | Sonnet | `backend/db/` saja | 1 |
| **UX/IX Designer** | **Opus** | `backend/src/View/` (Layout.php, UiBuilder.php), `backend/public/assets/` (app.css, **tokens.css**, app.js), `backend/public/styleguide.php` + `backend/src/Page/StyleguidePage.php` (galeri komponen hidup), `docs/DESIGN-SYSTEM.md` — **TIDAK menyentuh Page/Model/Service/Api modul** | 1 (paralel) |
| Shell Integrator | Opus | `backend/src/Auth/` (Role, Acl), `backend/src/Service/` (AuditService, TaskBoardService), `backend/src/Page/` (Dashboard, Calendar, MyCalendar, Profile, Tasks, TaskDetail), `backend/public/` (tasks.php, task.php — thin), `android/app/src/main/res/` (label saja), `backend/README.md` — **TANPA `src/View/` & `public/assets/`** (pindah ke UX/IX) | 1 (paralel) |
| HR Module Engineer | Opus | `backend/src/Model/Hr*.php`, `backend/src/Service/Hr*.php`, `backend/src/Page/Hr*.php`, `backend/src/Api/Hr*.php`, `backend/public/` (file CREW §3 saja), `backend/public/api/hr/` — **tanpa HTML/CSS mentah** | 2 |
| Sell Module Engineer | Sonnet | `backend/src/Model/Mkt*.php`, `backend/src/Service/Mkt*.php`, `backend/src/Page/Mkt*.php` (atau `Sell*`), `backend/public/` (file SELL §3 saja) — **tanpa HTML/CSS mentah** | 2 |
| QC Integrator | Sonnet | perbaikan kecil lintas folder + `docs/QC-SANGGRALOKA-ONE.md` | 3 |

Aturan kelas: model/service/page modul baru pakai prefix nama kelas `Hr` /
`Mkt` (contoh `HrEmployee extends BaseModel`, `MktQuotesPage extends
BasePage`) supaya tidak bentrok dengan kelas FIX existing.

**Protokol permintaan komponen (satu-satunya jalur lintas-tim):** bila module
engineer butuh tampilan yang belum ada method-nya di `UiBuilder` (mis. papan
kanban, kartu guest, deck swipeable), ia **TIDAK** menulis HTML sendiri —
melainkan mencatat kebutuhan di `docs/COMPONENT-REQUESTS.md` (nama method
usulan + parameter + contoh data). Untuk menjaga paralelisme, engineer boleh
memakai **placeholder sementara** (`$this->ui->card(...)` polos berisi tabel
biasa) sampai UX/IX menerbitkan komponen final — pertukaran ke method final
= satu baris, tanpa mengubah logika. UX/IX menambah method ke `UiBuilder`
(kontrak stabil: signature tak dihapus/diubah, hanya ditambah).

**Catatan rekonsiliasi (run Shell yang dihentikan):** run Shell Integrator
sebelumnya SEMPAT menyentuh `src/View/` & `public/assets/app.css`. Mulai
revisi ini file-file itu **milik UX/IX** — perubahan View/asset dari run lama
ditinjau & diambil alih UX/IX; Shell Integrator berikutnya tidak lagi
menyentuhnya.

Nav: Agent SHELL menulis nav Layout **persis** daftar file §3 (grup menu
FIX / CREW / SELL per role, server-side — yang tak berhak tidak dirender).
Agent HR/SELL wajib memakai nama file §3 persis — kalau butuh halaman
tambahan, daftarkan dulu ke PM (tulis di laporan akhir).

## 6. Definisi selesai (QC gate)

1. `php -l` lolos semua file PHP.
2. Migrasi 0001→0011 jalan berurutan di MySQL kosong tanpa error.
3. Login role lama (dept_head/technician) TIDAK berubah perilakunya.
4. Papan task menampilkan 3 sumber label; menyelesaikan task CREW/SELL
   meng-update baris `hr_tasks`; kartu FIX link ke WO.
5. Kalender pribadi menampilkan shift HK contoh + task due.
6. Setiap listing baru punya toolbar filter + kolom sortable (aturan UI
   HotelFix — pakai pola `SortSpec` existing).
7. Zona merah payroll menolak role selain `hr_admin|fc|gm` di server, dan
   meminta PIN step-up.
8. Tidak ada fakta resort karangan (kode kompetensi, harga, nama outlet).
9. **Gate design (baru):** nol HTML/CSS mentah & nol inline style di file
   `src/Page/*` modul (grep `<div`/`style=` di Page modul = 0 kecuali lewat
   `UiBuilder`); semua warna/tipografi dari `tokens.css` (tidak ada hex
   hard-coded di app.css di luar blok token); `styleguide.php` merender semua
   komponen tanpa error; brand = palet Sanggraloka (bukan biru HotelFix lama).

## 7. Log keputusan PM

- 6 Jul 2026: struktur folder = copy hotelfix.2 apa adanya; Android hanya
  di-rename labelnya (fungsi CREW/SELL Android = fase berikut, sesuai
  prinsip "web = administrasi").
- 6 Jul 2026: kolom `app` di user_property_access tidak dipakai (satu
  aplikasi = satu role); dicatat sebagai penyimpangan sadar dari §2.1
  SPEK-HOTELCREW.
- 6 Jul 2026: OTP WhatsApp zona merah = stub (PIN dulu); WA gateway belum ada.
- **7 Jul 2026 (owner): design DIPISAH dari functionality** → +agent UX/IX
  memiliki lapisan View+assets secara eksklusif (§8); Shell Integrator
  kehilangan hak atas `src/View/` & `public/assets/`; ditambah protokol
  permintaan komponen + placeholder agar paralel tanpa tabrakan. Lampiran
  "spesifikasi UX/IX" dari owner belum diterima — mandat §8 sementara disusun
  PM dari positioning resort + brand Sanggraloka existing, menunggu konfirmasi.

---

## 8. Lapisan Design (UX/IX) — arsitektur & mandat agent

> **Tujuan owner:** memperbaiki SEMUA tampilan Sanggraloka One dengan tim
> UX/IX khusus, dan meletakkan design **terpisah** dari functionality supaya
> tim design & tim engineer bekerja paralel tanpa saling mengganggu.

### 8.1 Batas lapisan (apa itu "design" vs "functionality")

| Lapisan DESIGN (milik UX/IX) | Lapisan FUNCTIONALITY (milik engineer) |
|---|---|
| `src/View/Layout.php` — chrome, header, nav shell, footer | `src/Page/*` — ambil data, panggil komponen, handle POST |
| `src/View/UiBuilder.php` — semua komponen penghasil HTML | `src/Model/*`, `src/Service/*` — data & aturan bisnis |
| `public/assets/tokens.css` — token brand (warna, tipografi, radius, spacing, shadow) | `src/Api/*` — endpoint JSON |
| `public/assets/app.css` — kelas komponen (memakai token) | migrasi `db/` — skema |
| `public/assets/app.js` — interaksi progresif (drag kanban, tab, filter) | |
| `public/styleguide.php` — galeri komponen hidup | |

Aturan besi: **HTML hanya lahir di `UiBuilder`/`Layout`; CSS hanya di
`assets/`.** Page menghasilkan tampilan HANYA lewat pemanggilan method
`UiBuilder`. Tidak ada `echo "<div...>"` atau `style="..."` di Page modul.

### 8.2 Kontrak antar-tim (yang membuat paralelisme aman)

1. **Kontrak = signature method `UiBuilder` + nama token `tokens.css`.**
   Selama signature tidak berubah, UX/IX bebas mendesain ulang isi HTML/CSS
   (redesign = **drop-in**, tidak menyentuh satu baris pun kode modul).
2. **Additive-only:** method `UiBuilder` boleh ditambah, tidak dihapus/diubah
   parameternya (kalau perlu evolusi → tambah method baru, tandai lama
   `@deprecated`). Token boleh ditambah; token lama tidak dihapus mendadak.
3. **Permintaan komponen** lewat `docs/COMPONENT-REQUESTS.md` (§5). Engineer
   pakai placeholder komponen dasar sampai versi final terbit.
4. **Styleguide sebagai kebenaran visual:** `styleguide.php` menampilkan
   setiap komponen dengan contoh data — reviewer menilai design di satu
   halaman, bukan menyusuri 40 halaman modul.

### 8.3 Mandat design (FINAL — dikonfirmasi owner 7 Jul 2026)

Spesifikasi UX/IX = **brief restyling owner** (dokumen di bawah) + moodboard
yang disetujui. Rincian lengkap token, ikon, komponen, dan 3 tema ada di
**`docs/DESIGN-SYSTEM.md`** (rujukan wajib agent UX/IX & module engineer).

**Brief restyling owner (kutipan pengarah, dikunci):**
- Ubah tampilan jadi **dashboard premium gaya 2026**: soft shadow, sudut
  membulat, ruang putih seimbang, KPI card jelas, tabel bersih, sidebar
  modern, top bar elegan, responsif.
- **JANGAN** membangun ulang dari nol, **JANGAN** menghapus fungsi, **JANGAN**
  ubah logika bisnis, **JANGAN** rename ID/kelas/route/atribut data penting.
  Hanya poles presentasi, layout, responsivitas, UX. → selaras total dgn
  prinsip §8.1 (design terpisah dari functionality).
- Bootstrap 5 best practice bila relevan, CSS bersih & maintainable, hindari
  animasi berlebih.

**Brand & identitas (dipertahankan, bukan diganti):**
- Palet Sanggraloka: hutan gelap `#0E1A16` · hijau hutan `#1B5E3B` · teal
  `#0E7C66` · amber `#D99A06` · gradien 135° hijau→teal→hijau muda.
- Ikon = Tabler outline bertema **luxury & alam**: daun, kupu-kupu (maskot
  Troides helena), tunas, tetesan air suci, lembah, canang/flower, diamond,
  award, sparkles, moon-stars.
- Tipografi tenang (system-ui), dua bobot (400/500-600), sentence case,
  kontras WCAG AA, target sentuh ≥44px (staf lapangan Gen Z).

**3 TEMA PILIHAN PER-KARYAWAN (keputusan owner — anti-monoton):**
implementasi via `[data-theme]` di elemen pembungkus `Layout`; nilai token
warna berbeda per tema, **komponen & logika NOL berubah**. Karyawan memilih
di **Profil Saya** → tersimpan (preferensi user / `hr_employees`) → `Layout`
menyetel atribut. Default = Rimba Terang.

| Tema | `data-theme` | Suasana | Kanvas / aksen |
|---|---|---|---|
| Rimba Terang | `terang` | terang & segar, shift pagi | `#EEF2EE` / hijau-teal |
| Sawah Senja | `senja` | hangat krem-amber, tenang | `#F4ECDB` / amber-terakota |
| Hutan Malam | `malam` | gelap low-glare, MOD malam | `#0E1A16` / teal-amber |

Ketiga tema WAJIB lulus kontras AA dan menampilkan badge modul
FIX/CREW/SELL yang terbaca. Menambah tema baru = tambah blok token di
`tokens.css`, tanpa menyentuh kode modul.

### 8.3b Baseline lama (arsip)

Sasaran & konteks (dari `sanggraloka.md`, bukan karangan):
- **Brand Sanggraloka, bukan biru HotelFix.** Satukan seluruh aplikasi ke
  palet Sanggraloka yang sudah ditetapkan di mockup HotelSell: **hijau hutan
  gelap + gradien hijau–teal–amber** (lihat `hotelsell/docs/mockups/app.css`).
  `tokens.css` di-refactor: pisahkan blok token brand agar ganti tema = satu
  file.
- **"Quiet luxury" / eco-luxury** (north star Michelin-class): bersih,
  lapang, tipografi tenang, kontras cukup, hindari ramai — cocok positioning
  resort.
- **Dipakai staf Gen Z & literasi digital beragam, sering di lapangan:**
  target sentuh besar (≥44px), ikon + label (Tabler icons seperti mockup),
  status berwarna konsisten (badge sudah ada), mode tampilan sederhana.
  Aksesibilitas: kontras WCAG AA, fokus keyboard, `aria` pada komponen
  interaktif.
- **Konsisten lintas 3 modul:** FIX/CREW/SELL memakai komponen & token yang
  SAMA; pembeda modul cukup lewat aksen/label grup nav, bukan CSS terpisah
  per modul.
- **Responsif** (web dipakai di desktop admin & tablet kiosk kantin).
- **Tanpa framework berat**: tetap plain CSS + progressive JS (konsisten
  ARSITEKTUR-BACKEND-PHP.md); tidak menambah build step.

> ⚠️ Bila owner mengirim spesifikasi UX/IX detail (referensi visual, palet
> pasti, komponen wajib), PM memperbarui §8.3 ini dan agent UX/IX mengikuti
> versi final — bagian di atas adalah baseline agar kerja tidak tersendat.

### 8.4 Deliverable agent UX/IX (Gelombang 1, paralel)

1. `tokens.css` — token brand Sanggraloka terstruktur (warna, tipografi,
   spacing, radius, shadow, z-index), diimpor `app.css`.
2. `app.css` — refactor jadi berlapis (token → base → komponen → utilitas);
   nol hex hard-coded di luar blok token; kelas untuk komponen baru yang
   dibutuhkan modul (kanban, guest card, deck, wizard payroll, kalender
   overlay) — daftar tumbuh dari `COMPONENT-REQUESTS.md`.
3. `UiBuilder.php` — pertahankan 31 method existing (additive-only) + tambah
   komponen baru: `kanbanBoard`, `guestCard`, `wizardSteps`, `calendarMonth`
   (overlay multi-sumber), `emptyState`, `pageHeader`, `metricCard`, dll
   sesuai permintaan.
4. `Layout.php` — chrome bermodul (grup nav FIX/CREW/SELL/Bersama diberi
   gaya konsisten; header profil; area flash) — **hanya presentasi**, data
   menu tetap dari fungsi role yang disediakan Shell (kontrak: Layout
   menerima array menu, tidak menghitung role sendiri di View).
5. `styleguide.php` + `StyleguidePage.php` — galeri semua komponen.
6. `docs/DESIGN-SYSTEM.md` — daftar token, daftar method + contoh pemakaian
   (rujukan module engineer), aturan additive-only.

### 8.5 Urutan (kenapa aman paralel)

UX/IX (Gelombang 1) menerbitkan design system + kontrak komponen **berbarengan**
dengan DB & Shell. Module engineer (Gelombang 2) menulis Page yang memanggil
`UiBuilder`; komponen yang belum final dipakai via placeholder. Saat UX/IX
menuntaskan komponen, penggantian ke method final bersifat kosmetik (satu
baris per pemakaian) dan tidak pernah menyentuh Model/Service/Api. Redesign
lanjutan kapan pun = hanya `assets/` + isi method `UiBuilder`.
