# Panduan AI Agent - Preventive Maintenance

Panduan ini berlaku untuk seluruh repository. Ikuti instruksi pengguna untuk tugas aktif, baca kode terkait sebelum mengubahnya, dan pertahankan struktur serta desain yang sudah dibuat. Berkomunikasi dengan pengguna dalam bahasa Indonesia; pesan commit menggunakan bahasa Inggris.

## Gambaran proyek

Aplikasi manajemen preventive maintenance dengan dashboard, Pilot Plant, inventory spare part, stock movement, quarantine, maintenance plan/work order, notifikasi, laporan, autentikasi, dan kiosk checkout. Jangan menganggap seluruh halaman sudah memakai API: periksa service dan sumber data halaman yang sedang dikerjakan; beberapa file data/demo masih tersedia.

Monorepo menggunakan pnpm workspaces dengan satu `pnpm-lock.yaml` di root:

- `apps/app`: React 19, TypeScript, Vite, React Router, Tailwind CSS, shadcn/ui berbasis Base UI, TanStack React Query, Axios.
- `apps/api`: Express 5, TypeScript, Prisma 7, MySQL dengan adapter MariaDB, Zod, JWT cookie, Swagger/OpenAPI, Multer dan Sharp.
- `packages/shared`: DTO dan kontrak publik TypeScript untuk frontend/backend.
- Runtime root saat panduan ditulis: Node.js 22.x, pnpm 10.33.4. `package.json` dan lockfile menjadi acuan versi sebenarnya.

## Struktur folder

```text
preventive-maintenance/
|-- AGENTS.md
|-- AUTH.md                       # Kontrak auth, environment dan akun admin
|-- package.json                  # Perintah lintas workspace
|-- pnpm-workspace.yaml
|-- pnpm-lock.yaml
|-- vercel.json                   # Build dan routing deployment
|-- api/index.js                  # Entry serverless Vercel
|-- packages/shared/
|   |-- index.ts                  # Ekspor kontrak bersama
|   |-- *.ts                      # DTO auth, API, inventory, maintenance, Pilot Plant
|-- apps/app/
|   |-- components.json           # Konfigurasi shadcn
|   |-- openspec/                 # Proposal, design, spec dan task frontend
|   |-- test/                     # Tes frontend
|   |-- src/
|       |-- main.tsx              # QueryClientProvider dan devtools
|       |-- App.tsx               # Routing dan application shell
|       |-- index.css             # Styling dan token tema
|       |-- components/
|       |   |-- ui/               # Primitif shadcn yang sudah terpasang
|       |   |-- auth/             # Provider, context, route guard
|       |   |-- layout/           # Sidebar dan header
|       |-- pages/
|       |   |-- home/
|       |   |-- inventory/        # Stock, movement dan quarantine
|       |   |-- pilot-plant/
|       |   |-- maintenance/
|       |   |-- notifications/
|       |   |-- kiosk-checkout/
|       |   |-- reports/
|       |   |-- settings/
|       |   |-- login/
|       |   |-- not-found/
|       |-- services/             # Integrasi HTTP dan service per fitur
|       |-- hooks/                # Hook bersama dan sebagian query hooks
|       |-- lib/                  # Axios, query client, utilitas
|       |-- assets/
|-- apps/api/
    |-- openspec/                 # Proposal, design, spec dan task backend
    |-- prisma.config.ts
    |-- prisma/
    |   |-- models/              # Model Prisma per entitas
    |   |-- migrations/          # Riwayat migrasi database
    |   |-- seeders/             # Seeder dan dokumentasinya
    |   |-- schema-design.md     # Dokumentasi schema/ERD
    |-- test/                    # Vitest, kontrak API dan integrasi MySQL
    |-- src/
        |-- index.ts             # Menjalankan server
        |-- app.ts               # Middleware, static files, API, error handler
        |-- routes/              # *.routes.ts dan pendamping *.openapi.ts
        |-- controllers/         # Adapter HTTP
        |-- services/            # Aturan bisnis, query, transaksi, mapping DTO
        |-- validators/          # Schema validasi input
        |-- middlewares/         # Auth, role, upload, request context, error
        |-- config/              # Env, Prisma client, Swagger, auth, media
        |-- interfaces/          # Kontrak internal dan domain error
        |-- generated/           # Prisma client; jangan edit manual
        |-- public/uploads/      # Penyimpanan foto lokal
```

Struktur di atas diringkas, bukan daftar semua file. Jangan mengganti struktur menjadi `modules/`, `domain/`, `infrastructure/`, atau generic CRUD repository tanpa kebutuhan dan arahan pengguna. Komponen khusus halaman berada di `pages/<fitur>/components/`; komponen lintas halaman berada di `components/`.

## Aturan frontend dan UI

- Utamakan komponen shadcn yang tersedia di `apps/app/src/components/ui`: Button, Input, Select, Calendar, Popover, Table, Sheet, Skeleton, dan lainnya. Periksa implementasi lokal sebelum memakai props; komponen proyek berbasis Base UI, sehingga contoh Radix tidak selalu cocok.
- Ikuti desain halaman yang ada. Gunakan notifications dan inventory sebagai referensi layout; jangan melakukan redesign besar ketika tugas hanya menambah fungsi atau memperbaiki bug.
- Filter pencarian, dropdown, tanggal, dan action ditempatkan dalam satu baris pada desktop, responsif pada layar kecil. Untuk stock movement dan quarantine, container filter terpisah dari card tabel, mengikuti notifications. Tabel dan pagination tetap dalam card tersendiri.
- Pertahankan token warna, spacing, typography, pola ikon, dan utilitas `cn` yang ada. Hindari warna hardcoded atau library UI tambahan jika komponen tersedia.
- Pecah tabel, detail sheet/dialog, form dan filter yang cukup kompleks menjadi komponen halaman; page mengatur komposisi dan state halaman.
- Gunakan TanStack React Query untuk server state dan mutation. Gunakan query client bersama di `lib/query-client.ts`; jangan membuat client baru setiap render atau provider duplikat.
- Letakkan akses HTTP di service fitur; gunakan `lib/axios.ts` dan helper yang sesuai. Jangan menduplikasi request di page/component. Pertahankan service Pilot Plant di `services/pilot-plant.service.ts`, termasuk query hooks yang sudah ada; jangan membuat kembali service/hook paralel untuk fungsi yang sama.
- Ikuti pola query key, filter, pagination, invalidation dan penanganan error fitur terkait. Reset page saat filter berubah. Pastikan mutation memperbarui daftar/detail/summary yang terdampak.
- Gunakan Skeleton shadcn sesuai bentuk konten untuk fetch awal. Bedakan pending awal, background refetch, mutation pending, empty state, dan error; jangan menampilkan kosong seolah data selesai saat masih pending atau menghapus data terlihat saat refetch tanpa kebutuhan.
- Tombol submit mengikuti mutation pending untuk mencegah pengiriman ganda. Tampilkan error yang bisa ditindaklanjuti dan sediakan retry bila relevan.
- Pertahankan label aksesibel, termasuk `sr-only` pada filter tanpa label visual. Tombol ikon memerlukan nama aksesibel; gunakan primitive dialog/popover yang menangani fokus dan keyboard.
- Tanggal kalender tetap string `yyyy-MM-dd` jika kontrak API memakai date-only. Jangan mengubahnya melalui UTC sehingga tanggal bergeser. Filter movement memakai `dateFrom/dateTo`; quarantine memakai `reportedFrom/reportedTo`.
- Foto dan nama pada form Pilot Plant tetap satu alur submit pengguna sesuai kontrak API. Gunakan pola preview/edit foto yang ada di inventory. URL `blob:` hanya untuk preview browser, bukan nilai yang disimpan ke database; bersihkan object URL ketika tidak digunakan.
- Jangan menjadikan localStorage atau data dummy sebagai sumber data operasional yang sudah memiliki API.

## Aturan backend dan kontrak

Alur: `routes -> controllers -> services -> Prisma`.

- Routes menentukan path, metode, middleware auth/role/upload dan controller.
- Controllers memvalidasi input HTTP, memanggil service, lalu menggunakan helper respons yang ada.
- Services memiliki aturan bisnis, query, transaksi, DTO mapping dan translasi error persistence. Services tidak mengimpor Express Request/Response, controllers atau routes.
- Gunakan Prisma client dari `src/config/prisma.ts`. Jangan membuat client per request.
- Kontrak publik berada di `packages/shared`; gunakan `import type` untuk DTO. Jangan mengirim generated Prisma types atau seluruh record database sebagai respons. Pilih field DTO secara eksplisit.
- Pertahankan envelope `success/data/meta` atau `success/error/meta`, request ID, pagination dan katalog error. HTTP 204, file/download dan aset statis mengikuti kontrak tanpa envelope JSON.
- Pertahankan JWT HttpOnly cookie, pemeriksaan origin, role dan batas akses existing. Jangan memindahkan token ke localStorage atau memperluas akses endpoint untuk mempermudah frontend.
- Error pengguna mengikuti bahasa Indonesia dan kode error stabil. Jangan membocorkan stack trace, kredensial, query sensitif atau detail database.
- Aturan lintas fitur memiliki satu pemilik transaksi. Teruskan transaction client ke service peserta; jangan membuka transaksi independen untuk operasi yang harus atomik.
- Inventory ledger, saldo/version, quarantine, efek work order dan audit yang terkait harus konsisten. Pertahankan idempotency dan concurrency checks; jangan memperbaiki saldo dengan update langsung yang melewati ledger.
- Maintenance menggunakan kontrak Inventory untuk pemakaian spare part. Dashboard/reports adalah pembacaan data, bukan tempat mutasi bisnis.

### Penamaan domain

- Pilot Plant terdiri dari **Category -> Equipment -> Item**. Gunakan istilah `pilot-plant`, `category`, `equipment`, `item`; jangan memperkenalkan kembali nama `asset/assets` untuk domain ini.
- Item Pilot Plant dan Part inventory adalah dua entitas berbeda. Jangan menambahkan relasi Item ke spare part hanya karena namanya sama-sama item/part.
- Calibration telah dikeluarkan dari model database. Sisa UI/file lama bukan alasan untuk membuat ulang model tanpa permintaan fitur.

### OpenAPI

- Registrasi endpoint ada di `src/routes/*.routes.ts`.
- Anotasi `@openapi` ada di file pendamping `src/routes/*.openapi.ts`, bukan blok panjang di router.
- Setiap perubahan kontrak endpoint harus memperbarui dokumentasi: input, multipart upload, auth, response, error dan pagination yang terdampak.
- Swagger dipasang di `/api/v1/docs/`; scanner membaca `.openapi.ts` pada source dan `.openapi.js` setelah build. Pertahankan komentar pada hasil kompilasi.
- Verifikasi dokumentasi terkompilasi dengan `pnpm --filter express-api-starter-ts test:docs` setelah build API.

## Database, migrasi dan upload

- Sumber schema adalah Prisma di `apps/api/prisma/` (termasuk `models/`), dengan konfigurasi `prisma.config.ts`. Periksa schema aktual dan migrasi terkait sebelum mengubah relasi/kolom.
- Buat migrasi melalui Prisma CLI, bukan menulis file SQL migrasi manual. Jangan mengedit atau menghapus migrasi yang sudah diterapkan untuk menyamakan nama dengan model; buat migrasi baru dan periksa hasilnya.
- Untuk rename atau perubahan relasi, periksa potensi kehilangan data pada migrasi yang dihasilkan. Jangan menerima drop/recreate atau reset database secara otomatis.
- Jangan menjalankan reset, drop, reseed destruktif, atau migrasi terhadap database production tanpa otorisasi untuk tindakan tersebut. Generate Prisma client berbeda dari menerapkan migrasi.
- Sinkronkan `prisma/schema-design.md`, DTO, service, validator, OpenAPI dan seeder bila perubahan schema memengaruhinya.
- Dummy data berada di `prisma/seeders/`. Ikuti dokumentasi seeder, buat rerun aman, dan hindari menimpa data pengguna atau menggandakan ledger.
- Foto Pilot Plant menggunakan `photoKey` di database; URL publik diturunkan oleh API. Pipeline upload memvalidasi/mengolah foto melalui Multer, Sharp dan media storage. Jangan simpan base64 atau object URL browser sebagai key.
- Storage lokal default berada di `apps/api/src/public/uploads`; `MEDIA_ROOT` dapat menggantinya. Route statis ada di `app.ts`. Jangan menghapus `media-storage.service.ts` hanya karena file disajikan secara statis.
- Filesystem deployment serverless bukan penyimpanan upload permanen. Periksa kebutuhan persistence sebelum mengubah deployment/media.

## Development, environment dan validasi

Jalankan dari root; gunakan `pnpm.cmd` di PowerShell bila execution policy memblokir `pnpm.ps1`.

| Perintah | Kegunaan |
| --- | --- |
| `pnpm install` | Install workspace; postinstall membangun shared |
| `pnpm dev` | Build shared, lalu watcher workspace |
| `pnpm dev:app` / `pnpm dev:api` | Menjalankan frontend / backend |
| `pnpm build` | Build shared, API dan app secara berurutan |
| `pnpm typecheck` | Build shared lalu typecheck workspace |
| `pnpm --filter app typecheck` | Typecheck frontend |
| `pnpm --filter express-api-starter-ts typecheck` | Typecheck backend |
| `pnpm test` | Build shared lalu tes API dan frontend |
| `pnpm prisma:generate` | Generate client tanpa menerapkan migrasi |
| `pnpm --filter express-api-starter-ts prisma:seed:pilot-plant` | Seeder demo Pilot Plant; menulis database |

- API development memakai `tsx watch` sehingga restart ketika source berubah.
- Scheduler notifikasi VPS berada di `apps/api/src/schedulers/notifications.scheduler.ts`, dimulai oleh `src/index.ts`: overdue tiap 15 menit, PM/stok pukul 07.00 Asia/Jakarta. Aktif default hanya di production; `NOTIFICATIONS_SCHEDULER_ENABLED` dapat mengaktifkan/menonaktifkan. Aktifkan hanya pada satu worker, bukan entry serverless atau import `app.ts`. Detail operasional di `src/services/notifications.md`.
- Frontend biasanya port 3000, API 5000. Environment lokal masing-masing berada di `apps/app/.env` dan `apps/api/.env`; jangan tampilkan atau commit secret.
- Frontend memakai `VITE_API_BASE_URL` atau proxy development. Nilai berprefix `VITE_` bersifat publik. Backend memvalidasi `DATABASE_URL`, `JWT_SECRET`, `APP_ORIGIN` dan opsi lain di `src/config/env.ts`. Detail auth ada di `AUTH.md`; opsi seed ada di README seeder.
- Shared harus dibangun ulang setelah perubahan DTO jika watcher shared tidak berjalan.
- Jalankan pemeriksaan sesuai perubahan. Layout sederhana: typecheck dan pemeriksaan tampilan bila tersedia. Kontrak API: typecheck, tes terkait dan Swagger. Transaksi/migrasi: tes database terisolasi yang relevan.
- Tes MySQL memiliki guard database khusus. Baca test/script terkait, gunakan database disposable, dan jangan mengarahkan tes destruktif ke database kerja pengguna. Tes yang skip tidak membuktikan integrasi berhasil.
- `pnpm --filter express-api-starter-ts lint` memakai `--fix`; periksa diff karena dapat mengubah source.
- `pnpm build:vercel` **menulis database**: build, `prisma migrate deploy`, lalu seed deploy `--all`. Jangan gunakan sebagai pemeriksaan build lokal biasa.
- `vercel.json` mengarahkan `/api` dan `/public` ke entry API serta route frontend ke SPA. Periksa konfigurasi aktual sebelum mengubah routing.
- Laporkan pemeriksaan yang benar-benar dijalankan, hasilnya, dan batas verifikasi. Jangan mengklaim UI telah diuji di browser jika hanya typecheck.

## Disiplin Git dan commit

- Periksa `git status` dan diff sebelum mengedit maupun commit. Pertahankan perubahan pengguna yang sudah ada; jangan overwrite, discard atau memasukkannya ke commit secara diam-diam.
- Satu commit untuk satu fitur/perbaikan yang utuh dan bisa ditinjau. Frontend, backend, DTO, dokumentasi dan tes yang diperlukan untuk fitur yang sama boleh berada dalam satu commit.
- Pisahkan perubahan tidak terkait: fitur lain, refactor, formatting massal, dependency update, dan dokumentasi mandiri. Jangan memisahkan sedemikian rupa sehingga commit antara sengaja rusak.
- Stage file atau hunk secara selektif. Periksa `git diff --cached` sebelum commit; hindari `git add .` bila working tree berisi pekerjaan campuran.
- Jika pengguna meminta semua perubahan di-commit, tinjau seluruh diff dan kelompokkan menurut fitur yang dapat dilacak. Jangan mengarang riwayat atau klaim asal perubahan yang tidak diketahui.
- Gunakan pesan bahasa Inggris dengan format `type(scope): imperative description`. Contoh:
  - `feat(pilot-plant): add image uploads when creating items`
  - `fix(inventory): reset pagination when filters change`
  - `refactor(inventory): extract movement table component`
  - `docs(agents): document project conventions`
- Gunakan `feat`, `fix`, `refactor`, `docs`, `test`, `build`, `ci`, atau `chore` sesuai isi. Hindari pesan samar seperti `update`, `fix all`, atau `changes`.
- Jalankan validasi relevan sebelum commit. Jangan commit `.env`, secret, uploads pengguna, `node_modules`, atau output build/generated yang diabaikan repository. Commit lockfile ketika dependency berubah.
- Lanjutkan history existing. Jangan rebase/amend commit yang sudah dipublikasikan atau force push untuk merapikan history tanpa permintaan eksplisit. Jangan membuat ulang repository Git.
- Commit dan push ketika diminta pengguna; jangan menganggap setiap edit otomatis harus dipush. Periksa branch dan remote; jangan berasumsi selalu `main`. Jika diminta push ke `main`, gunakan push normal dan tangani divergensi tanpa force push otomatis.

## Cara bekerja dan dokumentasi library

- Baca implementasi tetangga dan dokumen fitur terkait sebelum menambah pola baru. Utamakan perubahan terarah; jangan mengubah struktur folder atau desain di luar kebutuhan tugas.
- Dokumen pendukung: `AUTH.md`, `apps/api/src/README.md`, `apps/api/src/services/*.md`, `apps/api/src/middlewares/errors.md`, `apps/api/prisma/schema-design.md`, `apps/api/prisma/seeders/README.md`, serta OpenSpec di masing-masing app.
- Sebagian README/spec lama menjelaskan baseline historis. Jika berbeda dengan kode sekarang, verifikasi implementasi dan instruksi pengguna; jangan mengembalikan perilaku lama secara otomatis. Contohnya, OpenAPI sekarang memakai file pendamping.
- Untuk tugas OpenSpec, baca proposal/design/spec/tasks perubahan yang dimaksud; tandai task selesai hanya setelah implementasi dan verifikasi yang relevan. Jangan mengasumsikan semua task lama masih aktif.
- Gunakan Context7 MCP saat tugas membahas library, framework, SDK, API library, CLI, atau cloud service: resolve library ID dengan nama resmi dan pertanyaan, pilih sumber resmi/relevan, lalu query docs dengan pertanyaan lengkap. Gunakan versi spesifik jika disebutkan.
- Context7 tidak diperlukan untuk refactor layout existing, script dari awal, debugging business logic, code review, atau konsep pemrograman umum. Jika tool tidak tersedia, nyatakan keterbatasan bila relevan dan gunakan dokumentasi resmi sebagai fallback; jangan mengaku sudah mengambil dokumentasi.
- Sebelum menghapus komponen, cari semua pemakaiannya. Jelaskan komponen yang dihapus dan fungsi sebelumnya dalam laporan perubahan.
- Akhiri pekerjaan dengan ringkasan perubahan, validasi, dan kendala nyata. Perbarui panduan ini ketika arsitektur atau konvensi proyek berubah.
