think
16px
820px

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_4 worktree. 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_4PENDIRIAN_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_5 branch):
  • ../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_5 worktree — read for reference only. Implement in dev_4. Branch new work off master (local dev/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_PERKUMPULANPENDIRIAN_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.tsSUBMISSION_TYPE_LABELS["PENDIRIAN_PERKUMPULAN"] = "Pendirian Perkumpulan".
- lib/destination-for.ts — extend PtSubmissionType union, flowBasePath() case → "perkumpulan", add to TERMINAL_TYPES.
- lib/flow-steps.tsPERKUMPULAN_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 off master. Never touch dev_5/dev_5 files (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 test ahu_ocr_dev4_test port 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 push hides missing migrations from tests.
  • Contract: contract/review.ts (zod strictObjects), aliased @contract/review in both tsconfigs.
  • LLM: Qwen thinking model → pass enable_thinking=false on 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/upload and share the URL.

9. Source vs. outside (for reconciliation)

  • In-project (authoritative for us): the dev_5 flow docs + SABH FormDataPerkumpulan.php anchors 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.