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.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +168 -546
- package/dist/server.js +1146 -2465
- package/docs/agent-integration.md +9 -74
- package/package.json +1 -1
- package/prisma/migrations/20261010070000_remove_memory_changelog/migration.sql +40 -0
- package/prisma/schema.prisma +1 -80
- package/web/assets/{DalangHanomanScreen-aLBtUGE4.js → DalangHanomanScreen-DqzYitwv.js} +1 -1
- package/web/assets/{DocPreviewModal-CHrsP0pL.js → DocPreviewModal-Chk-jQ51.js} +1 -1
- package/web/assets/{DocsWorkspace-D262CVxH.js → DocsWorkspace-DuNVIjTg.js} +1 -1
- package/web/assets/{IdeScreen-D2GI3KYh.js → IdeScreen-BZGVyFT5.js} +1 -1
- package/web/assets/{LeadScreen-eb_DK1j6.js → LeadScreen-35VgddUo.js} +1 -1
- package/web/assets/{ReviewScreen-DarOFH_a.js → ReviewScreen-EkG8ywTU.js} +1 -1
- package/web/assets/{SchedulerScreen-DKoMf2LT.js → SchedulerScreen-ClaLLB8Y.js} +1 -1
- package/web/assets/SettingsScreen-liOlVCeT.js +62 -0
- package/web/assets/{TeamScreen-C2fSsQ8C.js → TeamScreen-Dzl6Ruju.js} +1 -1
- package/web/assets/{TerminalScreen-GsfOMtu5.js → TerminalScreen-CK3SzzgP.js} +1 -1
- package/web/assets/{TriageScreen-DdKMAroz.js → TriageScreen-EtBRNg-t.js} +1 -1
- package/web/assets/{VpsScreen-CDAjvyT1.js → VpsScreen-9qeTHo1w.js} +1 -1
- package/web/assets/index-D5w059cP.js +1063 -0
- package/web/assets/{live-Cz6dWAau.js → live-Bz-jmiWI.js} +1 -1
- package/web/index.html +1 -1
- package/web/assets/ChangelogScreen-DL5v_FZf.js +0 -1
- package/web/assets/SettingsScreen-BAUhwd5K.js +0 -62
- 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
|
@@ -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
|
+
|
package/prisma/schema.prisma
CHANGED
|
@@ -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
|
|
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-
|
|
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-
|
|
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};
|