Handoff Brief — PENDIRIAN_PERKUMPULAN flow (Dev-B / dev_4)
Purpose: everything a fresh Claude Code session needs to carry the Perkumpulan pendirian flow forward in the
dev_4worktree. Written 2026-08-07 by the session that did the PT Pendirian audit + the Yayasan/Perkumpulan intake-design research.
0. Ownership & where things live
- Efran /
dev_4→PENDIRIAN_PERKUMPULAN. ← this is your lane. - dev5 (Dev A) →
PENDIRIAN_YAYASAN. Sibling flow, shares code (see §6 "shared files"). - Design source of truth (read-only reference, lives on the
dev_5branch): ../dev_5/docs/flows/flow-pendirian-perkumpulan.md← THE spec for this flow. Read it first.../dev_5/docs/flows/flow-pendirian-yayasan.md← sibling, for the shared bits.../dev_5/docs/superpowers/plans/2026-08-06-pendirian-yayasan-perkumpulan.md← master impl plan (phases 0–5, ~124 tasks, file structure).- Do NOT edit files in the
dev_5worktree — read for reference only. Implement indev_4. Branch new work offmaster(localdev/4==origin/master, synced 2026-08-07).
1. Locked design facts for Perkumpulan (from the flow doc, all SABH-code-anchored)
| Aspect | Value | Anchor |
|---|---|---|
| id_aksi / product | 14 / 60 | UploadAktaController.php:59 actionPerkumpulan |
| Flow shape | 4-step, akta-first, terminal read-only | mirrors PT pendirian |
| Documents | Akta only (single-document flow) | no file_ktp/file_npwp; KTP/NPWP belong to perubahan (id_aksi 15) |
| Organs | Rapat Anggota / Pengurus / Pengawas | Rapat Anggota stored in SABH pembina column (_formPengurusPerkumpulan.php:99-110) |
| AD/ART | REQUIRED: asas_tujuan, hak_kewajiban, pengelola, mekanisme, pembubaran |
FormDataPerkumpulan.php:126-128 |
| Kekayaan awal | NOT required (Rp100jt check commented out in SABH) → no rule | FormDataPerkumpulan.php:130-131,243-247 |
| Asing variant | identity-only (passport/KITAS). No Kemenlu doc (contrast Yayasan) | FormDataPerkumpulan.php:69,71 |
nama_lambang |
NOT required (it's in safe, not required) — do not treat as mandatory AD/ART |
FormDataPerkumpulan.php:116 |
| Verifikator | SABH has a kasie verifikator, but it's downstream → out of PoC scope (D4b); flow stays terminal | VerifikatorAktifPerkumpulanController.php:15 |
2. Rule set (D11 — Perkumpulan variant)
| Rule | Severity | Overridable | Notes |
|---|---|---|---|
AKTA_PRESENT |
FAIL | no | akta must be uploaded |
ORGAN_COMPLETENESS |
WARNING | yes | rapat_anggota/pengurus/pengawas |
ADART_COMPLETENESS |
WARNING | yes | 5 fields (§1). Perkumpulan-only rule — not in Yayasan |
NAMA_AVAILABILITY |
WARNING | yes | SABH readonly tbl_order_name+tbl_badan_hukum base='perkumpulan' |
Dropped (no anchor): all kekayaan rules, KTP/NPWP/NIK rules, saham/modal/bukti-setor/KBLI. Candidate GAP (from web research, not in the SABH-anchored design): "min. 3 pendiri WNI" — regulation requires it; D11 has no founder-count rule. Flag to Efran whether to add.
3. Intake design decision (made this session) — TRACK-FIRST + classifier-as-guardrail
The user chose track-first: the Perkumpulan sidebar entry ("Permohonan Baru") is the track declaration. User clicks Perkumpulan → declares lokal/asing up front → uploads akta.
- The classifier does NOT decide the track. It runs as a guardrail/confirmation: verify the uploaded akta actually reads as a Perkumpulan pendirian deed (Rapat Anggota organ / "AKTA PENDIRIAN PERKUMPULAN" title); if it disagrees with the chosen track, warn on the existing classification board (reuse PT/apostille override pattern).
- Why (grounded in our model's real capability): the trained GPU classifier (
ahu-doc-classifier, LayoutLMv3) has no yayasan/perkumpulan labels. The nirlaba classifier is in-app-LLM-only, untuned, BLOCKED-ON-S5, with no trained fallback. And the notary always knows the track for certain. So auto-detecting the track (PT-style) buys little and risks misrouting the whole downstream flow. Once real akta arrive + tuned, the guardrail can be promoted to auto-suggest-with-confirm.
4. New sidebar structure (user-provided, FINAL)
Utama
Dashboard
PT
Permohonan Baru
Perbaikan Data PT
Yayasan
Permohonan Baru ← dev5 owns
Perkumpulan
Permohonan Baru ← you own
Implement in frontend/src/components/layout/sidebar.tsx (notaris nav groups). This is a SHARED file with dev5 — coordinate so both new groups land without a conflict.
5. Wiring checklist (Perkumpulan)
Backend
- backend/src/security/domains.ts — add PENDIRIAN_PERKUMPULAN to DOMAIN_BY_TYPE (joins NOTARIS_FAMILY_TYPES, so ?family=notaris + notaris dashboard pick it up). ⚠️ The notaris domain is literally named "PT" today — a naming smell for a nirlaba entity. Recommended: rename to NOTARIS (or split PT/NIRLABA under the notaris persona). Coordinate with dev5; at minimum add the type.
- backend/src/services/submission-type-inference.ts — map classified AKTA_PENDIRIAN_PERKUMPULAN → PENDIRIAN_PERKUMPULAN.
- New classifier taxonomy (nirlaba, apostille-classifier pattern): class AKTA_PENDIRIAN_PERKUMPULAN; + AKTA_SUBTYPE_MAP → subtype perkumpulan.
- New schema backend/src/schema/akta-perkumpulan.ts (variant of the shared organ-aware extractor, variant: "perkumpulan").
- PERKUMPULAN_PENDIRIAN_RULE_SET (the D11 rules above) — Perkumpulan-exclusive.
- SubmissionType enum + registry/dispatch entry; add to TERMINAL_TYPES.
- NAMA_AVAILABILITY query with base='perkumpulan'.
Frontend
- lib/submission-actions.ts — SUBMISSION_TYPE_LABELS["PENDIRIAN_PERKUMPULAN"] = "Pendirian Perkumpulan".
- lib/destination-for.ts — extend PtSubmissionType union, flowBasePath() case → "perkumpulan", add to TERMINAL_TYPES.
- lib/flow-steps.ts — PERKUMPULAN_LABELS (terminal 4-step: Unggah → Klasifikasi → Proses & Periksa → Selesai).
- routes.tsx — /perkumpulan/pendirian/... upload/klasifikasi/review/status routes.
- KlasifikasiPage branch; dashboard ActionCard; sidebar group (§4).
- Review UI is universal — reuse the ReviewEngine projector→sections pattern + validation-banner→field redirect (targetFieldRef/sectionKey) that the PT flows use.
6. Shared-with-dev5 files — COORDINATE before touching (D10)
These are touched by BOTH Yayasan (dev5) and Perkumpulan (you). Agree who scaffolds them to avoid merge pain:
- The organ-aware shared extractor + OrganMember type (variant discriminator).
- The nirlaba classifier taxonomy file (shared label set).
- sidebar.tsx (both add a sibling group).
- security/domains.ts, submission-type-inference.ts, the classifier label enum, AKTA_SUBTYPE_MAP.
Perkumpulan-EXCLUSIVE (safe to build without coordination): PERKUMPULAN_PENDIRIAN_RULE_SET + ADART_COMPLETENESS, akta-perkumpulan.ts schema variant, /perkumpulan/* routes/pages, PERKUMPULAN_LABELS.
7. BLOCKED-ON-S5
Real Perkumpulan akta samples menyusul; synthetic rejected. Blocked until akta arrive: extractor prompt tuning + organ/AD-ART accuracy tests. NOT blocked (build in parallel now): enum/registry/dispatch/context builder, rule-set logic, classifier taxonomy scaffold + board, route family, entire frontend mirror, NAMA_AVAILABILITY.
8. Engineering conventions / reminders
- Worktree: work in
dev_4; branch offmaster. Never touchdev_5/dev_5files (read-only). Push only when Efran asks. - bun:
/home/efran/.bun/bin/bun. Typecheck:node node_modules/.bin/tsc --noEmit(backend + frontend). - Backend tests:
bun test; DB testahu_ocr_dev4_testport 47030. NEVER run two backend suites concurrently (shared DB → false fails). Baseline has ~1–2 environmental fails. - Frontend tests:
vitest run; use JSON reporter (--reporter=json --outputFile=) for reliable failure capture. Run FULL suites (not just typecheck) before any push. - Prisma: schema changes need a real migration file (staging runs
migrate deploy);db pushhides missing migrations from tests. - Contract:
contract/review.ts(zodstrictObjects), aliased@contract/reviewin both tsconfigs. - LLM: Qwen thinking model → pass
enable_thinking=falseon extraction calls or you get reasoning text, not JSON (silent empty results). - Engine repos hands-off: don't edit
ahu-doc-classifier; prepare integration prompts instead. - AHU platform contract: model/OCR egress goes through the gateway when flipped (
ahu-gpu-manager/docs/CONVENTIONS.md); changes dormant until env flip. - Shared BO docs (if any doc-reuse): ref-count guard (NIK/name/sourceDocumentId) before any fs-delete.
- .md deliverables: upload via
curl -F "file=@<file>.md" https://x056.think.val.id/uploadand share the URL.
9. Source vs. outside (for reconciliation)
- In-project (authoritative for us): the dev_5 flow docs + SABH
FormDataPerkumpulan.phpanchors above. Design policy D5/D6: SABH code wins over general regulation. - Outside (web, regulation/practice) — divergences to decide on: min-3-WNI founders (regulation requires; our D11 doesn't have it); regulation lists domisili/notulen/sumber-dana docs (our design is akta-only per SABH upload transaction); regulation says AD/ART includes "lambang" (our code says not required). These are known deltas, sided with SABH code — revisit only if Efran wants regulatory completeness over SABH-parity.