hanoman 0.9.19 → 0.9.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +168 -546
  3. package/dist/server.js +1146 -2465
  4. package/docs/agent-integration.md +9 -74
  5. package/package.json +1 -1
  6. package/prisma/migrations/20261010070000_remove_memory_changelog/migration.sql +40 -0
  7. package/prisma/schema.prisma +1 -80
  8. package/web/assets/{DalangHanomanScreen-aLBtUGE4.js → DalangHanomanScreen-DqzYitwv.js} +1 -1
  9. package/web/assets/{DocPreviewModal-CHrsP0pL.js → DocPreviewModal-Chk-jQ51.js} +1 -1
  10. package/web/assets/{DocsWorkspace-D262CVxH.js → DocsWorkspace-DuNVIjTg.js} +1 -1
  11. package/web/assets/{IdeScreen-D2GI3KYh.js → IdeScreen-BZGVyFT5.js} +1 -1
  12. package/web/assets/{LeadScreen-eb_DK1j6.js → LeadScreen-35VgddUo.js} +1 -1
  13. package/web/assets/{ReviewScreen-DarOFH_a.js → ReviewScreen-EkG8ywTU.js} +1 -1
  14. package/web/assets/{SchedulerScreen-DKoMf2LT.js → SchedulerScreen-ClaLLB8Y.js} +1 -1
  15. package/web/assets/SettingsScreen-liOlVCeT.js +62 -0
  16. package/web/assets/{TeamScreen-C2fSsQ8C.js → TeamScreen-Dzl6Ruju.js} +1 -1
  17. package/web/assets/{TerminalScreen-GsfOMtu5.js → TerminalScreen-CK3SzzgP.js} +1 -1
  18. package/web/assets/{TriageScreen-DdKMAroz.js → TriageScreen-EtBRNg-t.js} +1 -1
  19. package/web/assets/{VpsScreen-CDAjvyT1.js → VpsScreen-9qeTHo1w.js} +1 -1
  20. package/web/assets/index-D5w059cP.js +1063 -0
  21. package/web/assets/{live-Cz6dWAau.js → live-Bz-jmiWI.js} +1 -1
  22. package/web/index.html +1 -1
  23. package/web/assets/ChangelogScreen-DL5v_FZf.js +0 -1
  24. package/web/assets/SettingsScreen-BAUhwd5K.js +0 -62
  25. package/web/assets/index-gNO91_qw.js +0 -1063
@@ -112,42 +112,8 @@ perlu mengambilnya, cukup rujuk tabel di bawah:
112
112
  | `agents` | `/api/custom-agents*` | katalog custom agent global & per project — **`agents:write` mengubah apa yang dilihat SETIAP sesi baru** (ADR-0094) |
113
113
  | `skills` | `/api/skills*` | skill global hanoman, user, plugin (baca-saja) & per project, termasuk isi berkasnya — **`skills:write` pada skill global hanoman mengubah instruksi SETIAP sesi baru di semua project** |
114
114
  | `telegram` | `/api/telegram*` kecuali sub-path kredensial | context/memory/reply/audit kanal operator Telegram (ADR-0096) |
115
- | `memory` | `/api/memories*` kecuali `…/activate` dan `…/reject` (cookie-only) | memori project bersama. Token **wajib** punya allowlist project (`projectIds`); project ditentukan dari header `x-hanoman-repo` yang diisi CLI MCP, bukan dari parameter (ADR-0178) |
116
115
  | `team` | `/api/tasks*`, `/api/members*` | papan **Tim**: kartu kerja MANUSIA & direktori anggota (ADR-0157). `status` kartu milik manusia — ia **bukan** `stage` backlog. `POST /api/tasks/:id/escalate` melahirkan backlog item dan tetap `team:write` (cermin `POST /api/tickets/:id/accept`) |
117
116
 
118
- ### Memori project (`/api/memories`, ADR-0178)
119
-
120
- - Project **tidak** dipilih lewat parameter. CLI MCP hanoman (`hanoman mcp`) membaca repo di direktori
121
- kerjanya — `origin`, root commit, HEAD — dan mengirimnya sebagai header `x-hanoman-repo`; server
122
- mencocokkannya ke `Project.gitRemote` dan ke allowlist **Project yang diizinkan** pada token.
123
- - Token tanpa allowlist → `403 {need:"projectIds"}`; mengirim `projectId` → `400`.
124
- - Jangkar (`anchors[]`) diisi path saja; blob SHA diisi CLI dari HEAD dan diverifikasi ulang server.
125
- Usulan dengan jangkar terverifikasi langsung `active`; tanpa jangkar atau `kind: decision` masuk
126
- review manusia (`…/activate` / `…/reject` cookie-only).
127
- - Galat: `404` remote tak dikenal / root commit beda · `409 {duplicateOf}` · `422 {anchor}` jangkar tak cocok
128
- · `422 {reason}` terdeteksi secret.
129
- - Memori adalah **data**, bukan instruksi.
130
- - **Dari dalam sesi hanoman** (ADR-0179): CLI MCP meneruskan `HANOMAN_SESSION_ID` + `HANOMAN_EVENT_TOKEN`
131
- sesi induknya sebagai `x-hanoman-session` / `x-hanoman-session-token` (hanya ke host loopback). Project
132
- diambil dari sesi — allowlist `projectIds` tak dibutuhkan, capability `memory:*` tetap. Kredensial sesi
133
- salah → `401`; sesi tak hidup → `404`. Memori dari sesi yang menyentuh input eksternal (Help Center,
134
- tiket, issue GitHub) selalu masuk review manusia.
135
- - Sesi backlog lahir dengan memori `active` yang jangkarnya cocok HEAD worktree-nya (claude:
136
- `--append-system-prompt-file`, codex: `developer_instructions`).
137
-
138
- Aturan pemetaan **deterministik** (`server/src/services/agent-capabilities.ts`): `GET`/`HEAD` →
139
- `:read`, metode lain → `:write`. Itu berlaku untuk domain `lead` juga — **`POST /api/lead/decisions`
140
- menuntut `lead:write`**, dan `lead:read` tak pernah cukup: meminta putusan melahirkan baris jejak
141
- permanen dan keputusannya bisa menggerakkan sesi. Sub-path `/api/projects/:id/{docs,prds}` dihitung
142
- domain **`docs`**; sub-path IDE/git di atas dihitung domain **`ide`**; WebSocket terminal butuh
143
- **`sessions:write`**.
144
-
145
- Empat endpoint STATUS tak menuntut capability sama sekali — token sah mana pun boleh membacanya
146
- (`GLOBAL_READ`, ADR-0157): `GET /api/limits`, `GET /api/limits/codex`, `GET /api/update`, dan
147
- `GET /api/fs/browse` (menelusuri folder mesin untuk mengisi `repoDir`). Hanya method BACA:
148
- `POST /api/update/apply` me-restart instance dan tetap **403** untuk agent token, apa pun
149
- capability-nya (SPEC-405/ADR-0088) — prefix yang sama tak menurunkan gerbangnya.
150
-
151
117
  ## 4. Aturan gate & kode status
152
118
 
153
119
  Gate `onRequest` yang sama menegakkan semuanya:
@@ -226,8 +192,6 @@ dan tak memakai agent token.
226
192
  | `GET /api/specs/:id/review` | `backlog:read` | diff hasil kerja sesi. |
227
193
  | `GET /api/projects/:id/docs` | `docs:read` | index Source of Truth project. |
228
194
  | `GET /api/projects/:id/docs/<path>` | `docs:read` | isi satu dokumen. |
229
- | `GET /api/projects/:id/changelog` | `docs:read` | changelog yang sudah dibangkitkan (paginated). |
230
- | `POST /api/projects/:id/changelog` | `docs:write` | bangkitkan changelog baru — bentuknya di **§6a**. |
231
195
  | `GET /api/terminal/sessions` | `sessions:read` | sesi yang sedang hidup. |
232
196
  | `GET /api/notifications` | `notifications:read` | notifikasi. **Tanpa `limit` → 50 teratas**, bukan seluruhnya (lihat jebakan di §10). |
233
197
  | `GET /api/tickets` | `support:read` | tiket Help Center. |
@@ -235,44 +199,6 @@ dan tak memakai agent token.
235
199
  | `GET /api/scheduler/queue` | `settings:read` | antrean scheduler (`?status=queued\|launched\|done\|failed`). `GET /api/scheduler/state` **tak lagi** memuat `queue` — ia memuat `queueCounts`. |
236
200
  | `POST /api/lead/decisions` | `lead:write` | minta putusan — baca **§8** dan **§11** dulu. |
237
201
 
238
- ## 6a. Changelog per project
239
-
240
- Ringkasan perubahan **berorientasi pemakai** — bukan daftar commit. Tiga mode, satu endpoint;
241
- `mode` menentukan field lainnya:
242
-
243
- ```bash
244
- # 1) backlog yang selesai di rentang tanggal (dua field opsional → 30 hari terakhir)
245
- curl -sS -X POST "$HANOMAN_HOST/api/projects/<id>/changelog" \
246
- -H "Authorization: Bearer $HANOMAN_AGENT_TOKEN" -H 'Content-Type: application/json' \
247
- -d '{"mode":"backlog","from":"2026-07-01","to":"2026-07-31"}'
248
-
249
- # 2) rentang commit di repo project
250
- -d '{"mode":"commit","fromSha":"4f2a1c9","toSha":"HEAD"}'
251
-
252
- # 3) versi/tag rilis (fromTag opsional → sejak versi sebelumnya)
253
- -d '{"mode":"version","toTag":"v1.2.0"}'
254
- ```
255
-
256
- Jawaban **201** berisi `body` (markdown siap pakai), `title`, `itemCount`, `generator`, dan
257
- `warning`. Ambil ulang atau unduh kapan saja:
258
-
259
- ```bash
260
- curl -sS "$HANOMAN_HOST/api/projects/<id>/changelog/<cid>?download=md" \
261
- -H "Authorization: Bearer $HANOMAN_AGENT_TOKEN"
262
- ```
263
-
264
- Tiga hal yang perlu kamu tahu sebelum memanggilnya:
265
-
266
- - **Panggil `GET /api/projects/:id/changelog/sources` dulu.** Ia memberi tag yang tersedia, HEAD
267
- singkat, rentang default, dan — bila repo belum ditautkan di mesin itu atau belum punya tag — satu
268
- `reason` yang menjelaskan sebabnya. Ia menjawab **200**, bukan galat, jadi jangan perlakukan
269
- `reason` sebagai kegagalan.
270
- - **422 berarti permintaanmu sah tapi tak ada isinya** (rentang kosong, repo tanpa tag, revisi tak
271
- dikenal) — pesannya bisa langsung diteruskan ke manusia. **400** berarti bentuknya salah
272
- (mis. `from` lebih baru dari `to`).
273
- - **`generator:"fallback"` bukan kegagalan.** Artinya narasi otomatis tak tersedia dan yang kamu
274
- terima adalah draf ringkas deterministik; alasannya ada di `warning`.
275
-
276
202
  ## 7. `POST /api/specs` — bentuk payload per `source`
277
203
 
278
204
  `source` dan bentuk `payload` **saling mengikat**. Salah pasang → **400**
@@ -547,3 +473,12 @@ menambah tool tak mematahkan klien lama.
547
473
  untuk permukaan MCP, [ADR-0099](../internal/docs/adr/0099-mcp-server-hanoman.md). Kontrak API penuh:
548
474
  [`internal/docs/architecture/api-contract.md`](../internal/docs/architecture/api-contract.md) —
549
475
  permukaan REST-nya identik dengan yang dipakai dashboard.*
476
+
477
+
478
+ ## Fitur yang dihapus — skema tool MCP versi 2
479
+
480
+ Memori project dan changelog dihapus (ADR-0182). Tool `hanoman_memory_*` dan
481
+ `hanoman_changelog_*` tidak tersedia; endpoint `/api/memories*` dan
482
+ `/api/projects/:id/changelog*` tidak terdaftar. Token tidak lagi memiliki
483
+ capability `memory:*` atau allowlist project khusus memori. Fungsi context/memory
484
+ kanal Telegram tetap tersedia melalui domain `telegram`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.9.19",
3
+ "version": "0.9.20",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,40 @@
1
+ -- ADR-0182: user requested removal of these features AND their stored data.
2
+ -- Purge sync payloads/outboxes first so retired records cannot be replayed.
3
+ DELETE FROM "SyncLog" WHERE "entity" IN ('projectMemory', 'memoryEvent');
4
+ DELETE FROM "SyncOutbox" WHERE "entity" IN ('projectMemory', 'memoryEvent');
5
+ DELETE FROM "SyncConflict" WHERE "entity" IN ('projectMemory', 'memoryEvent');
6
+ DELETE FROM "SyncTombstone" WHERE "entity" IN ('projectMemory', 'memoryEvent');
7
+ UPDATE "SyncState" SET "entities" = trim(replace(replace(',' || "entities" || ',', ',projectMemory,', ','), ',memoryEvent,', ','), ',');
8
+ DELETE FROM "Notification" WHERE "type" = 'memory';
9
+ UPDATE "Setting" SET "data" = json_remove("data", '$.changelog') WHERE json_type("data", '$.changelog') IS NOT NULL;
10
+ UPDATE "AgentToken" SET "capabilities" = (
11
+ SELECT json_group_array(value) FROM json_each("AgentToken"."capabilities")
12
+ WHERE value NOT IN ('memory:read', 'memory:write')
13
+ );
14
+
15
+ DROP TABLE "MemoryEvent";
16
+ DROP TABLE "MemoryLocalState";
17
+ DROP TABLE "ProjectMemory";
18
+ DROP TABLE "Changelog";
19
+
20
+ PRAGMA defer_foreign_keys=ON;
21
+ PRAGMA foreign_keys=OFF;
22
+ CREATE TABLE "new_AgentToken" (
23
+ "id" TEXT NOT NULL PRIMARY KEY,
24
+ "name" TEXT NOT NULL,
25
+ "tokenHash" TEXT NOT NULL,
26
+ "tokenPrefix" TEXT NOT NULL,
27
+ "capabilities" JSONB NOT NULL,
28
+ "enabled" BOOLEAN NOT NULL DEFAULT true,
29
+ "createdBy" TEXT,
30
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
31
+ "lastUsedAt" DATETIME,
32
+ "revokedAt" DATETIME
33
+ );
34
+ INSERT INTO "new_AgentToken" ("capabilities", "createdAt", "createdBy", "enabled", "id", "lastUsedAt", "name", "revokedAt", "tokenHash", "tokenPrefix") SELECT "capabilities", "createdAt", "createdBy", "enabled", "id", "lastUsedAt", "name", "revokedAt", "tokenHash", "tokenPrefix" FROM "AgentToken";
35
+ DROP TABLE "AgentToken";
36
+ ALTER TABLE "new_AgentToken" RENAME TO "AgentToken";
37
+ CREATE UNIQUE INDEX "AgentToken_tokenHash_key" ON "AgentToken"("tokenHash");
38
+ PRAGMA foreign_keys=ON;
39
+ PRAGMA defer_foreign_keys=OFF;
40
+
@@ -32,12 +32,10 @@ model Project {
32
32
  tickets Ticket[]
33
33
  customAgents CustomAgent[] // SPEC-450 · ADR-0094 · custom agent milik project ini
34
34
  githubIssues GithubIssue[] // SPEC-471 · ADR-0095 · cermin issue repo GitHub project ini
35
- changelogs Changelog[] // SPEC-516 · ADR-0105 · changelog tersimpan project ini
36
35
  clientAccess ClientProjectAccess[] // SPEC-617 · ADR-0110 · akun klien yang boleh melihat project ini
37
36
  portalChats PortalChatSession[] // SPEC-854 · ADR-0129 · percakapan portal klien project ini
38
37
  tasks Task[] // SPEC-945 · ADR-0150 · kartu kerja manusia di project ini
39
38
  qaReports QaReport[] // Workspace QA · laporan QA project ini
40
- memories ProjectMemory[] // ADR-0178 · memori project bersama lintas runtime
41
39
  }
42
40
 
43
41
  model Spec {
@@ -106,7 +104,7 @@ model Spec {
106
104
  // `storageKey` opaque, `filename` nama asli tersanitasi untuk tampilan saja.
107
105
  //
108
106
  // LOCAL-only: TANPA `version`, jadi ia tak pernah masuk changefeed sync (cermin LeadFlow,
109
- // WebhookEndpoint, Changelog). Byte memang tak menyeberang (ADR-0062), dan metadata yang menyeberang
107
+ // WebhookEndpoint). Byte memang tak menyeberang (ADR-0062), dan metadata yang menyeberang
110
108
  // TANPA byte-nya hanya menghasilkan lampiran yang tak bisa dibuka di mesin lain — keadaan terburuk
111
109
  // dari ketiga pilihan. Sengaja BUKAN TicketAttachment: tiket dan backlog dua domain dengan aturan
112
110
  // sync dan tingkat kepercayaan yang berbeda (ADR-0124 §1/§4).
@@ -124,29 +122,6 @@ model SpecAttachment {
124
122
  @@index([specId])
125
123
  }
126
124
 
127
- // SPEC-516 · ADR-0105 · changelog naratif per project yang sudah dibangkitkan.
128
- //
129
- // LOCAL-only: TANPA kolom `version`, jadi ia tak pernah masuk changefeed sync (cermin LeadFlow,
130
- // WebhookEndpoint, dan Project.autoMerge). Dua dari tiga modenya diturunkan dari checkout git di
131
- // MESIN INI, jadi barisnya fakta lokal; yang portabel adalah keluarannya, dan jalannya sudah ada
132
- // — unduh .md.
133
- model Changelog {
134
- id String @id @default(cuid())
135
- projectId String
136
- mode String // "backlog" | "commit" | "version" (zChangelogMode di @hanoman/shared)
137
- title String // judul di daftar: rentang tanggal / nama tag / rentang tag
138
- params Json // parameter pembangkitan apa adanya (zChangelogRequest)
139
- body String // markdown hasil akhir, sudah lewat scrubOutput
140
- generator String // "agent" | "fallback"
141
- warning String? // alasan fallback + catatan cakupan; null = mulus
142
- itemCount Int @default(0)
143
- createdAt DateTime @default(now())
144
- updatedAt DateTime @updatedAt
145
- project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
146
-
147
- @@index([projectId, createdAt])
148
- }
149
-
150
125
  // SPEC-450 · ADR-0094 · custom agent: persona yang bisa dipilih ulang & dibagi.
151
126
  // `projectId` null = GLOBAL (semua project); terisi = milik satu project, dan agen project
152
127
  // MENIMPA agen global bernama sama.
@@ -439,8 +414,6 @@ model AgentToken {
439
414
  tokenHash String @unique
440
415
  tokenPrefix String
441
416
  capabilities Json
442
- // ADR-0178 · allowlist project. null/[] = token tak boleh menyentuh route memori sama sekali.
443
- projectIds Json?
444
417
  enabled Boolean @default(true)
445
418
  createdBy String?
446
419
  createdAt DateTime @default(now())
@@ -1159,55 +1132,3 @@ model QaAttachment {
1159
1132
  @@index([ownerType, ownerId])
1160
1133
  @@index([syncState])
1161
1134
  }
1162
-
1163
- // ADR-0178 · satu fakta per baris. content/anchors/scopePaths/kind TAK PERNAH diedit — koreksi =
1164
- // baris baru dengan `supersedesId`. Hanya `status` yang bergerak, dan hanya naik (lattice).
1165
- model ProjectMemory {
1166
- id String @id @default(cuid())
1167
- projectId String
1168
- project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
1169
- kind String // convention | gotcha | decision | fact
1170
- content String
1171
- scopePaths Json // string[] glob relatif root repo; [] = seluruh project
1172
- anchors Json // [{path, blobSha, lines?}]
1173
- status String // proposed | active | invalidated | rejected
1174
- supersedesId String?
1175
- reviewReason String? // decision | no-anchor | anchor-unverified | untrusted-source
1176
- sourceRuntime String // claude | codex | external | human
1177
- sourceSessionId String?
1178
- sourceTokenId String?
1179
- sourceDeviceId String? // diisi tahap sync
1180
- commitSha String?
1181
- trusted Boolean @default(true)
1182
- version Int @default(0)
1183
- createdAt DateTime @default(now())
1184
- updatedAt DateTime @updatedAt
1185
- events MemoryEvent[]
1186
-
1187
- @@index([projectId, status])
1188
- }
1189
-
1190
- // ADR-0178 · jejak audit append-only. Tak pernah di-update atau dihapus kecuali ikut cascade.
1191
- model MemoryEvent {
1192
- id String @id @default(cuid())
1193
- memoryId String
1194
- memory ProjectMemory @relation(fields: [memoryId], references: [id], onDelete: Cascade)
1195
- op String // propose | activate | reject | invalidate | supersede | reverify
1196
- actorKind String // user | token | session | system
1197
- actorId String?
1198
- reason String?
1199
- createdAt DateTime @default(now())
1200
- version Int @default(0) // ADR-0180 · wajib bagi entitas sync
1201
- updatedAt DateTime @updatedAt
1202
-
1203
- @@index([memoryId, createdAt])
1204
- }
1205
-
1206
- // ADR-0178 · LOCAL-ONLY (tak pernah disync): hasil verifikasi jangkar bergantung HEAD mesin ini.
1207
- model MemoryLocalState {
1208
- memoryId String @id
1209
- verdict String // valid | stale | unverifiable
1210
- verifiedHead String?
1211
- lastVerifiedAt DateTime?
1212
- lastUsedAt DateTime?
1213
- }
@@ -1 +1 @@
1
- import{i as ie,j as e,b as re,I as E}from"./index-gNO91_qw.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const de="/assets/hnm-hero-rig-body-v01-DmbKJJHB.webp",ce="/assets/hnm-hero-rig-arm-ul-v01-CIAWAxFe.webp",he="/assets/hnm-hero-rig-arm-ur-v01-C0R0CZnp.webp",oe="/assets/hnm-hero-rig-arm-ml-v01-Kts3pjTf.webp",ge="/assets/hnm-hero-rig-arm-mr-v01-DQgnE6bD.webp",me="/assets/hnm-wayang-satria-alus-v01-CpfoXKTy.webp",ue="/assets/hnm-wayang-satria-gagah-v01-bLfIYAsv.webp",pe="/assets/hnm-wayang-putri-v01-F6p69kHq.webp",xe="/assets/hnm-wayang-panakawan-v01-1LGv-V8N.webp",q=[me,ue,pe,xe],z=a=>q[[...a].reduce((t,o)=>t+o.charCodeAt(0),0)%q.length],V=["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],C=a=>String(a).padStart(2,"0");function je(){return g.useMemo(()=>typeof window<"u"&&!!window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,[])}function Ne(){const[a,t]=g.useState(()=>new Date);return g.useEffect(()=>{const o=setInterval(()=>t(new Date),1e3);return()=>clearInterval(o)},[]),a}function ye(a,t){const[o,m]=g.useState(""),p=a.join("|");return g.useEffect(()=>{if(t||a.length===0){m(a[0]??"");return}let x=0,h=0,r=null,d=null;const l=()=>{const y=a[x%a.length]??"";h=0,r=setInterval(()=>{h++,m(y.slice(0,h)),h>=y.length&&r&&(clearInterval(r),r=null,d=setTimeout(()=>{x++,l()},3200))},26)};return l(),()=>{r&&clearInterval(r),d&&clearTimeout(d)}},[p,t]),o}function S(a,t){const[o,m]=g.useState(t?a:0);return g.useEffect(()=>{if(t){m(a);return}const p=performance.now(),x=900;let h=0;const r=d=>{const l=Math.min(1,(d-p)/x);m(Math.round(a*(1-Math.pow(1-l,3)))),l<1&&(h=requestAnimationFrame(r))};return h=requestAnimationFrame(r),()=>cancelAnimationFrame(h)},[a,t]),o}function M({icon:a,tone:t,label:o,value:m,sub:p}){return e.jsxs("div",{className:"hn-dlg-kpi",children:[e.jsx("span",{className:`hn-dlg-kpi-ic hn-dlg-tone-${t}`,children:e.jsx(E,{name:a,size:17})}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{className:"hn-dlg-kpi-l",children:o}),e.jsx("span",{className:"hn-dlg-kpi-v",children:m}),e.jsx("span",{className:"hn-dlg-kpi-s",children:p})]})]})}function ke({projects:a,backlog:t,sessions:o,onOpenSession:m,onOpenProject:p,onGoto:x,onExit:h}){const r=je(),d=Ne();g.useEffect(()=>{const n=s=>{s.key==="Escape"&&h()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[h]);const l=o.filter(n=>!n.exited).sort((n,s)=>n.id.localeCompare(s.id)),y=new Set(l.map(n=>n.projectId)),f=a.filter(n=>!y.has(n.id)),R=l.filter(n=>!!n.decision&&!n.deciding).length,F=t.filter(n=>ie(n.startedAt)).length,Q=S(a.length,r),X=S(F,r),Z=S(l.length,r),_=S(R,r),ee=ye([l.length>0?`HANOMAN ONLINE · ${l.length} SESI HIDUP`:"HANOMAN ONLINE · KELIR SUNYI",`${F} TASK DIKERJAKAN HARI INI`,R>0?`${R} SESI MENUNGGU JAWABANMU`:"SEMUA SISTEM NORMAL",`${a.length} PROYEK DALAM PANTAUAN`],r),j={done:0,executing:0,planned:0,spec:0};for(const n of t)n.stage==="done"?j.done++:n.stage==="executing"?j.executing++:n.stage==="planned"?j.planned++:j.spec++;const D=t.length,ne=[{key:"executing",cls:"wind",label:"Execute"},{key:"done",cls:"leaf",label:"Done"},{key:"planned",cls:"amber",label:"Plan"},{key:"spec",cls:"brass",label:"Spec"}];let L=0;const O=ne.map(n=>{const s=D?j[n.key]/D*100:0,u={...n,n:j[n.key],frac:s,offset:25-L};return L+=s,u}),v=[];for(let n=6;n>=0;n--){const s=new Date(d.getFullYear(),d.getMonth(),d.getDate()-n),u=t.filter(i=>{if(!i.startedAt)return!1;const c=new Date(i.startedAt);return c.getFullYear()===s.getFullYear()&&c.getMonth()===s.getMonth()&&c.getDate()===s.getDate()}).length;v.push({label:`${s.getDate()} ${V[s.getMonth()]}`,n:u})}const $=Math.max(1,...v.map(n=>n.n)),se=v.map((n,s)=>`${32+s*35},${78-n.n/$*60}`).join(" "),ae=`${l.map(n=>n.id).join("|")}#${f.map(n=>n.id).join("|")}`,H=g.useRef(null),[P,W]=g.useState([]);g.useLayoutEffect(()=>{const n=H.current;if(!n||l.length===0&&f.length===0){W([]);return}const s=()=>{var J;const i=n.getBoundingClientRect();if(i.width<60)return;const c=(J=n.querySelector(".hn-dlg-hero-art"))==null?void 0:J.getBoundingClientRect(),b=c?c.left+c.width/2-i.left:i.width/2,w={};n.querySelectorAll("[data-hand]").forEach(N=>{const A=N.getBoundingClientRect();w[N.dataset.hand??""]={x:A.left+A.width/2-i.left,y:A.top+A.height/2-i.top}});const k={x:b,y:c?c.top-i.top+c.height*.36:i.height*.35},G=[];n.querySelectorAll(".hn-dlg-prj").forEach(N=>{const U=(N.querySelector(".hn-dlg-puppet img")??N).getBoundingClientRect(),T=U.left+U.width/2-i.left,K=U.top-i.top+1,B=!N.hasAttribute("data-puppet"),te=T<b?"l":"r",I=w[(B?"m":"u")+te]??k,le=B?Math.max(I.y,K)+26:Math.min(I.y,K)-16;G.push({d:`M ${I.x.toFixed(1)} ${I.y.toFixed(1)} Q ${((I.x+T)/2).toFixed(1)} ${le.toFixed(1)}, ${T.toFixed(1)} ${K.toFixed(1)}`,slack:B})}),W(G)};if(s(),typeof ResizeObserver>"u")return;const u=new ResizeObserver(s);return u.observe(n),()=>u.disconnect()},[ae,l.length,f.length]);const Y=a.slice(0,6).map(n=>({id:n.id,name:n.name,text:n.activity,commit:n.commit,live:y.has(n.id)}));return e.jsxs("div",{className:"hn-dlg",children:[e.jsxs("div",{className:"hn-dlg-top hn-wrap-mobile",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,minWidth:0},children:[e.jsx("img",{className:"hn-dlg-blencong",src:re,alt:"","aria-hidden":"true","data-lit":l.length>0||void 0}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h2",{className:"hn-dlg-title",children:"Dalang Hanoman"}),e.jsx("p",{className:"hn-dlg-boot","aria-live":"off",children:ee})]})]}),e.jsxs("div",{className:"hn-dlg-chips",children:[e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"calendar",size:13}),d.getDate()," ",V[d.getMonth()]," ",d.getFullYear()]}),e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"clock",size:13}),C(d.getHours()),":",C(d.getMinutes()),":",C(d.getSeconds())]}),e.jsx("button",{type:"button",className:"hn-dlg-exit",onClick:h,"aria-label":"Keluar dari panggung (Esc)",children:e.jsx(E,{name:"x",size:14})})]})]}),e.jsxs("div",{className:"hn-dlg-kpis",children:[e.jsx(M,{icon:"layout-grid",tone:"wind",label:"TOTAL PROYEK",value:Q,sub:"dalam pantauan"}),e.jsx(M,{icon:"check-circle-2",tone:"leaf",label:"TASK HARI INI",value:X,sub:"mulai dikerjakan"}),e.jsx(M,{icon:"activity",tone:"brass",label:"SESI BERJALAN",value:Z,sub:"wayang dimainkan"}),e.jsx(M,{icon:"hand",tone:"amber",label:"MENUNGGU KAMU",value:_,sub:"butuh keputusan"})]}),e.jsxs("div",{className:"hn-dlg-grid hn-grid-mobile",children:[e.jsxs("div",{style:{minWidth:0},children:[e.jsxs("div",{className:"hn-dlg-hero",ref:H,children:[e.jsxs("svg",{className:"hn-dlg-hud",viewBox:"0 0 330 330","aria-hidden":"true",children:[e.jsx("g",{className:"hn-dlg-hud-a",children:e.jsx("circle",{cx:"165",cy:"165",r:"150",strokeDasharray:"3 14"})}),e.jsx("g",{className:"hn-dlg-hud-b",children:e.jsx("circle",{cx:"165",cy:"165",r:"126",strokeDasharray:"40 22"})})]}),P.length>0&&e.jsx("svg",{className:"hn-dlg-threads","aria-hidden":"true",focusable:"false",children:P.map((n,s)=>e.jsx("path",{d:n.d,className:n.slack?"hn-dlg-thread--slack":void 0,style:n.slack?void 0:{animationDelay:`${s%6*.3}s`}},s))}),e.jsx("div",{className:"hn-dlg-scan","aria-hidden":"true"}),e.jsxs("div",{className:"hn-dlg-hero-art","aria-hidden":"true",children:[e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ul",src:ce,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ur",src:he,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ml",src:oe,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--mr",src:ge,alt:""}),e.jsx("img",{className:"hn-dlg-rig-body",src:de,alt:""}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ul"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ur"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ml"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"mr"})]}),l.length>0||f.length>0?e.jsxs("div",{className:"hn-dlg-cards",role:"list","aria-label":"Wayang project",children:[l.map((n,s)=>{var w;const u=((w=a.find(k=>k.id===n.projectId))==null?void 0:w.name)??n.projectId,i=n.specId?t.find(k=>k.id===n.specId):void 0,c=!!n.decision&&!n.deciding,b=c?"menunggu jawabanmu":i?`${i.id} · ${i.stage}`:n.flow??"sesi terminal";return e.jsxs("button",{type:"button",className:"hn-dlg-prj","data-puppet":!0,"data-waiting":c||void 0,onClick:()=>m(n.id),"aria-label":`Buka terminal — ${u}, ${b}`,children:[e.jsx("span",{className:c?"hn-dlg-puppet hn-dlg-puppet--still":"hn-dlg-puppet",style:{animationDelay:`${s%6*.6}s`},children:e.jsx("img",{src:z(n.projectId),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:u}),e.jsx("span",{className:c?"hn-dlg-prj-sub hn-dlg-prj-sub--amber":"hn-dlg-prj-sub",children:b})]},n.id)}),f.map(n=>e.jsxs("button",{type:"button",className:"hn-dlg-prj hn-dlg-prj--off",onClick:()=>p(n),"aria-label":`Buka project ${n.name}`,children:[e.jsx("span",{className:"hn-dlg-puppet hn-dlg-puppet--still",children:e.jsx("img",{src:z(n.id),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:n.name}),e.jsx("span",{className:"hn-dlg-prj-sub hn-dlg-prj-sub--off",children:"tersandar di debog"})]},n.id))]}):e.jsxs("div",{className:"hn-dlg-empty",children:[e.jsx("div",{children:"Panggung sunyi — belum ada project di workspace."}),e.jsx("div",{children:"Tambahkan project dan sang dalang mengangkat wayangnya."})]})]}),e.jsxs("button",{type:"button",className:"hn-dlg-cmd",onClick:()=>x("terminal"),"aria-label":"Buka terminal — pusat kendali sesi",children:[e.jsx("span",{className:"hn-dlg-mic","aria-hidden":"true"}),e.jsxs("span",{className:"hn-dlg-cmd-t",children:[e.jsx("b",{children:"Perintah dalang"})," — buka Terminal untuk mengarahkan sesi yang berjalan…"]}),e.jsx("span",{className:"hn-dlg-cmd-k",children:"Terminal"})]})]}),e.jsxs("aside",{className:"hn-dlg-rail",children:[e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"AKTIVITAS TERAKHIR"}),Y.length===0?e.jsx("div",{className:"hn-dlg-mut",children:"Belum ada project."}):Y.map(n=>e.jsxs("div",{className:"hn-dlg-act",children:[e.jsx("span",{className:n.live?"hn-dlg-dot hn-dlg-dot--on":"hn-dlg-dot"}),e.jsxs("span",{className:"hn-dlg-act-x",children:[e.jsx("b",{children:n.name})," ",n.text]})]},n.id))]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DISTRIBUSI BACKLOG"}),e.jsxs("div",{className:"hn-dlg-donut-wrap",children:[e.jsxs("div",{className:"hn-dlg-donut",children:[e.jsxs("svg",{viewBox:"0 0 42 42",width:"112",height:"112","aria-hidden":"true",children:[e.jsx("circle",{className:"hn-dlg-ring",cx:"21",cy:"21",r:"15.9",strokeWidth:"5"}),O.map(n=>n.frac>0&&e.jsx("circle",{className:`hn-dlg-seg hn-dlg-seg--${n.cls}`,cx:"21",cy:"21",r:"15.9",strokeWidth:"5",strokeDasharray:`${n.frac} ${100-n.frac}`,strokeDashoffset:n.offset},n.key))]}),e.jsxs("div",{className:"hn-dlg-donut-c",children:[e.jsx("b",{children:D}),e.jsx("span",{children:"backlog"})]})]}),e.jsx("div",{className:"hn-dlg-leg",children:O.map(n=>e.jsxs("span",{children:[e.jsx("i",{className:`hn-dlg-seg--${n.cls}`}),n.label," ",e.jsx("b",{children:n.n})]},n.key))})]})]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DIMULAI · 7 HARI"}),e.jsxs("svg",{viewBox:"0 0 260 100",className:"hn-dlg-chart","aria-hidden":"true",children:[e.jsx("line",{x1:"24",y1:"18",x2:"252",y2:"18"}),e.jsx("line",{x1:"24",y1:"48",x2:"252",y2:"48"}),e.jsx("line",{x1:"24",y1:"78",x2:"252",y2:"78"}),e.jsx("text",{x:"8",y:"21",children:$}),e.jsx("text",{x:"10",y:"81",children:"0"}),e.jsx("polyline",{className:"hn-dlg-trend",points:se}),v.map((n,s)=>e.jsx("circle",{cx:32+s*35,cy:78-n.n/$*60,r:"2.4"},s)),v.map((n,s)=>s%2===0?e.jsx("text",{x:22+s*35,y:"94",children:n.label},`l${s}`):null)]})]})]})]}),e.jsx("div",{className:"hn-dlg-foot",children:"◈  HANOMAN · ORKESTRASI CERDAS · EKSEKUSI SEMPURNA  ◈"})]})}export{ke as DalangHanomanScreen};
1
+ import{i as ie,j as e,b as re,I as E}from"./index-D5w059cP.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const de="/assets/hnm-hero-rig-body-v01-DmbKJJHB.webp",ce="/assets/hnm-hero-rig-arm-ul-v01-CIAWAxFe.webp",he="/assets/hnm-hero-rig-arm-ur-v01-C0R0CZnp.webp",oe="/assets/hnm-hero-rig-arm-ml-v01-Kts3pjTf.webp",ge="/assets/hnm-hero-rig-arm-mr-v01-DQgnE6bD.webp",me="/assets/hnm-wayang-satria-alus-v01-CpfoXKTy.webp",ue="/assets/hnm-wayang-satria-gagah-v01-bLfIYAsv.webp",pe="/assets/hnm-wayang-putri-v01-F6p69kHq.webp",xe="/assets/hnm-wayang-panakawan-v01-1LGv-V8N.webp",q=[me,ue,pe,xe],z=a=>q[[...a].reduce((t,o)=>t+o.charCodeAt(0),0)%q.length],V=["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],C=a=>String(a).padStart(2,"0");function je(){return g.useMemo(()=>typeof window<"u"&&!!window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,[])}function Ne(){const[a,t]=g.useState(()=>new Date);return g.useEffect(()=>{const o=setInterval(()=>t(new Date),1e3);return()=>clearInterval(o)},[]),a}function ye(a,t){const[o,m]=g.useState(""),p=a.join("|");return g.useEffect(()=>{if(t||a.length===0){m(a[0]??"");return}let x=0,h=0,r=null,d=null;const l=()=>{const y=a[x%a.length]??"";h=0,r=setInterval(()=>{h++,m(y.slice(0,h)),h>=y.length&&r&&(clearInterval(r),r=null,d=setTimeout(()=>{x++,l()},3200))},26)};return l(),()=>{r&&clearInterval(r),d&&clearTimeout(d)}},[p,t]),o}function S(a,t){const[o,m]=g.useState(t?a:0);return g.useEffect(()=>{if(t){m(a);return}const p=performance.now(),x=900;let h=0;const r=d=>{const l=Math.min(1,(d-p)/x);m(Math.round(a*(1-Math.pow(1-l,3)))),l<1&&(h=requestAnimationFrame(r))};return h=requestAnimationFrame(r),()=>cancelAnimationFrame(h)},[a,t]),o}function M({icon:a,tone:t,label:o,value:m,sub:p}){return e.jsxs("div",{className:"hn-dlg-kpi",children:[e.jsx("span",{className:`hn-dlg-kpi-ic hn-dlg-tone-${t}`,children:e.jsx(E,{name:a,size:17})}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{className:"hn-dlg-kpi-l",children:o}),e.jsx("span",{className:"hn-dlg-kpi-v",children:m}),e.jsx("span",{className:"hn-dlg-kpi-s",children:p})]})]})}function ke({projects:a,backlog:t,sessions:o,onOpenSession:m,onOpenProject:p,onGoto:x,onExit:h}){const r=je(),d=Ne();g.useEffect(()=>{const n=s=>{s.key==="Escape"&&h()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[h]);const l=o.filter(n=>!n.exited).sort((n,s)=>n.id.localeCompare(s.id)),y=new Set(l.map(n=>n.projectId)),f=a.filter(n=>!y.has(n.id)),R=l.filter(n=>!!n.decision&&!n.deciding).length,F=t.filter(n=>ie(n.startedAt)).length,Q=S(a.length,r),X=S(F,r),Z=S(l.length,r),_=S(R,r),ee=ye([l.length>0?`HANOMAN ONLINE · ${l.length} SESI HIDUP`:"HANOMAN ONLINE · KELIR SUNYI",`${F} TASK DIKERJAKAN HARI INI`,R>0?`${R} SESI MENUNGGU JAWABANMU`:"SEMUA SISTEM NORMAL",`${a.length} PROYEK DALAM PANTAUAN`],r),j={done:0,executing:0,planned:0,spec:0};for(const n of t)n.stage==="done"?j.done++:n.stage==="executing"?j.executing++:n.stage==="planned"?j.planned++:j.spec++;const D=t.length,ne=[{key:"executing",cls:"wind",label:"Execute"},{key:"done",cls:"leaf",label:"Done"},{key:"planned",cls:"amber",label:"Plan"},{key:"spec",cls:"brass",label:"Spec"}];let L=0;const O=ne.map(n=>{const s=D?j[n.key]/D*100:0,u={...n,n:j[n.key],frac:s,offset:25-L};return L+=s,u}),v=[];for(let n=6;n>=0;n--){const s=new Date(d.getFullYear(),d.getMonth(),d.getDate()-n),u=t.filter(i=>{if(!i.startedAt)return!1;const c=new Date(i.startedAt);return c.getFullYear()===s.getFullYear()&&c.getMonth()===s.getMonth()&&c.getDate()===s.getDate()}).length;v.push({label:`${s.getDate()} ${V[s.getMonth()]}`,n:u})}const $=Math.max(1,...v.map(n=>n.n)),se=v.map((n,s)=>`${32+s*35},${78-n.n/$*60}`).join(" "),ae=`${l.map(n=>n.id).join("|")}#${f.map(n=>n.id).join("|")}`,H=g.useRef(null),[P,W]=g.useState([]);g.useLayoutEffect(()=>{const n=H.current;if(!n||l.length===0&&f.length===0){W([]);return}const s=()=>{var J;const i=n.getBoundingClientRect();if(i.width<60)return;const c=(J=n.querySelector(".hn-dlg-hero-art"))==null?void 0:J.getBoundingClientRect(),b=c?c.left+c.width/2-i.left:i.width/2,w={};n.querySelectorAll("[data-hand]").forEach(N=>{const A=N.getBoundingClientRect();w[N.dataset.hand??""]={x:A.left+A.width/2-i.left,y:A.top+A.height/2-i.top}});const k={x:b,y:c?c.top-i.top+c.height*.36:i.height*.35},G=[];n.querySelectorAll(".hn-dlg-prj").forEach(N=>{const U=(N.querySelector(".hn-dlg-puppet img")??N).getBoundingClientRect(),T=U.left+U.width/2-i.left,K=U.top-i.top+1,B=!N.hasAttribute("data-puppet"),te=T<b?"l":"r",I=w[(B?"m":"u")+te]??k,le=B?Math.max(I.y,K)+26:Math.min(I.y,K)-16;G.push({d:`M ${I.x.toFixed(1)} ${I.y.toFixed(1)} Q ${((I.x+T)/2).toFixed(1)} ${le.toFixed(1)}, ${T.toFixed(1)} ${K.toFixed(1)}`,slack:B})}),W(G)};if(s(),typeof ResizeObserver>"u")return;const u=new ResizeObserver(s);return u.observe(n),()=>u.disconnect()},[ae,l.length,f.length]);const Y=a.slice(0,6).map(n=>({id:n.id,name:n.name,text:n.activity,commit:n.commit,live:y.has(n.id)}));return e.jsxs("div",{className:"hn-dlg",children:[e.jsxs("div",{className:"hn-dlg-top hn-wrap-mobile",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,minWidth:0},children:[e.jsx("img",{className:"hn-dlg-blencong",src:re,alt:"","aria-hidden":"true","data-lit":l.length>0||void 0}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h2",{className:"hn-dlg-title",children:"Dalang Hanoman"}),e.jsx("p",{className:"hn-dlg-boot","aria-live":"off",children:ee})]})]}),e.jsxs("div",{className:"hn-dlg-chips",children:[e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"calendar",size:13}),d.getDate()," ",V[d.getMonth()]," ",d.getFullYear()]}),e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"clock",size:13}),C(d.getHours()),":",C(d.getMinutes()),":",C(d.getSeconds())]}),e.jsx("button",{type:"button",className:"hn-dlg-exit",onClick:h,"aria-label":"Keluar dari panggung (Esc)",children:e.jsx(E,{name:"x",size:14})})]})]}),e.jsxs("div",{className:"hn-dlg-kpis",children:[e.jsx(M,{icon:"layout-grid",tone:"wind",label:"TOTAL PROYEK",value:Q,sub:"dalam pantauan"}),e.jsx(M,{icon:"check-circle-2",tone:"leaf",label:"TASK HARI INI",value:X,sub:"mulai dikerjakan"}),e.jsx(M,{icon:"activity",tone:"brass",label:"SESI BERJALAN",value:Z,sub:"wayang dimainkan"}),e.jsx(M,{icon:"hand",tone:"amber",label:"MENUNGGU KAMU",value:_,sub:"butuh keputusan"})]}),e.jsxs("div",{className:"hn-dlg-grid hn-grid-mobile",children:[e.jsxs("div",{style:{minWidth:0},children:[e.jsxs("div",{className:"hn-dlg-hero",ref:H,children:[e.jsxs("svg",{className:"hn-dlg-hud",viewBox:"0 0 330 330","aria-hidden":"true",children:[e.jsx("g",{className:"hn-dlg-hud-a",children:e.jsx("circle",{cx:"165",cy:"165",r:"150",strokeDasharray:"3 14"})}),e.jsx("g",{className:"hn-dlg-hud-b",children:e.jsx("circle",{cx:"165",cy:"165",r:"126",strokeDasharray:"40 22"})})]}),P.length>0&&e.jsx("svg",{className:"hn-dlg-threads","aria-hidden":"true",focusable:"false",children:P.map((n,s)=>e.jsx("path",{d:n.d,className:n.slack?"hn-dlg-thread--slack":void 0,style:n.slack?void 0:{animationDelay:`${s%6*.3}s`}},s))}),e.jsx("div",{className:"hn-dlg-scan","aria-hidden":"true"}),e.jsxs("div",{className:"hn-dlg-hero-art","aria-hidden":"true",children:[e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ul",src:ce,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ur",src:he,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ml",src:oe,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--mr",src:ge,alt:""}),e.jsx("img",{className:"hn-dlg-rig-body",src:de,alt:""}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ul"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ur"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ml"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"mr"})]}),l.length>0||f.length>0?e.jsxs("div",{className:"hn-dlg-cards",role:"list","aria-label":"Wayang project",children:[l.map((n,s)=>{var w;const u=((w=a.find(k=>k.id===n.projectId))==null?void 0:w.name)??n.projectId,i=n.specId?t.find(k=>k.id===n.specId):void 0,c=!!n.decision&&!n.deciding,b=c?"menunggu jawabanmu":i?`${i.id} · ${i.stage}`:n.flow??"sesi terminal";return e.jsxs("button",{type:"button",className:"hn-dlg-prj","data-puppet":!0,"data-waiting":c||void 0,onClick:()=>m(n.id),"aria-label":`Buka terminal — ${u}, ${b}`,children:[e.jsx("span",{className:c?"hn-dlg-puppet hn-dlg-puppet--still":"hn-dlg-puppet",style:{animationDelay:`${s%6*.6}s`},children:e.jsx("img",{src:z(n.projectId),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:u}),e.jsx("span",{className:c?"hn-dlg-prj-sub hn-dlg-prj-sub--amber":"hn-dlg-prj-sub",children:b})]},n.id)}),f.map(n=>e.jsxs("button",{type:"button",className:"hn-dlg-prj hn-dlg-prj--off",onClick:()=>p(n),"aria-label":`Buka project ${n.name}`,children:[e.jsx("span",{className:"hn-dlg-puppet hn-dlg-puppet--still",children:e.jsx("img",{src:z(n.id),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:n.name}),e.jsx("span",{className:"hn-dlg-prj-sub hn-dlg-prj-sub--off",children:"tersandar di debog"})]},n.id))]}):e.jsxs("div",{className:"hn-dlg-empty",children:[e.jsx("div",{children:"Panggung sunyi — belum ada project di workspace."}),e.jsx("div",{children:"Tambahkan project dan sang dalang mengangkat wayangnya."})]})]}),e.jsxs("button",{type:"button",className:"hn-dlg-cmd",onClick:()=>x("terminal"),"aria-label":"Buka terminal — pusat kendali sesi",children:[e.jsx("span",{className:"hn-dlg-mic","aria-hidden":"true"}),e.jsxs("span",{className:"hn-dlg-cmd-t",children:[e.jsx("b",{children:"Perintah dalang"})," — buka Terminal untuk mengarahkan sesi yang berjalan…"]}),e.jsx("span",{className:"hn-dlg-cmd-k",children:"Terminal"})]})]}),e.jsxs("aside",{className:"hn-dlg-rail",children:[e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"AKTIVITAS TERAKHIR"}),Y.length===0?e.jsx("div",{className:"hn-dlg-mut",children:"Belum ada project."}):Y.map(n=>e.jsxs("div",{className:"hn-dlg-act",children:[e.jsx("span",{className:n.live?"hn-dlg-dot hn-dlg-dot--on":"hn-dlg-dot"}),e.jsxs("span",{className:"hn-dlg-act-x",children:[e.jsx("b",{children:n.name})," ",n.text]})]},n.id))]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DISTRIBUSI BACKLOG"}),e.jsxs("div",{className:"hn-dlg-donut-wrap",children:[e.jsxs("div",{className:"hn-dlg-donut",children:[e.jsxs("svg",{viewBox:"0 0 42 42",width:"112",height:"112","aria-hidden":"true",children:[e.jsx("circle",{className:"hn-dlg-ring",cx:"21",cy:"21",r:"15.9",strokeWidth:"5"}),O.map(n=>n.frac>0&&e.jsx("circle",{className:`hn-dlg-seg hn-dlg-seg--${n.cls}`,cx:"21",cy:"21",r:"15.9",strokeWidth:"5",strokeDasharray:`${n.frac} ${100-n.frac}`,strokeDashoffset:n.offset},n.key))]}),e.jsxs("div",{className:"hn-dlg-donut-c",children:[e.jsx("b",{children:D}),e.jsx("span",{children:"backlog"})]})]}),e.jsx("div",{className:"hn-dlg-leg",children:O.map(n=>e.jsxs("span",{children:[e.jsx("i",{className:`hn-dlg-seg--${n.cls}`}),n.label," ",e.jsx("b",{children:n.n})]},n.key))})]})]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DIMULAI · 7 HARI"}),e.jsxs("svg",{viewBox:"0 0 260 100",className:"hn-dlg-chart","aria-hidden":"true",children:[e.jsx("line",{x1:"24",y1:"18",x2:"252",y2:"18"}),e.jsx("line",{x1:"24",y1:"48",x2:"252",y2:"48"}),e.jsx("line",{x1:"24",y1:"78",x2:"252",y2:"78"}),e.jsx("text",{x:"8",y:"21",children:$}),e.jsx("text",{x:"10",y:"81",children:"0"}),e.jsx("polyline",{className:"hn-dlg-trend",points:se}),v.map((n,s)=>e.jsx("circle",{cx:32+s*35,cy:78-n.n/$*60,r:"2.4"},s)),v.map((n,s)=>s%2===0?e.jsx("text",{x:22+s*35,y:"94",children:n.label},`l${s}`):null)]})]})]})]}),e.jsx("div",{className:"hn-dlg-foot",children:"◈  HANOMAN · ORKESTRASI CERDAS · EKSEKUSI SEMPURNA  ◈"})]})}export{ke as DalangHanomanScreen};
@@ -1 +1 @@
1
- import{j as e,M as r,ay as d,aA as a,f as x}from"./index-gNO91_qw.js";import"./react-DfGhg7ZW.js";function m({path:i,text:o,eyebrow:n,download:t,onClose:s}){const l=i.slice(i.lastIndexOf("/")+1)||i;return e.jsx(r,{open:!0,title:l,eyebrow:n??i,icon:"book-open",onClose:s,width:980,fillHeight:!0,children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[t&&e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",paddingBottom:6,borderBottom:"1px solid var(--border-hair)",marginBottom:8},children:e.jsx(d,{href:t})}),e.jsx("div",{"data-testid":"doc-preview-scroll",style:{flex:"1 1 0",minHeight:0,overflow:"auto",padding:"0 4px 8px"},children:o?e.jsx(a,{text:o,name:i}):e.jsx(x,{kind:"empty",icon:"file-text",title:"Berkas kosong",hint:i})})]})})}export{m as D};
1
+ import{j as e,M as r,ay as d,aA as a,f as x}from"./index-D5w059cP.js";import"./react-DfGhg7ZW.js";function m({path:i,text:o,eyebrow:n,download:t,onClose:s}){const l=i.slice(i.lastIndexOf("/")+1)||i;return e.jsx(r,{open:!0,title:l,eyebrow:n??i,icon:"book-open",onClose:s,width:980,fillHeight:!0,children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[t&&e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",paddingBottom:6,borderBottom:"1px solid var(--border-hair)",marginBottom:8},children:e.jsx(d,{href:t})}),e.jsx("div",{"data-testid":"doc-preview-scroll",style:{flex:"1 1 0",minHeight:0,overflow:"auto",padding:"0 4px 8px"},children:o?e.jsx(a,{text:o,name:i}):e.jsx(x,{kind:"empty",icon:"file-text",title:"Berkas kosong",hint:i})})]})})}export{m as D};
@@ -1,3 +1,3 @@
1
- import{h as re,u as oe,e as y,j as e,v as le,as as T,ao as de,a as j,f as b,aP as ce,I as k,B as $,ay as xe,aA as A,p as pe,aC as ue}from"./index-gNO91_qw.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function J(s){let a={...s,kids:s.kids.map(J)};for(;!a.cat&&a.kids.length===1;){const i=a.kids[0];a={...i,label:a.label+"/"+i.label}}return a}function G(s){const a={path:"",kids:[]};for(const i of s){if(i.cat==="."){a.kids.push({path:".",label:".",cat:i,kids:[]});continue}let r=a;for(const x of i.cat.split("/")){const g=r.path?r.path+"/"+x:x;let d=r.kids.find(t=>t.path===g);d||(d={path:g,label:x,kids:[]},r.kids.push(d)),r=d}r.cat=i}return a.kids.map(J)}function O(s){const a=s.find(i=>i.scored&&i.linked)??s.find(i=>i.scored)??s[0];return a&&a.files[0]?`${a.cat}/${a.files[0]}`:""}function I({node:s,selected:a,onSelect:i,depth:r=0}){var h,u,p;const[x,g]=l.useState(!1),d=((h=s.cat)==null?void 0:h.scored)??!0,t=((u=s.cat)==null?void 0:u.linked)??!0;return e.jsxs("div",{style:r===0?{borderBottom:"1px solid var(--border-hair)"}:void 0,children:[e.jsxs("button",{onClick:()=>g(c=>!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"9px 6px",paddingLeft:6+r*12,border:"none",background:"transparent",cursor:"pointer",textAlign:"left"},children:[e.jsx(k,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(k,{name:"folder",size:15,color:d?t?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:"var(--text-strong)",fontWeight:500},children:[s.label,"/"]}),e.jsx("span",{style:{flex:1}}),s.cat&&d&&(s.cat.linked?e.jsx(k,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(k,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),x&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:1,paddingBottom:4},children:[s.kids.map(c=>e.jsx(I,{node:c,selected:a,onSelect:i,depth:r+1},c.path)),(p=s.cat)==null?void 0:p.files.map(c=>{const f=s.path+"/"+c,v=f===a;return e.jsxs("button",{onClick:()=>i(f),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 8px",paddingLeft:18+r*12,borderRadius:"var(--radius-sm)",border:"none",cursor:"pointer",textAlign:"left",background:v?"var(--brass-100)":"transparent"},children:[e.jsx(k,{name:"file-text",size:13,color:v?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:v?"var(--brass-700)":!d||t?"var(--text-body)":"var(--text-muted)",fontWeight:v?600:400},children:c})]},c)})]})]})}function ve({projectId:s,projectName:a,docStatus:i}){const[r,x]=l.useState([]),[g,d]=l.useState(0),[t,h]=re(ue("docs",s),"selected","",pe),[u,p]=l.useState({}),[c,f]=l.useState("preview"),[v,P]=l.useState("tree"),[w,F]=l.useState(""),[S,M]=l.useState(!1),{confirm:K,dialog:U}=oe(),[H,z]=l.useState("loading"),[V,q]=l.useState(0);l.useEffect(()=>{let n=!0;return z("loading"),y.getDocs(s).then(o=>{if(!n)return;const m=o.tree;x(m),d(o.coverage),p({}),f("preview"),z("ready"),h(O(m))}).catch(()=>{n&&(x([]),h(""),z("error"))}),()=>{n=!1}},[s,V]),l.useEffect(()=>{if(!t||t in u)return;let n=!0;return y.getDoc(s,t).then(o=>{n&&p(m=>({...m,[t]:o.content}))}).catch(()=>{n&&p(o=>({...o,[t]:null}))}),()=>{n=!1}},[t,s,u]);const D=!!t&&!(t in u),C=t?u[t]===null:!1,Q=()=>p(n=>{const o={...n};return delete o[t],o}),X=l.useMemo(()=>G(r.filter(n=>n.scored)),[r]),L=l.useMemo(()=>G(r.filter(n=>!n.scored)),[r]),N=u[t]??"",Y=t.includes("/")?t.slice(0,t.lastIndexOf("/")):".",B=r.find(n=>n.cat===Y),Z=t,_=i==="broken"?"err":i==="drift"?"warn":"ok",ee=i==="broken"?"broken":i==="drift"?"drift":"ok";function te(){F(N),f("edit")}function ne(){f("preview")}async function se(){await y.putDoc(s,t,w),p(n=>({...n,[t]:w})),f("preview")}function E(n){h(n),f("preview"),P("viewer")}async function R(){const n=await y.getDocs(s),o=n.tree;x(o),d(n.coverage),o.some(m=>m.files.some(ie=>`${m.cat}/${ie}`===t))||h(O(o))}async function W(){if(!S){M(!0);try{await R()}finally{M(!1)}}}async function ae(){t&&await K({title:`Hapus ${t}?`,message:"Berkas aslinya di disk ikut dihapus — dokumen ini adalah Source of Truth project.",confirmLabel:"Hapus dokumen",run:()=>y.deleteDoc(s,t)})&&(p(n=>{const o={...n};return delete o[t],o}),await R())}return e.jsxs(e.Fragment,{children:[e.jsx(le,{ariaLabel:"Panel Docs",active:v,onActiveChange:n=>P(n),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Files",className:"hn-panel-flex",content:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0,overflow:"auto"},children:[e.jsxs(T,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"12px 14px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsxs("span",{className:"hn-eyebrow",children:["docs · ",a]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(de,{status:ee,size:"sm"}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:S?"loader":"radar",onClick:W,disabled:S,children:S?"…":"Muat ulang"})]})]}),e.jsx("div",{style:{padding:"4px 8px"},children:H==="loading"?e.jsx(b,{kind:"loading",compact:!0,title:"Memuat index…"}):H==="error"?e.jsx(b,{kind:"error",compact:!0,title:"Gagal memuat index docs",hint:a,action:()=>q(n=>n+1)}):r.length===0?e.jsx(b,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada docs",hint:"Belum ada Markdown di repo ini.",action:W,actionLabel:"Muat ulang",actionIcon:"radar"}):e.jsxs(e.Fragment,{children:[X.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path)),L.length>0&&e.jsxs("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:[e.jsx("div",{className:"hn-eyebrow",style:{padding:"4px 6px",color:"var(--text-subtle)"},children:"Lainnya (tidak dinilai)"}),L.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path))]})]})})]}),e.jsxs(T,{padding:16,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12},children:[e.jsx("span",{className:"hn-eyebrow",children:"SoT coverage"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:a})]}),e.jsx(ce,{value:g,showLabel:!0,label:"Kategori ter-index",tone:_})]})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs(T,{padding:0,fill:!0,children:[e.jsxs("div",{style:{flex:"0 0 auto",display:"flex",alignItems:"center",gap:12,padding:"12px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(k,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:Z}),B&&B.scored&&(B.linked?e.jsx($,{tone:"ok",size:"sm",icon:"link",children:"indexed"}):e.jsx($,{tone:"err",size:"sm",icon:"unlink",children:"unlinked"})),e.jsx("span",{style:{flex:1}}),c==="preview"?e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(xe,{href:n=>y.docDownloadUrl(s,t,n),disabled:!t||D||C}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:ae,disabled:!t,children:"Hapus"}),e.jsx(j,{size:"sm",variant:"secondary",leftIcon:"pencil",onClick:te,disabled:!t||D||C,children:"Edit"})]}):e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(j,{size:"sm",variant:"ghost",onClick:ne,children:"Batal"}),e.jsx(j,{size:"sm",leftIcon:"check",onClick:se,children:"Simpan"})]})]}),c==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",style:{padding:"8px 30px 34px",flex:"1 1 auto",minHeight:0,overflow:"auto"},children:t?D?e.jsx(b,{kind:"loading",title:"Memuat dokumen…",hint:t}):C?e.jsx(b,{kind:"error",title:"Gagal memuat dokumen",hint:t,action:Q}):e.jsx(A,{text:N,name:t}):e.jsx(b,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari pohon docs di kiri."})}):e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1fr 1fr",flex:"1 1 auto",minHeight:0},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",borderRight:"1px solid var(--border-hair)",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{value:w,onChange:n=>F(n.target.value),spellCheck:!1,placeholder:`# Judul dokumen
1
+ import{h as re,u as oe,e as y,j as e,v as le,as as T,ao as de,a as j,f as b,aP as ce,I as k,B as $,ay as xe,aA as A,p as pe,aC as ue}from"./index-D5w059cP.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function J(s){let a={...s,kids:s.kids.map(J)};for(;!a.cat&&a.kids.length===1;){const i=a.kids[0];a={...i,label:a.label+"/"+i.label}}return a}function G(s){const a={path:"",kids:[]};for(const i of s){if(i.cat==="."){a.kids.push({path:".",label:".",cat:i,kids:[]});continue}let r=a;for(const x of i.cat.split("/")){const g=r.path?r.path+"/"+x:x;let d=r.kids.find(t=>t.path===g);d||(d={path:g,label:x,kids:[]},r.kids.push(d)),r=d}r.cat=i}return a.kids.map(J)}function O(s){const a=s.find(i=>i.scored&&i.linked)??s.find(i=>i.scored)??s[0];return a&&a.files[0]?`${a.cat}/${a.files[0]}`:""}function I({node:s,selected:a,onSelect:i,depth:r=0}){var h,u,p;const[x,g]=l.useState(!1),d=((h=s.cat)==null?void 0:h.scored)??!0,t=((u=s.cat)==null?void 0:u.linked)??!0;return e.jsxs("div",{style:r===0?{borderBottom:"1px solid var(--border-hair)"}:void 0,children:[e.jsxs("button",{onClick:()=>g(c=>!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"9px 6px",paddingLeft:6+r*12,border:"none",background:"transparent",cursor:"pointer",textAlign:"left"},children:[e.jsx(k,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(k,{name:"folder",size:15,color:d?t?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:"var(--text-strong)",fontWeight:500},children:[s.label,"/"]}),e.jsx("span",{style:{flex:1}}),s.cat&&d&&(s.cat.linked?e.jsx(k,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(k,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),x&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:1,paddingBottom:4},children:[s.kids.map(c=>e.jsx(I,{node:c,selected:a,onSelect:i,depth:r+1},c.path)),(p=s.cat)==null?void 0:p.files.map(c=>{const f=s.path+"/"+c,v=f===a;return e.jsxs("button",{onClick:()=>i(f),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 8px",paddingLeft:18+r*12,borderRadius:"var(--radius-sm)",border:"none",cursor:"pointer",textAlign:"left",background:v?"var(--brass-100)":"transparent"},children:[e.jsx(k,{name:"file-text",size:13,color:v?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:v?"var(--brass-700)":!d||t?"var(--text-body)":"var(--text-muted)",fontWeight:v?600:400},children:c})]},c)})]})]})}function ve({projectId:s,projectName:a,docStatus:i}){const[r,x]=l.useState([]),[g,d]=l.useState(0),[t,h]=re(ue("docs",s),"selected","",pe),[u,p]=l.useState({}),[c,f]=l.useState("preview"),[v,P]=l.useState("tree"),[w,F]=l.useState(""),[S,M]=l.useState(!1),{confirm:K,dialog:U}=oe(),[H,z]=l.useState("loading"),[V,q]=l.useState(0);l.useEffect(()=>{let n=!0;return z("loading"),y.getDocs(s).then(o=>{if(!n)return;const m=o.tree;x(m),d(o.coverage),p({}),f("preview"),z("ready"),h(O(m))}).catch(()=>{n&&(x([]),h(""),z("error"))}),()=>{n=!1}},[s,V]),l.useEffect(()=>{if(!t||t in u)return;let n=!0;return y.getDoc(s,t).then(o=>{n&&p(m=>({...m,[t]:o.content}))}).catch(()=>{n&&p(o=>({...o,[t]:null}))}),()=>{n=!1}},[t,s,u]);const D=!!t&&!(t in u),C=t?u[t]===null:!1,Q=()=>p(n=>{const o={...n};return delete o[t],o}),X=l.useMemo(()=>G(r.filter(n=>n.scored)),[r]),L=l.useMemo(()=>G(r.filter(n=>!n.scored)),[r]),N=u[t]??"",Y=t.includes("/")?t.slice(0,t.lastIndexOf("/")):".",B=r.find(n=>n.cat===Y),Z=t,_=i==="broken"?"err":i==="drift"?"warn":"ok",ee=i==="broken"?"broken":i==="drift"?"drift":"ok";function te(){F(N),f("edit")}function ne(){f("preview")}async function se(){await y.putDoc(s,t,w),p(n=>({...n,[t]:w})),f("preview")}function E(n){h(n),f("preview"),P("viewer")}async function R(){const n=await y.getDocs(s),o=n.tree;x(o),d(n.coverage),o.some(m=>m.files.some(ie=>`${m.cat}/${ie}`===t))||h(O(o))}async function W(){if(!S){M(!0);try{await R()}finally{M(!1)}}}async function ae(){t&&await K({title:`Hapus ${t}?`,message:"Berkas aslinya di disk ikut dihapus — dokumen ini adalah Source of Truth project.",confirmLabel:"Hapus dokumen",run:()=>y.deleteDoc(s,t)})&&(p(n=>{const o={...n};return delete o[t],o}),await R())}return e.jsxs(e.Fragment,{children:[e.jsx(le,{ariaLabel:"Panel Docs",active:v,onActiveChange:n=>P(n),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Files",className:"hn-panel-flex",content:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0,overflow:"auto"},children:[e.jsxs(T,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"12px 14px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsxs("span",{className:"hn-eyebrow",children:["docs · ",a]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(de,{status:ee,size:"sm"}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:S?"loader":"radar",onClick:W,disabled:S,children:S?"…":"Muat ulang"})]})]}),e.jsx("div",{style:{padding:"4px 8px"},children:H==="loading"?e.jsx(b,{kind:"loading",compact:!0,title:"Memuat index…"}):H==="error"?e.jsx(b,{kind:"error",compact:!0,title:"Gagal memuat index docs",hint:a,action:()=>q(n=>n+1)}):r.length===0?e.jsx(b,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada docs",hint:"Belum ada Markdown di repo ini.",action:W,actionLabel:"Muat ulang",actionIcon:"radar"}):e.jsxs(e.Fragment,{children:[X.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path)),L.length>0&&e.jsxs("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:[e.jsx("div",{className:"hn-eyebrow",style:{padding:"4px 6px",color:"var(--text-subtle)"},children:"Lainnya (tidak dinilai)"}),L.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path))]})]})})]}),e.jsxs(T,{padding:16,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12},children:[e.jsx("span",{className:"hn-eyebrow",children:"SoT coverage"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:a})]}),e.jsx(ce,{value:g,showLabel:!0,label:"Kategori ter-index",tone:_})]})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs(T,{padding:0,fill:!0,children:[e.jsxs("div",{style:{flex:"0 0 auto",display:"flex",alignItems:"center",gap:12,padding:"12px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(k,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:Z}),B&&B.scored&&(B.linked?e.jsx($,{tone:"ok",size:"sm",icon:"link",children:"indexed"}):e.jsx($,{tone:"err",size:"sm",icon:"unlink",children:"unlinked"})),e.jsx("span",{style:{flex:1}}),c==="preview"?e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(xe,{href:n=>y.docDownloadUrl(s,t,n),disabled:!t||D||C}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:ae,disabled:!t,children:"Hapus"}),e.jsx(j,{size:"sm",variant:"secondary",leftIcon:"pencil",onClick:te,disabled:!t||D||C,children:"Edit"})]}):e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(j,{size:"sm",variant:"ghost",onClick:ne,children:"Batal"}),e.jsx(j,{size:"sm",leftIcon:"check",onClick:se,children:"Simpan"})]})]}),c==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",style:{padding:"8px 30px 34px",flex:"1 1 auto",minHeight:0,overflow:"auto"},children:t?D?e.jsx(b,{kind:"loading",title:"Memuat dokumen…",hint:t}):C?e.jsx(b,{kind:"error",title:"Gagal memuat dokumen",hint:t,action:Q}):e.jsx(A,{text:N,name:t}):e.jsx(b,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari pohon docs di kiri."})}):e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1fr 1fr",flex:"1 1 auto",minHeight:0},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",borderRight:"1px solid var(--border-hair)",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{value:w,onChange:n=>F(n.target.value),spellCheck:!1,placeholder:`# Judul dokumen
2
2
 
3
3
  Paragraf pembuka…`,style:{flex:1,width:"100%",boxSizing:"border-box",resize:"none",border:"none",outline:"none",padding:"16px 18px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.7,color:"var(--text-body)",background:"var(--surface-card)"}})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Preview langsung"})}),e.jsx("div",{style:{flex:1,overflow:"auto",padding:"4px 24px 24px"},children:e.jsx(A,{text:w,name:t})})]})]})]})}]}),U]})}export{ve as DocsWorkspace,G as buildTree,O as firstDoc};