hanoman 0.9.36 → 0.9.37

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 (24) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +11 -2
  3. package/dist/server.js +43 -12
  4. package/docs/agent-integration.md +4 -0
  5. package/package.json +1 -1
  6. package/web/assets/{DalangHanomanScreen-NmpJIcg6.js → DalangHanomanScreen-JE8gkztH.js} +1 -1
  7. package/web/assets/{DocPreviewModal-DK597e3s.js → DocPreviewModal-B23vI_It.js} +1 -1
  8. package/web/assets/{DocsWorkspace-BQX-HlzW.js → DocsWorkspace-CbV27H6A.js} +1 -1
  9. package/web/assets/{IdeScreen-LeUPaFsS.js → IdeScreen-BY7sm97W.js} +1 -1
  10. package/web/assets/{LeadScreen-BVCKv46y.js → LeadScreen-BFwI29zS.js} +1 -1
  11. package/web/assets/{ReviewScreen-C6NcJChq.js → ReviewScreen-pM6zzGZl.js} +1 -1
  12. package/web/assets/{SchedulerScreen-2AH0R3TJ.js → SchedulerScreen-BIhqn3X1.js} +1 -1
  13. package/web/assets/{SettingsScreen-B4SVzh9m.js → SettingsScreen-C_TW3mbs.js} +1 -1
  14. package/web/assets/{TeamScreen-6XEfuZUm.js → TeamScreen-RT926lDf.js} +1 -1
  15. package/web/assets/TerminalScreen-fpC5a2jS.js +2 -0
  16. package/web/assets/{TriageScreen-BYJxyCar.js → TriageScreen-Zp1bdRnl.js} +1 -1
  17. package/web/assets/{VpsScreen-Df37dgKx.js → VpsScreen-Jnb8C1o2.js} +2 -2
  18. package/web/assets/{fields-C94HI0V8.js → fields-B_3dIGcG.js} +1 -1
  19. package/web/assets/{index-BeFSh2Ba.js → index-CbX7iwxN.js} +27 -27
  20. package/web/assets/{live-5ezoV9Fs.js → live-CNp86nGW.js} +1 -1
  21. package/web/assets/{sched-lead-shared-BpZu6N2A.js → sched-lead-shared-BUcJMfNH.js} +1 -1
  22. package/web/assets/{settings-rebase-DaTGgcuO.js → settings-rebase-CYr7W_rB.js} +1 -1
  23. package/web/index.html +1 -1
  24. package/web/assets/TerminalScreen-DubD6vT-.js +0 -2
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.9.36",
3
- "sha": "40fd09e5",
4
- "builtAt": "2026-10-25T08:39:29.269Z"
2
+ "version": "0.9.37",
3
+ "sha": "f525bd45",
4
+ "builtAt": "2026-10-30T09:03:54.676Z"
5
5
  }
package/dist/cli.js CHANGED
@@ -7234,7 +7234,13 @@ var init_dto = __esm({
7234
7234
  agent: zAgent.optional(),
7235
7235
  model: external_exports.string().optional(),
7236
7236
  effort: external_exports.string().optional(),
7237
- force: external_exports.boolean().optional()
7237
+ force: external_exports.boolean().optional(),
7238
+ // ADR-0232 · opsional: `worktree:true` → sesi lahir di `.worktrees/<id>` pada branch baru
7239
+ // `term/<id>` dari `branchFrom` (kosong → HEAD repo), alih-alih langsung di repoDir. Tanpa
7240
+ // keduanya body-nya byte-identik dengan sebelumnya. `branchFrom` tanpa `worktree` ditolak di
7241
+ // route — ia tak berarti apa-apa di repoDir dan diam-diam mengabaikannya menyesatkan.
7242
+ worktree: external_exports.boolean().optional(),
7243
+ branchFrom: external_exports.string().min(1).max(255).optional()
7238
7244
  }),
7239
7245
  // SPEC-252 · ADR-0061 — model & effort per SESI: override opsional saat Start; kosong → global.
7240
7246
  // SPEC-332 · ADR-0073 — mode goal per SESI: `goal` undefined → ikut Setting.goal.enabled,
@@ -11655,6 +11661,8 @@ var init_sessions = __esm({
11655
11661
  } })
11656
11662
  },
11657
11663
  prdPath: str("flow `breakdown`: jalur PRD yang dipecah. WAJIB untuk alur itu."),
11664
+ worktree: bool("Terminal agen biasa (hanya `project`, tanpa `flow`/`shell`): true = lahir di worktree terpisah pada branch baru `term/<id>`, bukan langsung di repo project. Kosong = di repo project."),
11665
+ branchFrom: str("Bersama `worktree: true`: branch/ref asal worktree (lokal atau origin). Kosong = HEAD repo."),
11658
11666
  force: bool("Lewati gerbang dependency. Pakai HANYA sesudah melihat daftar pemblokirnya.")
11659
11667
  },
11660
11668
  allOf: [
@@ -11684,7 +11692,8 @@ var init_sessions = __esm({
11684
11692
  if (flow2 === "breakdown") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2, prdPath: String(a.prdPath) } };
11685
11693
  if (flow2 === "reverse" || flow2 === "scaffold") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2 } };
11686
11694
  const body = { project };
11687
- for (const k of ["agent", "model", "effort"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
11695
+ for (const k of ["agent", "model", "effort", "branchFrom"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
11696
+ if (typeof a.worktree === "boolean") body.worktree = a.worktree;
11688
11697
  return { method: "POST", path: "/terminal/sessions", body };
11689
11698
  },
11690
11699
  shape: (raw) => raw
package/dist/server.js CHANGED
@@ -8115,7 +8115,13 @@ var init_dto = __esm({
8115
8115
  agent: zAgent.optional(),
8116
8116
  model: external_exports.string().optional(),
8117
8117
  effort: external_exports.string().optional(),
8118
- force: external_exports.boolean().optional()
8118
+ force: external_exports.boolean().optional(),
8119
+ // ADR-0232 · opsional: `worktree:true` → sesi lahir di `.worktrees/<id>` pada branch baru
8120
+ // `term/<id>` dari `branchFrom` (kosong → HEAD repo), alih-alih langsung di repoDir. Tanpa
8121
+ // keduanya body-nya byte-identik dengan sebelumnya. `branchFrom` tanpa `worktree` ditolak di
8122
+ // route — ia tak berarti apa-apa di repoDir dan diam-diam mengabaikannya menyesatkan.
8123
+ worktree: external_exports.boolean().optional(),
8124
+ branchFrom: external_exports.string().min(1).max(255).optional()
8119
8125
  }),
8120
8126
  // SPEC-252 · ADR-0061 — model & effort per SESI: override opsional saat Start; kosong → global.
8121
8127
  // SPEC-332 · ADR-0073 — mode goal per SESI: `goal` undefined → ikut Setting.goal.enabled,
@@ -13238,6 +13244,8 @@ var init_sessions = __esm({
13238
13244
  } })
13239
13245
  },
13240
13246
  prdPath: str("flow `breakdown`: jalur PRD yang dipecah. WAJIB untuk alur itu."),
13247
+ worktree: bool("Terminal agen biasa (hanya `project`, tanpa `flow`/`shell`): true = lahir di worktree terpisah pada branch baru `term/<id>`, bukan langsung di repo project. Kosong = di repo project."),
13248
+ branchFrom: str("Bersama `worktree: true`: branch/ref asal worktree (lokal atau origin). Kosong = HEAD repo."),
13241
13249
  force: bool("Lewati gerbang dependency. Pakai HANYA sesudah melihat daftar pemblokirnya.")
13242
13250
  },
13243
13251
  allOf: [
@@ -13267,7 +13275,8 @@ var init_sessions = __esm({
13267
13275
  if (flow2 === "breakdown") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2, prdPath: String(a.prdPath) } };
13268
13276
  if (flow2 === "reverse" || flow2 === "scaffold") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2 } };
13269
13277
  const body = { project };
13270
- for (const k of ["agent", "model", "effort"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
13278
+ for (const k of ["agent", "model", "effort", "branchFrom"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
13279
+ if (typeof a.worktree === "boolean") body.worktree = a.worktree;
13271
13280
  return { method: "POST", path: "/terminal/sessions", body };
13272
13281
  },
13273
13282
  shape: (raw) => raw
@@ -78287,6 +78296,8 @@ init_src2();
78287
78296
  init_session_phases();
78288
78297
  init_spec_review2();
78289
78298
  import { existsSync as existsSync18 } from "node:fs";
78299
+ import { execFileSync as execFileSync9 } from "node:child_process";
78300
+ import { randomUUID as randomUUID13 } from "node:crypto";
78290
78301
  init_integrate();
78291
78302
  init_settings3();
78292
78303
  init_codex_trust();
@@ -79647,6 +79658,26 @@ async function terminal_default(app3, opts2) {
79647
79658
  }
79648
79659
  const { agent, model, effort: effort2 } = await terminalAgentDefaults(parsed.data);
79649
79660
  if (agent === "codex") ensureCodexTrust(repoDir);
79661
+ if (parsed.data.worktree) {
79662
+ const id2 = `term-${randomUUID13().slice(0, 8)}`;
79663
+ const branch = `term/${id2.slice("term-".length)}`;
79664
+ const from = parsed.data.branchFrom ?? "HEAD";
79665
+ const result = await withSessionAdmission({ id: id2, exempt: false, force: parsed.data.force }, async () => {
79666
+ const wt = `${repoDir}/.worktrees/${id2}`;
79667
+ try {
79668
+ realGit.addWorktree(repoDir, wt, from);
79669
+ execFileSync9("git", ["switch", "-q", "-c", branch], { cwd: wt, stdio: "pipe" });
79670
+ } catch (e) {
79671
+ if (ownsWorktree(repoDir, wt)) realGit.removeWorktree(repoDir, wt);
79672
+ return { code: 422, body: { error: `gagal membuat worktree dari "${from}": ${e.message}` } };
79673
+ }
79674
+ const s3 = createSession(project.id, wt, { id: id2, agent, model, effort: effort2, branch });
79675
+ return { code: 201, body: { id: s3.id } };
79676
+ }, (pane) => ({ code: 201, body: { id: pane.id } }));
79677
+ return reply.code(result.code).send(result.body);
79678
+ }
79679
+ if (parsed.data.branchFrom)
79680
+ return reply.code(400).send({ error: "branchFrom hanya berlaku bersama worktree:true" });
79650
79681
  const s2 = await createOperatorSession(
79651
79682
  project.id,
79652
79683
  repoDir,
@@ -80686,7 +80717,7 @@ async function listVpsWithScore() {
80686
80717
  // src/services/vps-key.ts
80687
80718
  init_src2();
80688
80719
  init_config2();
80689
- import { execFileSync as execFileSync9 } from "node:child_process";
80720
+ import { execFileSync as execFileSync10 } from "node:child_process";
80690
80721
  import { chmodSync as chmodSync9, copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
80691
80722
  import { homedir as homedir11 } from "node:os";
80692
80723
  import { join as join44 } from "node:path";
@@ -80712,7 +80743,7 @@ function ensureHanomanKey() {
80712
80743
  if (!existsSync21(privPath)) adoptLegacyKey(dir2);
80713
80744
  if (!existsSync21(privPath)) {
80714
80745
  mkdirSync18(dir2, { recursive: true, mode: 448 });
80715
- execFileSync9(
80746
+ execFileSync10(
80716
80747
  "ssh-keygen",
80717
80748
  ["-t", "ed25519", "-N", "", "-C", "hanoman", "-f", privPath],
80718
80749
  { stdio: ["ignore", "ignore", "pipe"] }
@@ -81114,7 +81145,7 @@ async function antigravity(app3) {
81114
81145
  // src/services/model-catalog.ts
81115
81146
  init_src2();
81116
81147
  init_src();
81117
- import { randomUUID as randomUUID13 } from "node:crypto";
81148
+ import { randomUUID as randomUUID14 } from "node:crypto";
81118
81149
  import { readFile as readFile8, writeFile as writeFile6, rename as rename5, mkdir as mkdir9, rm as rm9 } from "node:fs/promises";
81119
81150
  import { dirname as dirname18, join as join46 } from "node:path";
81120
81151
 
@@ -81425,7 +81456,7 @@ function createModelCatalogService(deps) {
81425
81456
  async function writeModelCatalogCache(file, catalog, current = () => true) {
81426
81457
  const sanitized = parseCachedCatalog(catalog);
81427
81458
  await mkdir9(dirname18(file), { recursive: true });
81428
- const temp = `${file}.${process.pid}.${randomUUID13()}.tmp`;
81459
+ const temp = `${file}.${process.pid}.${randomUUID14()}.tmp`;
81429
81460
  try {
81430
81461
  await writeFile6(temp, JSON.stringify(sanitized), { mode: 384, flag: "wx" });
81431
81462
  if (current()) await rename5(temp, file);
@@ -87118,7 +87149,7 @@ init_qa_attachment_transfer();
87118
87149
  init_uploads();
87119
87150
  init_ask_via2();
87120
87151
  import { createHash as createHash21 } from "node:crypto";
87121
- import { execFileSync as execFileSync10 } from "node:child_process";
87152
+ import { execFileSync as execFileSync11 } from "node:child_process";
87122
87153
  import { join as join50 } from "node:path";
87123
87154
  var QaSessionError = class extends Error {
87124
87155
  constructor(code, message, needsBind = false) {
@@ -87153,7 +87184,7 @@ async function startQaFindingSession(d, fid) {
87153
87184
  if (!reused) {
87154
87185
  const base3 = realGit.revParse(repoDir, branch) ? branch : "HEAD";
87155
87186
  realGit.addWorktree(repoDir, wt, base3);
87156
- execFileSync10("git", ["checkout", "-B", branch], { cwd: wt, encoding: "utf8" });
87187
+ execFileSync11("git", ["checkout", "-B", branch], { cwd: wt, encoding: "utf8" });
87157
87188
  }
87158
87189
  } catch (e) {
87159
87190
  throw new QaSessionError(422, `Gagal membuat worktree QA: ${e.message}`);
@@ -89759,7 +89790,7 @@ init_event_log();
89759
89790
 
89760
89791
  // src/services/remote-access-request.ts
89761
89792
  init_src();
89762
- import { randomUUID as randomUUID14 } from "node:crypto";
89793
+ import { randomUUID as randomUUID15 } from "node:crypto";
89763
89794
  var REQUEST_TIER_LABEL = { lihat: "Lihat", kerja: "Kerja", tulis: "Tulis" };
89764
89795
  var entries3 = [];
89765
89796
  var accepted = [];
@@ -89783,7 +89814,7 @@ function createAccessRequest(input, now = Date.now()) {
89783
89814
  return { ok: false, reason: "rate-limited", retryAfterMs: accepted[0] + ACCESS_REQUEST_WINDOW_MS - now };
89784
89815
  accepted.push(now);
89785
89816
  const entry2 = {
89786
- id: randomUUID14(),
89817
+ id: randomUUID15(),
89787
89818
  tier: input.tier,
89788
89819
  state: "pending",
89789
89820
  requestedAt: now,
@@ -90971,7 +91002,7 @@ init_tap();
90971
91002
  init_src();
90972
91003
  init_db();
90973
91004
  init_actor();
90974
- import { randomUUID as randomUUID15 } from "node:crypto";
91005
+ import { randomUUID as randomUUID16 } from "node:crypto";
90975
91006
  function skipped(def2, row) {
90976
91007
  if (!def2.skipWhen || !row) return false;
90977
91008
  return row[def2.skipWhen.field] === def2.skipWhen.equals;
@@ -91037,7 +91068,7 @@ async function emitWebhook(i) {
91037
91068
  const targets = matchingEndpoints(type, projectId);
91038
91069
  if (!targets.length) return;
91039
91070
  const name2 = projectId ? (await prisma.project.findUnique({ where: { id: projectId }, select: { name: true } }))?.name ?? null : null;
91040
- const env = buildEnvelope(i, name2, (/* @__PURE__ */ new Date()).toISOString(), `evt_${randomUUID15().replace(/-/g, "")}`);
91071
+ const env = buildEnvelope(i, name2, (/* @__PURE__ */ new Date()).toISOString(), `evt_${randomUUID16().replace(/-/g, "")}`);
91041
91072
  if (!env) return;
91042
91073
  await enqueueEnvelope(env, targets);
91043
91074
  } catch (e) {
@@ -753,3 +753,7 @@ boundary langsung membuang cache dan hasil in-flight lama. Probe hanya `--versio
753
753
  10 detik dan 16 KiB per stream; sandbox aktif/hardening tidak mem-probe host. Kegagalan
754
754
  observasi tidak memblokir sesi host. Tool tidak memasang CLI atau mengubah konfigurasi dan
755
755
  endpoint/tool versi Codex tidak berubah.
756
+
757
+ ADR-0232: `hanoman_session_create` untuk terminal agen biasa (`project` tanpa `flow`/`shell`) menerima
758
+ `worktree: true` dan `branchFrom` — sesi lahir di worktree `.worktrees/term-<id>` pada branch baru
759
+ `term/<id>` dari branch pilihan. Tetap mode danger dengan capability `sessions:spawn`; tanpa tool baru.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.9.36",
3
+ "version": "0.9.37",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,4 +1,4 @@
1
- import{j as e,u as be,I as C,l as I,S as se,F as te}from"./index-BeFSh2Ba.js";import{R as d}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function ye({height:s,color:a,rod:l}){return e.jsxs("svg",{viewBox:"0 0 64 128",width:s*64/128,height:s,"aria-hidden":"true",focusable:"false",children:[e.jsx("path",{d:"M31.2 74 L30.2 127 L33.8 127 L32.8 74 Z",fill:l}),e.jsx("path",{d:"M51 79 L50.2 122 L53 122 L52.4 79 Z",fill:l}),e.jsx("path",{d:`M32 73
1
+ import{j as e,u as be,I as C,l as I,S as se,F as te}from"./index-CbX7iwxN.js";import{R as d}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function ye({height:s,color:a,rod:l}){return e.jsxs("svg",{viewBox:"0 0 64 128",width:s*64/128,height:s,"aria-hidden":"true",focusable:"false",children:[e.jsx("path",{d:"M31.2 74 L30.2 127 L33.8 127 L32.8 74 Z",fill:l}),e.jsx("path",{d:"M51 79 L50.2 122 L53 122 L52.4 79 Z",fill:l}),e.jsx("path",{d:`M32 73
2
2
  C 24 76, 19 88, 17.5 103 C 17 106, 20 107, 24 106.4
3
3
  C 28 106, 30 104, 32 104 C 34 104, 36 106, 40 106.4 C 44 107, 47 106, 46.5 103
4
4
  C 45 88, 40 76, 32 73 Z`,fill:a}),e.jsx("path",{d:"M32 74 C 29.5 66, 29.5 60, 31 53 L 37 53 C 38.5 60, 37.5 67, 34.5 74 Z",fill:a}),e.jsx("path",{d:`M31 53
@@ -1 +1 @@
1
- import{j as e,M as r,aP as d,aR as a,m as x}from"./index-BeFSh2Ba.js";import"./react-DfGhg7ZW.js";function f({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{f as D};
1
+ import{j as e,M as r,aP as d,aR as a,m as x}from"./index-CbX7iwxN.js";import"./react-DfGhg7ZW.js";function f({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{f as D};
@@ -1,3 +1,3 @@
1
- import{q as Ne,d as De,h as S,j as e,m as w,I as N,U as Se,Y as Ce,B as O,f as Ke,n as U,O as Le,aP as Me,aR as te,D as Pe,aU as $e,i as ie}from"./index-BeFSh2Ba.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function de(n){let t={...n,kids:n.kids.map(de)};for(;!t.cat&&t.kids.length===1;){const i=t.kids[0];t={...i,label:t.label+"/"+i.label}}return t}function re(n){const t={path:"",kids:[]};for(const i of n){if(i.cat==="."){t.kids.push({path:".",label:".",cat:i,kids:[]});continue}let l=t;for(const u of i.cat.split("/")){const k=l.path?l.path+"/"+u:u;let m=l.kids.find(s=>s.path===k);m||(m={path:k,label:u,kids:[]},l.kids.push(m)),l=m}l.cat=i}return t.kids.map(de)}function le(n){const t=n.find(i=>i.scored&&i.linked)??n.find(i=>i.scored)??n[0];return t&&t.files[0]?`${t.cat}/${t.files[0]}`:""}function oe(n){return/(^|\/)adr(s)?(\/|$)/i.test(n)?"ADR":/(^|\/)prd(s)?(\/|$)/i.test(n)?"PRD":/(^|\/)spec(s|ification)?(\/|$)/i.test(n)?"Spec":"Lainnya"}const ze=["PRD","Spec","ADR","Lainnya"],ue=n=>`dir:${n}`,Fe=(n,t)=>!!t&&t.startsWith(n.path+"/");function he({node:n,depth:t,ctx:i}){var h,p,y;const l=Fe(n,i.selected),[u,k]=o.useState(l);o.useEffect(()=>{l&&k(!0)},[l]);const m=((h=n.cat)==null?void 0:h.scored)??!0,s=((p=n.cat)==null?void 0:p.linked)??!0,v=ue(n.path),b=()=>k(d=>!d),c=d=>{d.key==="Enter"||d.key===" "?(d.preventDefault(),b()):d.key==="ArrowRight"&&!u?(d.preventDefault(),k(!0)):d.key==="ArrowLeft"&&u&&(d.preventDefault(),k(!1))};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{role:"treeitem","aria-level":t+1,"aria-expanded":u,tabIndex:i.tabbable===v?0:-1,className:"hn-docs-node hn-docs-node-dir",style:{paddingLeft:6+t*12},onClick:b,onKeyDown:c,onFocus:()=>i.setFocusKey(v),children:[e.jsx(N,{name:u?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(N,{name:"folder",size:15,color:m?s?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{className:"hn-docs-dir-label",children:[n.label,"/"]}),n.cat&&m&&(n.cat.linked?e.jsx(N,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(N,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),u&&e.jsxs("div",{role:"group",className:"hn-docs-group",children:[n.kids.map(d=>e.jsx(he,{node:d,depth:t+1,ctx:i},d.path)),(y=n.cat)==null?void 0:y.files.map(d=>{const f=n.path+"/"+d,j=f===i.selected;return e.jsxs("div",{role:"treeitem","aria-level":t+2,"aria-selected":j,"aria-current":j?"true":void 0,tabIndex:i.tabbable===f?0:-1,className:`hn-docs-node hn-docs-node-file${j?" is-selected":""}`,style:{paddingLeft:18+t*12},onClick:()=>i.onSelect(f),onFocus:()=>i.setFocusKey(f),onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&(g.preventDefault(),i.onSelect(f))},children:[e.jsx(N,{name:"file-text",size:13,color:j?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{className:`hn-docs-file-label${!m||s?"":" is-unlinked"}`,children:d})]},d)})]})]})}function ce({label:n,nodes:t,selected:i,onSelect:l}){const[u,k]=o.useState(null),m=t[0]?ue(t[0].path):"",v={selected:i,onSelect:l,tabbable:u??(i||m),setFocusKey:c=>k(c)},b=c=>{if(c.key!=="ArrowDown"&&c.key!=="ArrowUp")return;const h=Array.from(c.currentTarget.querySelectorAll('[role="treeitem"]')),p=h.indexOf(document.activeElement);if(p<0)return;c.preventDefault();const y=h[Math.min(h.length-1,Math.max(0,p+(c.key==="ArrowDown"?1:-1)))];y==null||y.focus()};return e.jsx("div",{role:"tree","aria-label":n,className:"hn-docs-tree",onKeyDown:b,children:t.map(c=>e.jsx(he,{node:c,depth:0,ctx:v},c.path))})}function Ie({projectId:n,projectName:t,docStatus:i}){const[l,u]=o.useState([]),[k,m]=o.useState(0),[s,v]=Ne($e("docs",n),"selected","",Pe),[b,c]=o.useState({}),[h,p]=o.useState("preview"),[y,d]=o.useState("tree"),[f,j]=o.useState(""),[g,q]=o.useState(!1),[L,W]=o.useState(!1),[G,C]=o.useState(""),[P,J]=o.useState(""),[D,$]=o.useState("all"),{confirm:Q,dialog:me}=De(),[z,K]=o.useState("loading"),[pe,ke]=o.useState(0);o.useEffect(()=>{let a=!0;return K("loading"),S.getDocs(n).then(r=>{if(!a)return;const x=r.tree;u(x),m(r.coverage),c({}),p("preview"),K("ready"),C(""),J(""),$("all"),v(le(x))}).catch(()=>{a&&(u([]),v(""),K("error"))}),()=>{a=!1}},[n,pe]),o.useEffect(()=>{if(!s||s in b)return;let a=!0;return S.getDoc(n,s).then(r=>{a&&c(x=>({...x,[s]:r.content}))}).catch(()=>{a&&c(r=>({...r,[s]:null}))}),()=>{a=!1}},[s,n,b]);const F=!!s&&!(s in b),A=s?b[s]===null:!1,fe=()=>c(a=>{const r={...a};return delete r[s],r}),V=a=>D==="all"||oe(a.cat)===D,xe=re(l.filter(a=>a.scored&&V(a))),Y=re(l.filter(a=>!a.scored&&V(a))),B=b[s]??"",be=s.includes("/")?s.slice(0,s.lastIndexOf("/")):".",T=l.find(a=>a.cat===be),_=s,E=h==="edit"&&f!==B,I=o.useMemo(()=>l.flatMap(a=>a.files.map(r=>({key:`${a.cat}/${r}`,scored:a.scored,linked:a.linked,kind:oe(a.cat)}))),[l]),R=P.trim().toLowerCase(),X=R?I.filter(a=>(D==="all"||a.kind===D)&&a.key.toLowerCase().includes(R)):[],ve=o.useMemo(()=>{const a={PRD:0,Spec:0,ADR:0,Lainnya:0};for(const r of I)a[r.kind]+=1;return a},[I]),ye=i==="broken"?"broken":i==="drift"?"drift":"ok";function Z(a){if(!E){p("preview"),a();return}Q({title:"Buang perubahan?",eyebrow:s,message:"Isi dokumen yang kamu ubah belum disimpan.",impact:["Perubahan di editor hilang dan tak bisa dikembalikan dari dashboard."],confirmLabel:"Buang perubahan",cancelLabel:"Lanjut mengedit",tone:"danger",icon:"trash-2"}).then(r=>{r&&(p("preview"),a())})}function ge(){C(""),j(B),p("edit")}const ee=()=>Z(()=>{});async function ae(){if(!(L||!s)){W(!0),C("");try{await S.putDoc(n,s,f),c(a=>({...a,[s]:f})),p("preview")}catch(a){C(ie("menyimpan dokumen",a))}finally{W(!1)}}}function H(a){Z(()=>{v(a),p("preview"),d("viewer")})}async function se(){const a=await S.getDocs(n),r=a.tree;u(r),m(a.coverage),r.some(x=>x.files.some(M=>`${x.cat}/${M}`===s))||v(le(r))}async function ne(){if(!g){q(!0);try{await se()}catch{K("error")}finally{q(!1)}}}async function je(){if(!s)return;const a=s;let r=!1;try{r=await Q({title:`Hapus ${a}?`,eyebrow:"Source of Truth",message:"Dokumen ini adalah Source of Truth project. Berkas aslinya di disk ikut dihapus.",impact:["Berkas di disk dihapus dan tak bisa dikembalikan dari dashboard.","Kategori indeks dihitung ulang setelah penghapusan."],confirmLabel:"Hapus dokumen",tone:"danger",icon:"trash-2",run:()=>S.deleteDoc(n,a)})}catch(x){C(ie("menghapus dokumen",x));return}if(r){c(x=>{const M={...x};return delete M[a],M});try{await se()}catch{K("error")}}}const we=z==="loading"?e.jsx(w,{kind:"loading",compact:!0,title:"Memuat indeks…"}):z==="error"?e.jsx(w,{kind:"error",compact:!0,title:"Gagal memuat indeks dokumen",hint:t,action:()=>ke(a=>a+1)}):l.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada dokumen",hint:"Belum ada Markdown di repo ini.",action:ne,actionLabel:"Muat ulang",actionIcon:"radar"}):R?X.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"search",title:"Tak ada berkas cocok",hint:`Tak ada yang cocok dengan “${P.trim()}”.`}):e.jsx("div",{role:"list","aria-label":"Hasil pencarian berkas",className:"hn-docs-results",children:X.map(a=>e.jsxs("button",{type:"button","aria-current":a.key===s?"true":void 0,onClick:()=>H(a.key),className:`hn-docs-result${a.key===s?" is-selected":""}`,children:[e.jsx(N,{name:"file-text",size:13,color:"var(--text-subtle)"}),e.jsx("span",{className:"hn-prj-mono",children:a.key}),e.jsx("span",{className:"hn-docs-result-kind",children:a.kind})]},a.key))}):e.jsxs(e.Fragment,{children:[e.jsx(ce,{label:"Berkas dokumen",nodes:xe,selected:s,onSelect:H}),Y.length>0&&e.jsxs("div",{className:"hn-docs-unscored",children:[e.jsx("div",{className:"hn-eyebrow hn-docs-unscored-label",children:"Lainnya (tidak dinilai)"}),e.jsx(ce,{label:"Dokumen tidak dinilai",nodes:Y,selected:s,onSelect:H})]})]});return e.jsxs(e.Fragment,{children:[e.jsx(Se,{ariaLabel:"Panel Dokumen",active:y,onActiveChange:a=>d(a),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Indeks",className:"hn-panel-flex",content:e.jsxs("aside",{"aria-label":"Indeks dokumen",className:"hn-docs-index",children:[e.jsxs("div",{className:"hn-docs-index-head",children:[e.jsxs("span",{className:"hn-eyebrow",children:["dokumen · ",t]}),e.jsxs("div",{className:"hn-docs-index-actions",children:[e.jsx(Ce,{status:ye,size:"sm"}),e.jsx(O,{size:"sm",variant:"ghost",leftIcon:g?"loader":"radar",onClick:ne,disabled:g,children:g?"Memuat…":"Muat ulang"})]})]}),z==="ready"&&l.length>0&&e.jsxs("div",{className:"hn-docs-index-tools",children:[e.jsx(Ke,{size:"sm","aria-label":"Cari berkas dokumen",leftIcon:"search",value:P,placeholder:"mis. product/prd",onChange:a=>J(a.target.value),className:"hn-prj-full"}),e.jsxs("div",{role:"group","aria-label":"Kategori dokumen",className:"hn-prj-chips",children:[e.jsx("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D==="all",onClick:()=>$("all"),children:"Semua"}),ze.map(a=>e.jsxs("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D===a,onClick:()=>$(a),children:[a,e.jsx("span",{className:"hn-prj-chip-count",children:ve[a]})]},a))]}),e.jsxs("span",{className:"hn-docs-cov",title:"Persentase kategori yang terindeks",children:["Cakupan ",Math.round(k),"%"]})]}),e.jsx("div",{className:"hn-docs-tree-scroll",children:we})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs("section",{"aria-label":"Isi dokumen",className:"hn-docs-viewer",style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsxs("div",{className:"hn-docs-viewer-head",children:[e.jsx(N,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{className:"hn-prj-mono hn-docs-path",children:_}),T&&T.scored&&(T.linked?e.jsx(U,{tone:"ok",size:"sm",icon:"link",children:"terindeks"}):e.jsx(U,{tone:"err",size:"sm",icon:"unlink",children:"tak tertaut"})),e.jsx("span",{className:"hn-grow"}),e.jsxs("div",{role:"group","aria-label":"Mode dokumen",className:"hn-prj-seg",children:[e.jsx("button",{type:"button","aria-pressed":h==="preview",className:"hn-touch-target",onClick:()=>{h==="edit"&&ee()},children:"Baca"}),e.jsx("button",{type:"button","aria-pressed":h==="edit",className:"hn-touch-target",onClick:()=>{h!=="edit"&&ge()},disabled:!s||F||A,children:"Edit"})]}),h==="preview"&&e.jsx(Le,{label:"Aksi untuk dokumen",icon:"ellipsis",items:[{key:"delete",label:"Hapus dokumen…",icon:"trash-2",tone:"danger",disabled:!s,onSelect:()=>{je()}}],children:e.jsx(Me,{href:a=>S.docDownloadUrl(n,s,a),disabled:!s||F||A})})]}),h==="edit"&&e.jsxs("div",{role:"region","aria-label":"Simpan perubahan",className:"hn-docs-savebar",children:[E?e.jsx(U,{tone:"warn",size:"sm",children:"belum disimpan"}):e.jsx("span",{className:"hn-prj-hint",children:"Tak ada perubahan"}),e.jsx("span",{className:"hn-grow"}),e.jsx(O,{size:"sm",variant:"ghost",onClick:ee,disabled:L,children:"Batal"}),e.jsx(O,{size:"sm",leftIcon:"check",onClick:()=>void ae(),loading:L,disabled:L||!E,children:"Simpan"})]}),G&&e.jsx("div",{role:"alert",className:"hn-docs-error",children:G}),h==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",className:"hn-docs-body",style:{flex:"1 1 auto",minHeight:0,overflow:"auto"},children:s?F?e.jsx(w,{kind:"loading",title:"Memuat dokumen…",hint:s}):A?e.jsx(w,{kind:"error",title:"Gagal memuat dokumen",hint:s,action:fe}):e.jsx("div",{className:"hn-docs-read",children:e.jsx(te,{text:B,name:s})}):e.jsx(w,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari indeks di kiri."})}):e.jsxs("div",{className:"hn-docs-edit",children:[e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{"aria-label":`Isi ${_}`,value:f,spellCheck:!1,onChange:a=>j(a.target.value),onKeyDown:a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="s"&&(a.preventDefault(),ae())},placeholder:`# Judul dokumen
1
+ import{q as Ne,d as De,h as S,j as e,m as w,I as N,U as Se,Y as Ce,B as O,f as Ke,n as U,O as Le,aP as Me,aR as te,D as Pe,aU as $e,i as ie}from"./index-CbX7iwxN.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function de(n){let t={...n,kids:n.kids.map(de)};for(;!t.cat&&t.kids.length===1;){const i=t.kids[0];t={...i,label:t.label+"/"+i.label}}return t}function re(n){const t={path:"",kids:[]};for(const i of n){if(i.cat==="."){t.kids.push({path:".",label:".",cat:i,kids:[]});continue}let l=t;for(const u of i.cat.split("/")){const k=l.path?l.path+"/"+u:u;let m=l.kids.find(s=>s.path===k);m||(m={path:k,label:u,kids:[]},l.kids.push(m)),l=m}l.cat=i}return t.kids.map(de)}function le(n){const t=n.find(i=>i.scored&&i.linked)??n.find(i=>i.scored)??n[0];return t&&t.files[0]?`${t.cat}/${t.files[0]}`:""}function oe(n){return/(^|\/)adr(s)?(\/|$)/i.test(n)?"ADR":/(^|\/)prd(s)?(\/|$)/i.test(n)?"PRD":/(^|\/)spec(s|ification)?(\/|$)/i.test(n)?"Spec":"Lainnya"}const ze=["PRD","Spec","ADR","Lainnya"],ue=n=>`dir:${n}`,Fe=(n,t)=>!!t&&t.startsWith(n.path+"/");function he({node:n,depth:t,ctx:i}){var h,p,y;const l=Fe(n,i.selected),[u,k]=o.useState(l);o.useEffect(()=>{l&&k(!0)},[l]);const m=((h=n.cat)==null?void 0:h.scored)??!0,s=((p=n.cat)==null?void 0:p.linked)??!0,v=ue(n.path),b=()=>k(d=>!d),c=d=>{d.key==="Enter"||d.key===" "?(d.preventDefault(),b()):d.key==="ArrowRight"&&!u?(d.preventDefault(),k(!0)):d.key==="ArrowLeft"&&u&&(d.preventDefault(),k(!1))};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{role:"treeitem","aria-level":t+1,"aria-expanded":u,tabIndex:i.tabbable===v?0:-1,className:"hn-docs-node hn-docs-node-dir",style:{paddingLeft:6+t*12},onClick:b,onKeyDown:c,onFocus:()=>i.setFocusKey(v),children:[e.jsx(N,{name:u?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(N,{name:"folder",size:15,color:m?s?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{className:"hn-docs-dir-label",children:[n.label,"/"]}),n.cat&&m&&(n.cat.linked?e.jsx(N,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(N,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),u&&e.jsxs("div",{role:"group",className:"hn-docs-group",children:[n.kids.map(d=>e.jsx(he,{node:d,depth:t+1,ctx:i},d.path)),(y=n.cat)==null?void 0:y.files.map(d=>{const f=n.path+"/"+d,j=f===i.selected;return e.jsxs("div",{role:"treeitem","aria-level":t+2,"aria-selected":j,"aria-current":j?"true":void 0,tabIndex:i.tabbable===f?0:-1,className:`hn-docs-node hn-docs-node-file${j?" is-selected":""}`,style:{paddingLeft:18+t*12},onClick:()=>i.onSelect(f),onFocus:()=>i.setFocusKey(f),onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&(g.preventDefault(),i.onSelect(f))},children:[e.jsx(N,{name:"file-text",size:13,color:j?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{className:`hn-docs-file-label${!m||s?"":" is-unlinked"}`,children:d})]},d)})]})]})}function ce({label:n,nodes:t,selected:i,onSelect:l}){const[u,k]=o.useState(null),m=t[0]?ue(t[0].path):"",v={selected:i,onSelect:l,tabbable:u??(i||m),setFocusKey:c=>k(c)},b=c=>{if(c.key!=="ArrowDown"&&c.key!=="ArrowUp")return;const h=Array.from(c.currentTarget.querySelectorAll('[role="treeitem"]')),p=h.indexOf(document.activeElement);if(p<0)return;c.preventDefault();const y=h[Math.min(h.length-1,Math.max(0,p+(c.key==="ArrowDown"?1:-1)))];y==null||y.focus()};return e.jsx("div",{role:"tree","aria-label":n,className:"hn-docs-tree",onKeyDown:b,children:t.map(c=>e.jsx(he,{node:c,depth:0,ctx:v},c.path))})}function Ie({projectId:n,projectName:t,docStatus:i}){const[l,u]=o.useState([]),[k,m]=o.useState(0),[s,v]=Ne($e("docs",n),"selected","",Pe),[b,c]=o.useState({}),[h,p]=o.useState("preview"),[y,d]=o.useState("tree"),[f,j]=o.useState(""),[g,q]=o.useState(!1),[L,W]=o.useState(!1),[G,C]=o.useState(""),[P,J]=o.useState(""),[D,$]=o.useState("all"),{confirm:Q,dialog:me}=De(),[z,K]=o.useState("loading"),[pe,ke]=o.useState(0);o.useEffect(()=>{let a=!0;return K("loading"),S.getDocs(n).then(r=>{if(!a)return;const x=r.tree;u(x),m(r.coverage),c({}),p("preview"),K("ready"),C(""),J(""),$("all"),v(le(x))}).catch(()=>{a&&(u([]),v(""),K("error"))}),()=>{a=!1}},[n,pe]),o.useEffect(()=>{if(!s||s in b)return;let a=!0;return S.getDoc(n,s).then(r=>{a&&c(x=>({...x,[s]:r.content}))}).catch(()=>{a&&c(r=>({...r,[s]:null}))}),()=>{a=!1}},[s,n,b]);const F=!!s&&!(s in b),A=s?b[s]===null:!1,fe=()=>c(a=>{const r={...a};return delete r[s],r}),V=a=>D==="all"||oe(a.cat)===D,xe=re(l.filter(a=>a.scored&&V(a))),Y=re(l.filter(a=>!a.scored&&V(a))),B=b[s]??"",be=s.includes("/")?s.slice(0,s.lastIndexOf("/")):".",T=l.find(a=>a.cat===be),_=s,E=h==="edit"&&f!==B,I=o.useMemo(()=>l.flatMap(a=>a.files.map(r=>({key:`${a.cat}/${r}`,scored:a.scored,linked:a.linked,kind:oe(a.cat)}))),[l]),R=P.trim().toLowerCase(),X=R?I.filter(a=>(D==="all"||a.kind===D)&&a.key.toLowerCase().includes(R)):[],ve=o.useMemo(()=>{const a={PRD:0,Spec:0,ADR:0,Lainnya:0};for(const r of I)a[r.kind]+=1;return a},[I]),ye=i==="broken"?"broken":i==="drift"?"drift":"ok";function Z(a){if(!E){p("preview"),a();return}Q({title:"Buang perubahan?",eyebrow:s,message:"Isi dokumen yang kamu ubah belum disimpan.",impact:["Perubahan di editor hilang dan tak bisa dikembalikan dari dashboard."],confirmLabel:"Buang perubahan",cancelLabel:"Lanjut mengedit",tone:"danger",icon:"trash-2"}).then(r=>{r&&(p("preview"),a())})}function ge(){C(""),j(B),p("edit")}const ee=()=>Z(()=>{});async function ae(){if(!(L||!s)){W(!0),C("");try{await S.putDoc(n,s,f),c(a=>({...a,[s]:f})),p("preview")}catch(a){C(ie("menyimpan dokumen",a))}finally{W(!1)}}}function H(a){Z(()=>{v(a),p("preview"),d("viewer")})}async function se(){const a=await S.getDocs(n),r=a.tree;u(r),m(a.coverage),r.some(x=>x.files.some(M=>`${x.cat}/${M}`===s))||v(le(r))}async function ne(){if(!g){q(!0);try{await se()}catch{K("error")}finally{q(!1)}}}async function je(){if(!s)return;const a=s;let r=!1;try{r=await Q({title:`Hapus ${a}?`,eyebrow:"Source of Truth",message:"Dokumen ini adalah Source of Truth project. Berkas aslinya di disk ikut dihapus.",impact:["Berkas di disk dihapus dan tak bisa dikembalikan dari dashboard.","Kategori indeks dihitung ulang setelah penghapusan."],confirmLabel:"Hapus dokumen",tone:"danger",icon:"trash-2",run:()=>S.deleteDoc(n,a)})}catch(x){C(ie("menghapus dokumen",x));return}if(r){c(x=>{const M={...x};return delete M[a],M});try{await se()}catch{K("error")}}}const we=z==="loading"?e.jsx(w,{kind:"loading",compact:!0,title:"Memuat indeks…"}):z==="error"?e.jsx(w,{kind:"error",compact:!0,title:"Gagal memuat indeks dokumen",hint:t,action:()=>ke(a=>a+1)}):l.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada dokumen",hint:"Belum ada Markdown di repo ini.",action:ne,actionLabel:"Muat ulang",actionIcon:"radar"}):R?X.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"search",title:"Tak ada berkas cocok",hint:`Tak ada yang cocok dengan “${P.trim()}”.`}):e.jsx("div",{role:"list","aria-label":"Hasil pencarian berkas",className:"hn-docs-results",children:X.map(a=>e.jsxs("button",{type:"button","aria-current":a.key===s?"true":void 0,onClick:()=>H(a.key),className:`hn-docs-result${a.key===s?" is-selected":""}`,children:[e.jsx(N,{name:"file-text",size:13,color:"var(--text-subtle)"}),e.jsx("span",{className:"hn-prj-mono",children:a.key}),e.jsx("span",{className:"hn-docs-result-kind",children:a.kind})]},a.key))}):e.jsxs(e.Fragment,{children:[e.jsx(ce,{label:"Berkas dokumen",nodes:xe,selected:s,onSelect:H}),Y.length>0&&e.jsxs("div",{className:"hn-docs-unscored",children:[e.jsx("div",{className:"hn-eyebrow hn-docs-unscored-label",children:"Lainnya (tidak dinilai)"}),e.jsx(ce,{label:"Dokumen tidak dinilai",nodes:Y,selected:s,onSelect:H})]})]});return e.jsxs(e.Fragment,{children:[e.jsx(Se,{ariaLabel:"Panel Dokumen",active:y,onActiveChange:a=>d(a),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Indeks",className:"hn-panel-flex",content:e.jsxs("aside",{"aria-label":"Indeks dokumen",className:"hn-docs-index",children:[e.jsxs("div",{className:"hn-docs-index-head",children:[e.jsxs("span",{className:"hn-eyebrow",children:["dokumen · ",t]}),e.jsxs("div",{className:"hn-docs-index-actions",children:[e.jsx(Ce,{status:ye,size:"sm"}),e.jsx(O,{size:"sm",variant:"ghost",leftIcon:g?"loader":"radar",onClick:ne,disabled:g,children:g?"Memuat…":"Muat ulang"})]})]}),z==="ready"&&l.length>0&&e.jsxs("div",{className:"hn-docs-index-tools",children:[e.jsx(Ke,{size:"sm","aria-label":"Cari berkas dokumen",leftIcon:"search",value:P,placeholder:"mis. product/prd",onChange:a=>J(a.target.value),className:"hn-prj-full"}),e.jsxs("div",{role:"group","aria-label":"Kategori dokumen",className:"hn-prj-chips",children:[e.jsx("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D==="all",onClick:()=>$("all"),children:"Semua"}),ze.map(a=>e.jsxs("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D===a,onClick:()=>$(a),children:[a,e.jsx("span",{className:"hn-prj-chip-count",children:ve[a]})]},a))]}),e.jsxs("span",{className:"hn-docs-cov",title:"Persentase kategori yang terindeks",children:["Cakupan ",Math.round(k),"%"]})]}),e.jsx("div",{className:"hn-docs-tree-scroll",children:we})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs("section",{"aria-label":"Isi dokumen",className:"hn-docs-viewer",style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsxs("div",{className:"hn-docs-viewer-head",children:[e.jsx(N,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{className:"hn-prj-mono hn-docs-path",children:_}),T&&T.scored&&(T.linked?e.jsx(U,{tone:"ok",size:"sm",icon:"link",children:"terindeks"}):e.jsx(U,{tone:"err",size:"sm",icon:"unlink",children:"tak tertaut"})),e.jsx("span",{className:"hn-grow"}),e.jsxs("div",{role:"group","aria-label":"Mode dokumen",className:"hn-prj-seg",children:[e.jsx("button",{type:"button","aria-pressed":h==="preview",className:"hn-touch-target",onClick:()=>{h==="edit"&&ee()},children:"Baca"}),e.jsx("button",{type:"button","aria-pressed":h==="edit",className:"hn-touch-target",onClick:()=>{h!=="edit"&&ge()},disabled:!s||F||A,children:"Edit"})]}),h==="preview"&&e.jsx(Le,{label:"Aksi untuk dokumen",icon:"ellipsis",items:[{key:"delete",label:"Hapus dokumen…",icon:"trash-2",tone:"danger",disabled:!s,onSelect:()=>{je()}}],children:e.jsx(Me,{href:a=>S.docDownloadUrl(n,s,a),disabled:!s||F||A})})]}),h==="edit"&&e.jsxs("div",{role:"region","aria-label":"Simpan perubahan",className:"hn-docs-savebar",children:[E?e.jsx(U,{tone:"warn",size:"sm",children:"belum disimpan"}):e.jsx("span",{className:"hn-prj-hint",children:"Tak ada perubahan"}),e.jsx("span",{className:"hn-grow"}),e.jsx(O,{size:"sm",variant:"ghost",onClick:ee,disabled:L,children:"Batal"}),e.jsx(O,{size:"sm",leftIcon:"check",onClick:()=>void ae(),loading:L,disabled:L||!E,children:"Simpan"})]}),G&&e.jsx("div",{role:"alert",className:"hn-docs-error",children:G}),h==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",className:"hn-docs-body",style:{flex:"1 1 auto",minHeight:0,overflow:"auto"},children:s?F?e.jsx(w,{kind:"loading",title:"Memuat dokumen…",hint:s}):A?e.jsx(w,{kind:"error",title:"Gagal memuat dokumen",hint:s,action:fe}):e.jsx("div",{className:"hn-docs-read",children:e.jsx(te,{text:B,name:s})}):e.jsx(w,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari indeks di kiri."})}):e.jsxs("div",{className:"hn-docs-edit",children:[e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{"aria-label":`Isi ${_}`,value:f,spellCheck:!1,onChange:a=>j(a.target.value),onKeyDown:a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="s"&&(a.preventDefault(),ae())},placeholder:`# Judul dokumen
2
2
 
3
3
  Paragraf pembuka…`,className:"hn-docs-textarea"})]}),e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Pratinjau langsung"})}),e.jsx("div",{className:"hn-docs-preview",children:e.jsx(te,{text:f,name:s})})]})]})]})}]}),me]})}export{Ie as DocsWorkspace,re as buildTree,oe as docKind,le as firstDoc};