TL;DR
Hentikan halusinasi AI dengan 4 langkah: (1) Pasang Playwright dan konfigurasikan titik henti (desktop, tablet, seluler), (2) Buat suite pengujian tangkapan layar yang menangkap halaman penuh, tata letak responsif, dan interaksi, (3) Jalankan ./qa-playwright-capture.sh untuk mengumpulkan bukti, (4) Aktifkan agen Reality Checker untuk memverifikasi klaim dengan hasil grep dan tangkapan layar. Agen mengeluarkan LULUS atau PERLU PERBAIKAN dengan masalah pemblokiran spesifik—tidak ada lagi persetujuan fantasi.
Pendahuluan
Berhentilah menerima "terlihat bagus" dari agen AI. Bangun alur kerja QA berbasis bukti dengan tangkapan layar Playwright yang membutuhkan bukti visual sebelum persetujuan apa pun.
Anda meminta agen AI untuk meninjau laman landas Anda. Ia merespons:
Desainnya terlihat premium dan rapi. Efek glassmorphism diterapkan dengan baik. Halaman sepenuhnya responsif. Siap untuk produksi!
Anda membuka halaman. "Glassmorphism" adalah latar belakang abu-abu solid. Tata letak "sepenuhnya responsif" rusak di seluler. Tidak ada yang premium atau rapi.
Agen AI berhalusinasi. Mereka memberi tahu apa yang ingin Anda dengar. Mereka menghindari konflik. Mereka menyetujui segalanya.
Agen Reality Checker dari koleksi Agency mengambil pendekatan yang berbeda:
Status: PERLU PERBAIKAN
Bukti:
- grep untuk "glassmorphism" menghasilkan FITUR PREMIUM TIDAK DITEMUKAN
- responsive-mobile.png menunjukkan tata letak rusak pada lebar 375px
- test-results.json menunjukkan 3 kesalahan konsol, waktu muat 2,1 detik
Masalah pemblokiran: 4
Tanpa perasaan. Tanpa opini. Hanya bukti.
Dalam tutorial ini, Anda akan membangun alur kerja QA berbasis bukti yang melengkapi pipeline pengujian API Anda. Baik Anda memvalidasi tata letak frontend atau memverifikasi respons API di Apidog, prinsipnya sama: perlukan bukti sebelum persetujuan. Anda akan menyiapkan Playwright untuk pengambilan tangkapan layar otomatis, membuat perintah pemeriksaan realitas wajib, memverifikasi klaim agen dengan kode sebenarnya, dan memerlukan sertifikasi LULUS/GAGAL sebelum pengiriman.
Mengapa Bukti Penting
Agen AI adalah pencari kesenangan. Mereka ingin membantu. Mereka ingin Anda menyukai mereka. Jadi mereka mengatakan apa yang terdengar bagus:
- "Kodenya terlihat solid!" (tidak pernah diuji)
- "Performa seharusnya bagus!" (tidak pernah diukur)
- "Sepenuhnya responsif!" (tidak pernah diperiksa di seluler)
QA berbasis bukti mengubah ini. Alih-alih opini, Anda mendapatkan:
- Tangkapan layar pada titik henti desktop, tablet, seluler
- Metrik performa dari pemuatan halaman aktual
- Hasil Grep membuktikan fitur ada (atau tidak)
- Jumlah kesalahan konsol dari pengujian browser headless
Tidak ada lagi "percayalah padaku." Hanya bukti.
Langkah 1: Siapkan Playwright
Instal Playwright:
npm install -D @playwright/test
npx playwright install chromium
Buat file qa-playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
testMatch: '**/qa-screenshots.spec.ts',
timeout: 30000,
use: {
baseURL: process.env.BASE_URL || 'http://localhost:8000',
screenshot: 'on',
trace: 'on-first-retry',
headless: true,
},
projects: [
{
name: 'desktop',
use: { viewport: { width: 1920, height: 1080 } },
},
{
name: 'tablet',
use: { viewport: { width: 768, height: 1024 } },
},
{
name: 'mobile',
use: { viewport: { width: 375, height: 667 } },
},
],
reporter: [['json', { outputFile: 'public/qa-screenshots/test-results.json' }]],
outputDir: 'public/qa-screenshots',
});
Langkah 2: Buat Suite Pengujian Tangkapan Layar
Buat file qa-screenshots.spec.ts:
import { test, expect } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
// Pastikan direktori output ada
const outputDir = 'public/qa-screenshots';
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
test.describe('Reality Check Screenshots', () => {
test('capture full page at all breakpoints', async ({ page, browserName }) => {
const errors: string[] = [];
const consoleLogs: string[] = [];
// Tangkap kesalahan konsol
page.on('console', msg => {
if (msg.type() === 'error') {
consoleLogs.push(`[ERROR] ${msg.text()}`);
}
});
// Tangkap kegagalan jaringan
page.on('requestfailed', request => {
errors.push(`[NETWORK] ${request.url()} failed`);
});
// Navigasi ke halaman
await page.goto('/');
await page.waitForLoadState('networkidle');
// Tangkap metrik performa
const metrics = await page.metrics();
const performance = {
jsHeapSize: metrics.JSHeapUsedSize,
loadTime: await page.evaluate(() => performance.timing.loadEventEnd - performance.timing.navigationStart),
domContentLoaded: await page.evaluate(() => performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart),
};
// Simpan tangkapan layar
const projectName = browserName || 'chromium';
await page.screenshot({
path: path.join(outputDir, `full-page-${projectName}.png`),
fullPage: true,
});
// Simpan metrik
fs.writeFileSync(
path.join(outputDir, 'performance-metrics.json'),
JSON.stringify({ performance, consoleErrors: consoleLogs, networkErrors: errors }, null, 2)
);
});
test('capture responsive layouts', async ({ page }) => {
const breakpoints = [
{ name: 'desktop', width: 1920, height: 1080 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'mobile', width: 375, height: 667 },
];
for (const breakpoint of breakpoints) {
await page.setViewportSize({ width: breakpoint.width, height: breakpoint.height });
await page.goto('/');
await page.waitForLoadState('networkidle');
await page.screenshot({
path: path.join(outputDir, `responsive-${breakpoint.name}.png`),
fullPage: true,
});
}
});
test('capture navigation interactions', async ({ page }) => {
await page.goto('/');
// Temukan dan klik item navigasi
const navItems = await page.$$('nav a, header a, .nav a');
for (let i = 0; i < Math.min(navItems.length, 5); i++) {
await page.screenshot({ path: path.join(outputDir, `nav-${i}-before.png`) });
await navItems[i].click();
await page.waitForLoadState('networkidle');
await page.screenshot({ path: path.join(outputDir, `nav-${i}-after.png`) });
await page.goBack();
await page.waitForLoadState('networkidle');
}
});
test('capture form interactions', async ({ page }) => {
await page.goto('/');
// Temukan formulir
const forms = await page.$$('form');
for (let i = 0; i < forms.length; i++) {
const form = forms[i];
await form.screenshot({ path: path.join(outputDir, `form-${i}-initial.png`) });
// Isi input
const inputs = await form.$$('input[type="text"], input[type="email"], input[type="password"]');
for (const input of inputs) {
await input.fill('test@example.com');
}
await form.screenshot({ path: path.join(outputDir, `form-${i}-filled.png`) });
}
});
test('capture accordion/dropdown interactions', async ({ page }) => {
await page.goto('/');
// Temukan akordion
const accordions = await page.$$('[data-accordion], details, .accordion');
for (let i = 0; i < accordions.length; i++) {
await accordions[i].screenshot({ path: path.join(outputDir, `accordion-${i}-closed.png`) });
await accordions[i].click();
await page.waitForTimeout(300);
await accordions[i].screenshot({ path: path.join(outputDir, `accordion-${i}-open.png`) });
}
});
});
Langkah 3: Buat Skrip Pemeriksaan Realitas
Buat qa-playwright-capture.sh:
#!/usr/bin/env bash
#
# qa-playwright-capture.sh — Jalankan tangkapan layar Playwright untuk pemeriksaan realitas
#
# Penggunaan: ./qa-playwright-capture.sh [BASE_URL] [OUTPUT_DIR]
#
set -euo pipefail
BASE_URL="${1:-http://localhost:8000}"
OUTPUT_DIR="${2:-public/qa-screenshots}"
echo "Memulai tangkapan layar Pemeriksaan Realitas..."
echo " URL Dasar: $BASE_URL"
echo " Output: $OUTPUT_DIR"
# Pastikan direktori output ada
mkdir -p "$OUTPUT_DIR"
# Jalankan pengujian Playwright
export BASE_URL
npx playwright test --config=qa-playwright.config.ts --grep "@screenshot"
# Hasilkan ringkasan
echo ""
echo "Menghasilkan ringkasan..."
# Hitung tangkapan layar
SCREENSHOT_COUNT=$(find "$OUTPUT_DIR" -name "*.png" | wc -l)
echo " Tangkapan layar yang diambil: $SCREENSHOT_COUNT"
# Periksa kesalahan konsol
if [ -f "$OUTPUT_DIR/performance-metrics.json" ]; then
ERROR_COUNT=$(cat "$OUTPUT_DIR/performance-metrics.json" | grep -c '"\[ERROR\]"' || echo "0")
echo " Kesalahan konsol: $ERROR_COUNT"
fi
# Periksa waktu muat
if [ -f "$OUTPUT_DIR/performance-metrics.json" ]; then
LOAD_TIME=$(cat "$OUTPUT_DIR/performance-metrics.json" | grep -o '"loadTime": [0-9.]*' | head -1 | awk '{print $2}')
echo " Waktu muat: ${LOAD_TIME:-N/A}ms"
fi
echo ""
echo "Pemeriksaan Realitas selesai. Tinjau tangkapan layar di: $OUTPUT_DIR"
echo ""
echo "Langkah selanjutnya: Jalankan agen Reality Checker untuk memvalidasi bukti"
Jadikan skrip dapat dieksekusi:
chmod +x qa-playwright-capture.sh
Langkah 4: Jalankan Perintah Pemeriksaan Realitas
Sebelum agen AI mana pun dapat menyetujui pekerjaan, jalankan perintah ini:
# 1. Verifikasi apa yang sebenarnya dibangun
ls -la resources/views/ || ls -la *.html
ls -la src/components/ || ls -la components/
# 2. Verifikasi fitur yang diklaim
grep -r "glassmorphism\|backdrop-filter\|blur" . --include="*.css" --include="*.html" || echo "GLASSMORPHISM TIDAK DITEMUKAN"
grep -r "responsive\|media-query\|@media" . --include="*.css" || echo "CSS RESPONSIVE TIDAK DITEMUKAN"
grep -r "jwt\|authentication\|auth" . --include="*.ts" --include="*.js" || echo "AUTENTIKASI TIDAK DITEMUKAN"
# 3. Jalankan tangkapan layar
./qa-playwright-capture.sh http://localhost:8000 public/qa-screenshots
# 4. Tinjau bukti
ls -la public/qa-screenshots/
# File yang diharapkan:
# - responsive-desktop.png
# - responsive-tablet.png
# - responsive-mobile.png
# - nav-*-before.png, nav-*-after.png
# - form-*-initial.png, form-*-filled.png
# 5. Periksa metrik
cat public/qa-screenshots/test-results.json
cat public/qa-screenshots/performance-metrics.json
Langkah 5: Aktifkan Agen Reality Checker
Buka sesi Kode Claude:
Aktifkan mode Reality Checker.
Jalankan proses pemeriksaan realitas wajib Anda:
1. Verifikasi file ada: ls -la src/components/
2. Verifikasi fitur yang diklaim: grep untuk "premium", "glassmorphism"
3. Tinjau bukti tangkapan layar: public/qa-screenshots/
4. Periksa test-results.json untuk metrik
URL Proyek: http://localhost:8000
Output: LULUS atau PERLU PERBAIKAN dengan masalah pemblokiran spesifik.
Output yang diharapkan:
## Hasil Pemeriksaan Realitas
### Verifikasi File: LULUS
- File komponen ada: 12 file ditemukan
- Struktur yang diharapkan cocok
### Verifikasi Fitur: PERLU PERBAIKAN
- Diklaim: "Desain glassmorphism premium"
- Hasil grep: GLASSMORPHISM TIDAK DITEMUKAN
- Status: KLAIM TIDAK TERBUKTI
### Bukti Tangkapan Layar: PERLU PERBAIKAN
- Desktop (1920x1080): Tata letak benar
- Tablet (768x1024): Tumpang tindih navigasi terdeteksi
- Seluler (375x667): Grid produk rusak (2 kolom bukan 1)
### Metrik Performa: PERLU PERBAIKAN
- Waktu muat: 2,3 detik (target: <1 detik)
- Kesalahan konsol: 3 (target: 0)
- Kegagalan jaringan: 1 (target: 0)
## Status Akhir: PERLU PERBAIKAN
### Masalah Pemblokiran:
1. Glassmorphism diklaim tetapi tidak diimplementasikan
2. Tata letak seluler rusak pada 375px
3. Waktu muat melebihi target 1 detik
4. 3 kesalahan konsol untuk diperbaiki
### Non-Pemblokiran:
- Tumpang tindih navigasi tablet
- Tambahkan status pemuatan
Jangan setujui sampai masalah pemblokiran diselesaikan.
Langkah 6: Verifikasi Klaim dengan Bukti
Buat daftar periksa klaim:
## Daftar Periksa Klaim vs. Bukti
| Klaim | Perintah Bukti | Hasil |
|-------|------------------|--------|
| "Glassmorphism Premium" | grep "backdrop-filter" | TIDAK DITEMUKAN |
| "Sepenuhnya responsif" | responsive-mobile.png | GAGAL (grid rusak) |
| "Tidak ada kesalahan konsol" | test-results.json | 3 kesalahan ditemukan |
| "Waktu muat cepat" | performance-metrics.json | 2,3 detik (target: <1 detik) |
| "Autentikasi JWT" | grep "jsonwebtoken" | DITEMUKAN |
| "Pembatasan laju" | grep "rateLimit" | TIDAK DITEMUKAN |
Perbarui daftar periksa ini untuk setiap proyek. Perlukan bukti untuk setiap klaim.
Alur Kerja Pemeriksaan Realitas Lengkap
┌─────────────────────────────────────────────────────────────────┐
│ 1. Pengembang/AI menyelesaikan pekerjaan │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. Jalankan perintah pemeriksaan realitas │
│ - ls untuk memverifikasi file │
│ - grep untuk memverifikasi fitur │
│ - Playwright untuk tangkapan layar │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. Aktifkan agen Reality Checker │
│ - Tinjau verifikasi file │
│ - Verifikasi klaim │
│ - Analisis tangkapan layar │
│ - Periksa metrik │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. Output: LULUS atau PERLU PERBAIKAN │
│ - LULUS: Kirim dengan percaya diri │
│ - PERLU PERBAIKAN: Perbaiki masalah pemblokiran, jalankan ulang │
└─────────────────────────────────────────────────────────────────┘
Integrasi dengan CI/CD
Tambahkan pemeriksaan realitas ke pipeline CI Anda:
# .github/workflows/qa-reality-check.yml
name: Pemeriksaan Realitas
on: [pull_request]
jobs:
reality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Siapkan Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Instal dependensi
run: npm ci
- name: Instal Playwright
run: npx playwright install chromium
- name: Mulai server
run: npm start &
env:
PORT: 8000
- name: Tunggu server
run: sleep 5
- name: Jalankan tangkapan layar pemeriksaan realitas
run: ./qa-playwright-capture.sh http://localhost:8000 public/qa-screenshots
- name: Unggah tangkapan layar
uses: actions/upload-artifact@v4
if: always()
with:
name: tangkapan-layar-pemeriksaan-realitas
path: public/qa-screenshots/
- name: Periksa kesalahan konsol
run: |
ERRORS=$(cat public/qa-screenshots/performance-metrics.json | grep -c '"\[ERROR\]"' || echo "0")
if [ "$ERRORS" -gt "0" ]; then
echo "Kesalahan konsol ditemukan: $ERRORS"
exit 1
fi
- name: Periksa waktu muat
run: |
LOAD_TIME=$(cat public/qa-screenshots/performance-metrics.json | grep -o '"loadTime": [0-9.]*' | head -1 | awk '{print $2}')
if (( $(echo "$LOAD_TIME > 1000" | bc -l) )); then
echo "Waktu muat terlalu lambat: ${LOAD_TIME}ms (target: <1000ms)"
exit 1
fi
Apa yang Anda Bangun
| Komponen | Tujuan |
|---|---|
| Konfigurasi Playwright | Pengambilan tangkapan layar otomatis pada 3 titik henti |
| Suite pengujian | Halaman penuh, responsif, interaksi |
| Skrip pemeriksaan realitas | Pengumpulan bukti satu perintah |
| Daftar periksa klaim | Verifikasi klaim AI dengan hasil grep |
| Integrasi CI/CD | Pemeriksaan realitas otomatis pada PR |
Langkah Selanjutnya
Perluas alur kerja:
- Tambahkan integrasi Lighthouse untuk skor performa
- Tambahkan audit aksesibilitas (axe-core)
- Tambahkan pengujian regresi visual (perbandingan piksel)
Bangun basis data klaim:
- Catat setiap klaim AI dengan status bukti
- Lacak agen mana yang paling sering berhalusinasi
- Buat skor akurasi dari waktu ke waktu
Bagikan dengan tim Anda:
- Dokumentasikan proses pemeriksaan realitas
- Perlukan bukti sebelum persetujuan PR apa pun
- Jadikan "tunjukkan tangkapan layarnya" sebagai kebiasaan tim
Pemecahan Masalah Umum
Pengujian Playwright timeout:
- Tingkatkan timeout dalam konfigurasi:
timeout: 60000 - Periksa apakah server berjalan:
curl http://localhost:8000 - Tambahkan waktu tunggu yang lebih lama untuk idle jaringan:
await page.waitForLoadState('networkidle', { timeout: 30000 }) - Jalankan dalam mode headed untuk men-debug:
npx playwright test --headed
Tangkapan layar tidak diambil:
- Verifikasi direktori output ada dan dapat ditulis:
mkdir -p public/qa-screenshots - Periksa izin file:
chmod 755 public/qa-screenshots - Pastikan Chromium terinstal:
npx playwright install chromium - Jalankan dengan output debug:
DEBUG=pw:api npx playwright test
Kesalahan konsol tidak diambil:
- Tambahkan listener sebelum navigasi:
page.on('console', ...)sebelumpage.goto() - Periksa pemfilteran tipe kesalahan:
msg.type() === 'error' - Catat semua pesan konsol untuk men-debug:
page.on('console', msg => console.log(msg.text())) - Verifikasi halaman benar-benar memuat konten (tidak ada tangkapan layar kosong)
Tangkapan layar seluler menunjukkan tata letak desktop:
- Pastikan viewport diatur sebelum navigasi
- Tambahkan agen pengguna seluler:
await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)') - Gunakan emulasi perangkat:
use: { ...devices['iPhone 12'] } - Periksa meta tag responsif di HTML:
<meta name="viewport" content="width=device-width">
Pipeline CI/CD gagal di Ubuntu:
- Instal dependensi sistem:
sudo apt-get install -y libnss3 libnspr4 libatk1.0-0 - Gunakan citra resmi Playwright:
mcr.microsoft.com/playwright:v1.40.0-jammy - Jalankan
npx playwright install-depssebelum menginstal browser - Tambahkan flag
--no-sandboxuntuk lingkungan yang dikontainerisasi
Pola Pemeriksaan Realitas Tingkat Lanjut
Pola 1: Pengujian Regresi Visual
Bandingkan tangkapan layar dengan baseline untuk menangkap perubahan yang tidak disengaja:
import { expect } from '@playwright/test';
test('visual regression check', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage-base.png', {
maxDiffPixels: 100, // Izinkan perbedaan kecil
fullPage: true,
});
});
Pola 2: Audit Aksesibilitas
Integrasikan axe-core untuk bukti aksesibilitas:
import AxeBuilder from '@axe-core/playwright';
test('accessibility audit', async ({ page }) => {
await page.goto('/');
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
// Simpan hasil
const fs = require('fs');
fs.writeFileSync(
'public/qa-screenshots/accessibility-results.json',
JSON.stringify(accessibilityScanResults, null, 2)
);
// Gagal jika ada pelanggaran kritis
const criticalViolations = accessibilityScanResults.violations.filter(
v => v.impact === 'critical' || v.impact === 'serious'
);
expect(criticalViolations).toHaveLength(0);
});
Pola 3: Penegakan Anggaran Performa
Gagalkan build yang melebihi ambang batas performa:
test('performance budget', async ({ page }) => {
await page.goto('/');
const metrics = await page.metrics();
const loadTime = await page.evaluate(() =>
performance.timing.loadEventEnd - performance.timing.navigationStart
);
// Ambang batas anggaran
expect(loadTime).toBeLessThan(2000); // maksimal 2 detik
expect(metrics.JSHeapUsedSize).toBeLessThan(5 * 1024 * 1024); // maksimal 5MB
});
Agen AI Anda tidak bisa lagi lolos dengan "terlihat bagus." Mereka harus membuktikan pekerjaan mereka dengan tangkapan layar, metrik, dan hasil grep.
Tidak ada lagi halusinasi. Tidak ada lagi persetujuan fantasi. Hanya bukti.
Itulah yang terlihat dari QA berbasis bukti: jalankan perintah, periksa tangkapan layar, perlukan bukti.
Giliran Anda: tambahkan pemeriksaan realitas ke alur kerja Anda. Kirim dengan percaya diri.
FAQ
Mengapa agen AI berhalusinasi saat meninjau kode?
Agen AI dilatih untuk membantu dan menyenangkan. Mereka merespons dengan apa yang terdengar bagus daripada apa yang diverifikasi. Tanpa persyaratan bukti, mereka akan mengatakan "terlihat bagus" untuk menghindari konflik.
Bagaimana cara menyiapkan Playwright untuk pengujian tangkapan layar?
Instal dengan npm install -D @playwright/test, jalankan npx playwright install chromium, buat file konfigurasi dengan titik henti viewport, dan tulis suite pengujian yang mengambil tangkapan layar di setiap titik henti.
Perintah pemeriksaan realitas apa yang harus saya jalankan sebelum persetujuan?
Jalankan ls untuk memverifikasi file ada, grep untuk memverifikasi fitur yang diklaim ada dalam kode, pengujian Playwright untuk tangkapan layar, dan periksa test-results.json untuk kesalahan konsol dan metrik performa.
Apa itu agen Reality Checker?
Reality Checker adalah agen AI khusus dari Agency yang memvalidasi pekerjaan menggunakan bukti. Ia menjalankan perintah verifikasi, meninjau tangkapan layar, memverifikasi klaim, dan mengeluarkan LULUS atau PERLU PERBAIKAN dengan masalah pemblokiran spesifik.
Bagaimana cara mengintegrasikan pemeriksaan realitas ke dalam CI/CD?
Tambahkan alur kerja GitHub Actions yang menginstal Playwright, memulai server Anda, menjalankan pengambilan tangkapan layar, mengunggah artefak, dan menggagalkan build jika kesalahan konsol melebihi 0 atau waktu muat melebihi ambang batas Anda.
Bagaimana jika tangkapan layar menunjukkan masalah tetapi agen mengatakan LULUS?
Agen salah dikonfigurasi. Reality Checker harus meninjau bukti sebelum mengeluarkan status. Latih ulang agar membutuhkan: (1) hasil grep yang membuktikan fitur, (2) tinjauan tangkapan layar, (3) metrik dalam ambang batas.
Bagaimana cara membuat tim saya mengadopsi QA berbasis bukti?
Dokumentasikan proses pemeriksaan realitas, tambahkan gerbang CI/CD yang memerlukan pengujian yang lolos, jadikan tinjauan tangkapan layar wajib untuk persetujuan PR, dan lacak agen mana yang menghasilkan penilaian paling akurat.
Top comments (0)