hanoman 0.2.1 → 0.2.2

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.1",
3
- "sha": "0aa68209",
4
- "builtAt": "2026-08-26T04:13:10.476Z"
2
+ "version": "0.2.2",
3
+ "sha": "0eb2277f",
4
+ "builtAt": "2026-08-26T05:23:49.777Z"
5
5
  }
package/dist/cli.js CHANGED
@@ -4740,6 +4740,12 @@ var init_agent = __esm({
4740
4740
  // capability domain produk masing-masing; domain ini tidak memberi akses shell atau sesi.
4741
4741
  "telegram:read",
4742
4742
  "telegram:write",
4743
+ // ADR-0157 · papan Tim (`/api/tasks`, `/api/members`). Domain TERSENDIRI, bukan menumpang
4744
+ // `backlog`: kartu tim adalah pekerjaan MANUSIA yang `status`-nya bebas dipindah, sementara
4745
+ // `Spec.stage` diturunkan dari fase sesi (ADR-0008/0024). Menumpangkannya berarti satu centang
4746
+ // "Backlog — tulis" diam-diam membuka papan orang, dan sebaliknya.
4747
+ "team:read",
4748
+ "team:write",
4743
4749
  // ADR-0155 · akses KETIGA: `danger`. Dipecah dari `:write` karena keempat operasi ini bukan
4744
4750
  // "menulis lebih banyak", melainkan menjalankan sesuatu di luar proses hanoman — sesi agen di
4745
4751
  // worktree, perintah di VPS, git yang mengubah sejarah, penghapusan artefak dokumen.
@@ -7008,6 +7014,50 @@ var init_webhook = __esm({
7008
7014
  }
7009
7015
  });
7010
7016
 
7017
+ // ../shared/src/team.ts
7018
+ var TASK_STATUSES, zTaskStatus, zEmail, zName, zIso, zCreateMember, zPatchMember, zCreateTask, zPatchTask, ESCALATE_SOURCES, zEscalateTask;
7019
+ var init_team = __esm({
7020
+ "../shared/src/team.ts"() {
7021
+ "use strict";
7022
+ init_zod();
7023
+ init_enums();
7024
+ TASK_STATUSES = ["backlog", "doing", "review", "done"];
7025
+ zTaskStatus = external_exports.enum(TASK_STATUSES);
7026
+ zEmail = external_exports.string().trim().min(3).max(200).email();
7027
+ zName = external_exports.string().trim().min(1).max(120);
7028
+ zIso = external_exports.string().datetime({ offset: true });
7029
+ zCreateMember = external_exports.object({
7030
+ name: zName,
7031
+ email: zEmail,
7032
+ role: external_exports.string().trim().max(60).nullable().optional()
7033
+ });
7034
+ zPatchMember = zCreateMember.omit({ email: true }).partial().extend({
7035
+ active: external_exports.boolean().optional()
7036
+ });
7037
+ zCreateTask = external_exports.object({
7038
+ title: external_exports.string().trim().min(1).max(300),
7039
+ detail: external_exports.string().max(2e4).nullable().optional(),
7040
+ projectId: external_exports.string().max(120).nullable().optional(),
7041
+ status: zTaskStatus.default("backlog"),
7042
+ priority: zPriority.default("sedang"),
7043
+ memberId: external_exports.string().max(200).nullable().optional(),
7044
+ startDate: zIso.nullable().optional(),
7045
+ dueDate: zIso.nullable().optional(),
7046
+ order: external_exports.number().finite().optional()
7047
+ });
7048
+ zPatchTask = zCreateTask.partial();
7049
+ ESCALATE_SOURCES = ["brief", "qa", "audit"];
7050
+ zEscalateTask = external_exports.object({
7051
+ source: external_exports.enum(ESCALATE_SOURCES).default("brief"),
7052
+ priority: zPriority.default("sedang"),
7053
+ // Dipakai HANYA saat kartunya belum punya project (`nextSpecId` butuh repo, dan repo milik
7054
+ // project). Route menolak 400 bila ia menyebut project LAIN — kartu tak boleh berpindah project
7055
+ // sebagai efek samping yang tak diminta.
7056
+ projectId: external_exports.string().max(120).optional()
7057
+ });
7058
+ }
7059
+ });
7060
+
7011
7061
  // ../shared/src/mcp-schema.ts
7012
7062
  function obj(o) {
7013
7063
  return {
@@ -7019,11 +7069,12 @@ function obj(o) {
7019
7069
  ...o.allOf ? { allOf: o.allOf } : {}
7020
7070
  };
7021
7071
  }
7022
- var str, enumStr, bool, int, strArray, PRIORITY_ENUM, SOURCE_ENUM, STAGE_ENUM, SEVERITY_ENUM, PRIORITY, BRIEF_PAYLOAD, QA_PAYLOAD, GOAL_PAYLOAD, SPEC_PAYLOAD_ONEOF, SOURCE_PAYLOAD_ALLOF, PAGE_PARAMS, DATE_PARAMS;
7072
+ var str, enumStr, bool, int, strArray, PRIORITY_ENUM, SOURCE_ENUM, STAGE_ENUM, SEVERITY_ENUM, TASK_STATUS_ENUM, ESCALATE_SOURCE_ENUM, PRIORITY, BRIEF_PAYLOAD, QA_PAYLOAD, GOAL_PAYLOAD, SPEC_PAYLOAD_ONEOF, SOURCE_PAYLOAD_ALLOF, PAGE_PARAMS, DATE_PARAMS;
7023
7073
  var init_mcp_schema = __esm({
7024
7074
  "../shared/src/mcp-schema.ts"() {
7025
7075
  "use strict";
7026
7076
  init_enums();
7077
+ init_team();
7027
7078
  str = (description, extra = {}) => ({ type: "string", description, ...extra });
7028
7079
  enumStr = (values, description) => ({ type: "string", enum: values, description });
7029
7080
  bool = (description) => ({ type: "boolean", description });
@@ -7033,6 +7084,8 @@ var init_mcp_schema = __esm({
7033
7084
  SOURCE_ENUM = zSpecSource.options;
7034
7085
  STAGE_ENUM = zStage.options;
7035
7086
  SEVERITY_ENUM = ["critical", "major", "minor"];
7087
+ TASK_STATUS_ENUM = TASK_STATUSES;
7088
+ ESCALATE_SOURCE_ENUM = ESCALATE_SOURCES;
7036
7089
  PRIORITY = enumStr(
7037
7090
  PRIORITY_ENUM,
7038
7091
  "Prioritas backlog. Nilainya bahasa Indonesia \u2014 `tinggi`, `sedang`, `rendah`. Bukan high/medium/low."
@@ -7142,7 +7195,7 @@ function renderResult(value, maxBytes) {
7142
7195
  preview: head
7143
7196
  }).slice(0, maxBytes);
7144
7197
  }
7145
- var DEFAULT_MAX_BYTES, DEFAULT_LIMIT, MAX_LIMIT, OBJECTIVE_CLIP, MARK, pick, shapeProject, shapeProjectDetail, SPEC_BASE, shapeSpecDetail, shapeSession, shapeNotification, shapeTicket, shapeGithubIssue, shapeLeadDecision;
7198
+ var DEFAULT_MAX_BYTES, DEFAULT_LIMIT, MAX_LIMIT, OBJECTIVE_CLIP, MARK, pick, shapeProject, shapeProjectDetail, SPEC_BASE, shapeSpecDetail, shapeSession, shapeNotification, shapeTicket, shapeGithubIssue, shapeTask, shapeMember, shapeLeadDecision;
7146
7199
  var init_mcp_shape = __esm({
7147
7200
  "../shared/src/mcp-shape.ts"() {
7148
7201
  "use strict";
@@ -7204,6 +7257,25 @@ var init_mcp_shape = __esm({
7204
7257
  ...pick(row, ["id", "projectId", "repoSlug", "number", "title", "authorLogin", "labels", "url", "issueState", "status", "specId", "issueUpdatedAt"]),
7205
7258
  body: clip(row.body, 500)
7206
7259
  });
7260
+ shapeTask = (row) => ({
7261
+ ...pick(row, [
7262
+ "id",
7263
+ "projectId",
7264
+ "title",
7265
+ "status",
7266
+ "priority",
7267
+ "memberId",
7268
+ "startDate",
7269
+ "dueDate",
7270
+ "order",
7271
+ "specId",
7272
+ "spec",
7273
+ "createdAt",
7274
+ "updatedAt"
7275
+ ]),
7276
+ detail: clip(row.detail, 500)
7277
+ });
7278
+ shapeMember = (row) => pick(row, ["id", "name", "email", "role", "active"]);
7207
7279
  shapeLeadDecision = (row) => ({
7208
7280
  ...pick(row, ["id", "projectId", "specId", "sessionId", "gate", "kind", "status", "confidence", "action", "choice", "createdAt"]),
7209
7281
  question: clip(row.question, 300),
@@ -10314,6 +10386,311 @@ var init_lead2 = __esm({
10314
10386
  }
10315
10387
  });
10316
10388
 
10389
+ // ../shared/src/mcp-catalog/team.ts
10390
+ var TASK_ID, MEMBER_ID, nullable, CLEAR, TASK_FIELDS, taskBody, TASKS, MEMBERS, DESTRUCTIVE, TEAM_TOOLS;
10391
+ var init_team2 = __esm({
10392
+ "../shared/src/mcp-catalog/team.ts"() {
10393
+ "use strict";
10394
+ init_mcp_schema();
10395
+ init_mcp_shape();
10396
+ init_helpers();
10397
+ TASK_ID = str("Id kartu papan Tim, seperti muncul di hanoman_tasks_list.");
10398
+ MEMBER_ID = str("Id anggota \u2014 email ternormalisasi (huruf kecil), seperti muncul di hanoman_members_list.");
10399
+ nullable = (v) => {
10400
+ if (typeof v !== "string") return void 0;
10401
+ return v === "" ? null : v;
10402
+ };
10403
+ CLEAR = " Kirim string KOSONG untuk mengosongkannya; tak menyebutnya sama sekali berarti biarkan apa adanya.";
10404
+ TASK_FIELDS = {
10405
+ title: str("Judul kartu, satu baris."),
10406
+ detail: str("Isi kartu. Markdown bebas." + CLEAR),
10407
+ project: str("Id project pemilik kartu. Kartu BOLEH tanpa project \u2014 papan Tim tak mensyaratkannya." + CLEAR),
10408
+ status: enumStr(TASK_STATUS_ENUM, "Kolom papan. Milik MANUSIA dan bebas dipindah \u2014 ini BUKAN `stage` backlog, yang diturunkan dari fase sesi."),
10409
+ priority: PRIORITY,
10410
+ member: str("Id anggota yang ditugaskan (email huruf kecil), dari hanoman_members_list." + CLEAR),
10411
+ startDate: str("Tanggal mulai, ISO 8601 berzona mis. `2026-09-01T00:00:00.000Z`. `besok` ditolak." + CLEAR),
10412
+ dueDate: str("Tanggal jatuh tempo, ISO 8601 berzona. Ini tanggal KARTU, bukan estimasi backlog." + CLEAR)
10413
+ };
10414
+ taskBody = (a) => {
10415
+ const body = {};
10416
+ if (s(a.title)) body.title = s(a.title);
10417
+ if (s(a.status)) body.status = s(a.status);
10418
+ if (s(a.priority)) body.priority = s(a.priority);
10419
+ if (n(a.order) !== void 0) body.order = n(a.order);
10420
+ for (const [key, arg] of [
10421
+ ["detail", a.detail],
10422
+ ["projectId", a.project],
10423
+ ["memberId", a.member],
10424
+ ["startDate", a.startDate],
10425
+ ["dueDate", a.dueDate]
10426
+ ]) {
10427
+ const v = nullable(arg);
10428
+ if (v !== void 0) body[key] = v;
10429
+ }
10430
+ return body;
10431
+ };
10432
+ TASKS = [
10433
+ {
10434
+ name: "hanoman_tasks_list",
10435
+ title: "Kartu papan Tim",
10436
+ description: "Kartu kerja MANUSIA di papan Tim, terurut sesuai posisinya di kolom. Empat kolom: `backlog`, `doing`, `review`, `done` \u2014 milik manusia, tak diturunkan dari sesi agen. `specId`/`spec` terisi hanya untuk kartu yang sudah dieskalasi jadi backlog item; `specId` terisi sementara `spec` null berarti tautannya PUTUS (backlognya sudah dihapus), bukan belum dieskalasi.",
10437
+ inputSchema: obj({
10438
+ properties: {
10439
+ project: str("Id project. Tanpa ini, seluruh project \u2014 termasuk kartu tanpa project."),
10440
+ status: enumStr(TASK_STATUS_ENUM, "Kolom papan."),
10441
+ member: MEMBER_ID,
10442
+ q: str("Cari substring pada judul + detail, tak peka huruf besar-kecil. Disaring SEBELUM paginasi, jadi hasilnya tak buta terhadap kartu di luar halaman pertama."),
10443
+ ...PAGE_PARAMS
10444
+ }
10445
+ }),
10446
+ mode: "read",
10447
+ capability: "team:read",
10448
+ samplePath: "/tasks",
10449
+ sampleMethod: "GET",
10450
+ build: (a) => ({
10451
+ method: "GET",
10452
+ path: "/tasks",
10453
+ query: query({
10454
+ projectId: s(a.project),
10455
+ status: s(a.status),
10456
+ memberId: s(a.member),
10457
+ q: s(a.q),
10458
+ page: n(a.page) === void 0 ? void 0 : String(n(a.page)),
10459
+ limit: n(a.limit) === void 0 ? void 0 : String(n(a.limit))
10460
+ })
10461
+ }),
10462
+ shape: (raw) => reshapePage(raw, shapeTask)
10463
+ },
10464
+ {
10465
+ name: "hanoman_task_create",
10466
+ title: "Buat kartu papan Tim",
10467
+ description: "Membuat kartu kerja manusia di papan Tim. Kartu BARU tak pernah tertaut backlog \u2014 tautan itu lahir dari hanoman_task_escalate, bukan dari field. Untuk pekerjaan yang akan dikerjakan AGEN, pakai hanoman_backlog_create: papan ini bukan antrean sesi.",
10468
+ inputSchema: obj({ properties: { ...TASK_FIELDS }, required: ["title"] }),
10469
+ mode: "write",
10470
+ capability: "team:write",
10471
+ samplePath: "/tasks",
10472
+ sampleMethod: "POST",
10473
+ build: (a) => ({ method: "POST", path: "/tasks", body: taskBody(a) }),
10474
+ shape: (raw) => shapeTask(raw)
10475
+ },
10476
+ {
10477
+ name: "hanoman_task_update",
10478
+ title: "Ubah kartu papan Tim",
10479
+ description: "Mengubah kartu papan Tim. Hanya field yang disebut yang ditulis. Kartu yang SUDAH tertaut backlog menolak pindah project dengan 400 \u2014 lepas tautannya dulu lewat hanoman_task_unlink. `specId` sengaja tak bisa diisi di sini.",
10480
+ inputSchema: obj({ properties: { task: TASK_ID, ...TASK_FIELDS }, required: ["task"] }),
10481
+ mode: "write",
10482
+ capability: "team:write",
10483
+ samplePath: "/tasks/t1",
10484
+ sampleMethod: "PATCH",
10485
+ build: (a) => ({ method: "PATCH", path: `/tasks/${enc(String(a.task))}`, body: taskBody(a) }),
10486
+ shape: (raw) => shapeTask(raw)
10487
+ },
10488
+ {
10489
+ name: "hanoman_task_escalate",
10490
+ title: "Eskalasi kartu jadi backlog item",
10491
+ description: "Melahirkan backlog item dari sebuah kartu papan Tim, lalu menautkan keduanya. IDEMPOTEN: kartu yang sudah tertaut menjawab 200 dengan `created: false` dan spec yang sama, bukan membuat backlog kedua. Kartu TANPA project ditolak 400 \u2014 id backlog diturunkan dari repo milik project, jadi sebutkan `project` lebih dulu. Ini TIDAK membuka sesi agen; peluncurannya tetap tindakan terpisah, dan Spec-nya lahir tanpa persetujuan peluncuran bila token pemanggil tak memegang `sessions:write`.",
10492
+ inputSchema: obj({
10493
+ properties: {
10494
+ task: TASK_ID,
10495
+ source: enumStr(ESCALATE_SOURCE_ENUM, "Bentuk backlog yang dilahirkan. Default `brief`. `goal`/`no_effort`/`help` sengaja tak tersedia: dua yang pertama menuntut kalimat yang hanya operator bisa tulis, yang terakhir milik tiket Help Center."),
10496
+ priority: PRIORITY,
10497
+ project: str("Id project tujuan. HANYA dipakai bila kartunya belum punya project \u2014 menyebut project LAIN dari milik kartu ditolak 400.")
10498
+ },
10499
+ required: ["task"]
10500
+ }),
10501
+ mode: "write",
10502
+ capability: "team:write",
10503
+ samplePath: "/tasks/t1/escalate",
10504
+ sampleMethod: "POST",
10505
+ build: (a) => ({
10506
+ method: "POST",
10507
+ path: `/tasks/${enc(String(a.task))}/escalate`,
10508
+ body: query({ source: s(a.source), priority: s(a.priority), projectId: s(a.project) })
10509
+ }),
10510
+ shape: (raw) => raw
10511
+ },
10512
+ {
10513
+ name: "hanoman_task_unlink",
10514
+ title: "Lepas tautan kartu dari backlog",
10515
+ description: "Melepas tautan kartu papan Tim dari backlog item-nya. NON-DESTRUKTIF: backlog item-nya dibiarkan hidup \u2014 hapus manual lewat hanoman_backlog_delete bila memang salah eskalasi. Idempoten: kartu yang memang tak tertaut menjawab 200 apa adanya.",
10516
+ inputSchema: obj({ properties: { task: TASK_ID }, required: ["task"] }),
10517
+ mode: "write",
10518
+ capability: "team:write",
10519
+ samplePath: "/tasks/t1/escalate",
10520
+ sampleMethod: "DELETE",
10521
+ build: (a) => ({ method: "DELETE", path: `/tasks/${enc(String(a.task))}/escalate` }),
10522
+ shape: (raw) => shapeTask(raw)
10523
+ }
10524
+ ];
10525
+ MEMBERS = [
10526
+ {
10527
+ name: "hanoman_members_list",
10528
+ title: "Anggota tim",
10529
+ description: "Direktori orang untuk papan Tim. GLOBAL, bukan per project \u2014 kartu boleh tanpa project. Anggota nonaktif TETAP terdaftar (di bawah): kartu lama yang ditugaskan padanya harus tetap punya nama. `id` = email ternormalisasi, dan itu yang dipakai sebagai `member` di tool kartu.",
10530
+ inputSchema: obj({ properties: { activeOnly: bool("Hanya anggota aktif. Default: semua, nonaktif di urutan bawah."), ...PAGE_PARAMS } }),
10531
+ mode: "read",
10532
+ capability: "team:read",
10533
+ samplePath: "/members",
10534
+ sampleMethod: "GET",
10535
+ build: (a) => ({
10536
+ method: "GET",
10537
+ path: "/members",
10538
+ query: query({
10539
+ active: a.activeOnly === true ? "true" : void 0,
10540
+ page: n(a.page) === void 0 ? void 0 : String(n(a.page)),
10541
+ limit: n(a.limit) === void 0 ? void 0 : String(n(a.limit))
10542
+ })
10543
+ }),
10544
+ shape: (raw) => reshapePage(raw, shapeMember)
10545
+ },
10546
+ {
10547
+ name: "hanoman_member_create",
10548
+ title: "Tambah anggota tim",
10549
+ description: "Menambah orang ke direktori papan Tim. `id` DITURUNKAN dari email (dipangkas + huruf kecil), bukan diacak \u2014 email yang sudah terdaftar menjawab 409 berikut id-nya, bukan membuat baris kedua.",
10550
+ inputSchema: obj({
10551
+ properties: {
10552
+ name: str("Nama yang ditampilkan di kartu."),
10553
+ email: str("Email. Menjadi id anggota sesudah dipangkas & dihurufkecilkan \u2014 dan id itu TAK BISA diubah kemudian."),
10554
+ role: str("Peran, mis. `desainer`. Bebas teks.")
10555
+ },
10556
+ required: ["name", "email"]
10557
+ }),
10558
+ mode: "write",
10559
+ capability: "team:write",
10560
+ samplePath: "/members",
10561
+ sampleMethod: "POST",
10562
+ build: (a) => ({
10563
+ method: "POST",
10564
+ path: "/members",
10565
+ body: { name: String(a.name), email: String(a.email), ...s(a.role) ? { role: s(a.role) } : {} }
10566
+ }),
10567
+ shape: (raw) => shapeMember(raw)
10568
+ },
10569
+ {
10570
+ name: "hanoman_member_update",
10571
+ title: "Ubah anggota tim",
10572
+ description: "Mengubah nama, peran, atau status aktif seorang anggota. `email` TIDAK bisa diubah dan ditolak eksplisit 400: id diturunkan darinya dan sync tak punya operasi rename, jadi id yang berubah meninggalkan baris yatim di setiap mesin lain. Ganti email = hapus lalu buat baru. Menonaktifkan TIDAK melepas kartu-kartunya.",
10573
+ inputSchema: obj({
10574
+ properties: {
10575
+ member: MEMBER_ID,
10576
+ name: str("Nama baru."),
10577
+ role: str("Peran baru." + CLEAR),
10578
+ active: bool("false = nonaktif: tetap terdaftar dan tetap memegang kartunya, hanya turun di daftar.")
10579
+ },
10580
+ required: ["member"]
10581
+ }),
10582
+ mode: "write",
10583
+ capability: "team:write",
10584
+ samplePath: "/members/a@b.id",
10585
+ sampleMethod: "PATCH",
10586
+ build: (a) => {
10587
+ const body = {};
10588
+ if (s(a.name)) body.name = s(a.name);
10589
+ if (typeof a.active === "boolean") body.active = a.active;
10590
+ const role = nullable(a.role);
10591
+ if (role !== void 0) body.role = role;
10592
+ return { method: "PATCH", path: `/members/${enc(String(a.member))}`, body };
10593
+ },
10594
+ shape: (raw) => shapeMember(raw)
10595
+ }
10596
+ ];
10597
+ DESTRUCTIVE = [
10598
+ {
10599
+ name: "hanoman_task_delete",
10600
+ title: "Hapus kartu papan Tim (BERBAHAYA)",
10601
+ description: "BERBAHAYA \u2014 menghapus kartu papan Tim secara permanen di SELURUH mesin yang tersync. Backlog item yang tertaut TIDAK ikut terhapus. Untuk sekadar mengarsipkan, pindahkan kartunya ke kolom `done` lewat hanoman_task_update. Hanya muncul saat tingkat `--danger` menyala.",
10602
+ inputSchema: obj({ properties: { task: TASK_ID }, required: ["task"] }),
10603
+ mode: "danger",
10604
+ capability: "team:write",
10605
+ samplePath: "/tasks/t1",
10606
+ sampleMethod: "DELETE",
10607
+ build: (a) => ({ method: "DELETE", path: `/tasks/${enc(String(a.task))}` }),
10608
+ shape: (raw) => raw
10609
+ },
10610
+ {
10611
+ name: "hanoman_member_delete",
10612
+ title: "Hapus anggota tim (BERBAHAYA)",
10613
+ description: "BERBAHAYA \u2014 menghapus anggota secara permanen di SELURUH mesin yang tersync. Kartu-kartunya TIDAK ikut terhapus: penugasannya dikosongkan (`memberId` jadi null), dan tak ada jejak siapa pemegangnya sebelum itu. Untuk orang yang sekadar berhenti aktif, pakai hanoman_member_update dengan `active: false` \u2014 ia tetap terdaftar dan kartunya tetap bernama. Hanya muncul saat tingkat `--danger` menyala.",
10614
+ inputSchema: obj({ properties: { member: MEMBER_ID }, required: ["member"] }),
10615
+ mode: "danger",
10616
+ capability: "team:write",
10617
+ samplePath: "/members/a@b.id",
10618
+ sampleMethod: "DELETE",
10619
+ build: (a) => ({ method: "DELETE", path: `/members/${enc(String(a.member))}` }),
10620
+ shape: (raw) => raw
10621
+ }
10622
+ ];
10623
+ TEAM_TOOLS = [...TASKS, ...MEMBERS, ...DESTRUCTIVE];
10624
+ }
10625
+ });
10626
+
10627
+ // ../shared/src/mcp-catalog/system.ts
10628
+ var SYSTEM_TOOLS;
10629
+ var init_system = __esm({
10630
+ "../shared/src/mcp-catalog/system.ts"() {
10631
+ "use strict";
10632
+ init_mcp_schema();
10633
+ SYSTEM_TOOLS = [
10634
+ {
10635
+ name: "hanoman_limits",
10636
+ title: "Sisa kuota langganan Claude",
10637
+ description: "Sisa kuota langganan Claude milik mesin ini berikut kapan jendelanya reset. Dibaca realtime dan di-cache 30 detik di server. Dipakai untuk memutuskan APAKAH pekerjaan berat layak dimulai sekarang \u2014 bukan gerbang: hanoman tak pernah menolak membuka sesi karena angka ini. Tak menuntut capability apa pun.",
10638
+ inputSchema: obj({ properties: {} }),
10639
+ mode: "read",
10640
+ capability: null,
10641
+ samplePath: "/limits",
10642
+ sampleMethod: "GET",
10643
+ build: () => ({ method: "GET", path: "/limits" }),
10644
+ shape: (raw) => raw
10645
+ },
10646
+ {
10647
+ name: "hanoman_limits_codex",
10648
+ title: "Sisa kuota Codex",
10649
+ description: "Sisa kuota codex, dibaca dari snapshot `rate_limits` di rollout sesi codex terakhir \u2014 TANPA panggilan jaringan, jadi kesegarannya seumur sesi codex terakhir di mesin ini, bukan realtime. Endpoint terpisah dari hanoman_limits karena sumber dan semantik kesegarannya memang beda. Tak menuntut capability apa pun.",
10650
+ inputSchema: obj({ properties: {} }),
10651
+ mode: "read",
10652
+ capability: null,
10653
+ samplePath: "/limits/codex",
10654
+ sampleMethod: "GET",
10655
+ build: () => ({ method: "GET", path: "/limits/codex" }),
10656
+ shape: (raw) => raw
10657
+ },
10658
+ {
10659
+ name: "hanoman_update_status",
10660
+ title: "Status versi & pembaruan",
10661
+ description: "Versi hanoman yang berjalan, versi terbaru di registry npm, dan apakah instance ini PUNYA supervisor yang bisa memasangnya (`canApply`). Baca-saja: memasang pembaruan me-restart instance dan sengaja tetap tindakan manusia di dashboard \u2014 tak ada tool untuk itu, apa pun tingkat modenya. Tak menuntut capability apa pun.",
10662
+ inputSchema: obj({ properties: {} }),
10663
+ mode: "read",
10664
+ capability: null,
10665
+ samplePath: "/update",
10666
+ sampleMethod: "GET",
10667
+ build: () => ({ method: "GET", path: "/update" }),
10668
+ shape: (raw) => raw
10669
+ },
10670
+ {
10671
+ name: "hanoman_fs_browse",
10672
+ title: "Telusuri folder mesin ini",
10673
+ description: "Sub-folder nyata di MESIN tempat hanoman berjalan, berikut path absolutnya \u2014 dipakai untuk mengisi `repoDir` saat mengikat project ke codebase yang sudah ada (hanoman_project_binding_set), yang tanpa ini hanya bisa ditebak. Hanya direktori, berkas tak ikut; yang berawalan titik disembunyikan. Tanpa `path`, ia mulai dari home. Tak menuntut capability apa pun.",
10674
+ inputSchema: obj({
10675
+ properties: {
10676
+ path: str("Path absolut folder yang dibuka. Kosong = folder home pengguna yang menjalankan hanoman. Folder yang tak terbaca menjawab 400, bukan daftar kosong.")
10677
+ }
10678
+ }),
10679
+ mode: "read",
10680
+ capability: null,
10681
+ samplePath: "/fs/browse",
10682
+ sampleMethod: "GET",
10683
+ build: (a) => ({
10684
+ method: "GET",
10685
+ path: "/fs/browse",
10686
+ ...typeof a.path === "string" && a.path !== "" ? { query: { path: a.path } } : {}
10687
+ }),
10688
+ shape: (raw) => raw
10689
+ }
10690
+ ];
10691
+ }
10692
+ });
10693
+
10317
10694
  // ../shared/src/mcp-catalog/index.ts
10318
10695
  var MCP_TOOLS;
10319
10696
  var init_mcp_catalog = __esm({
@@ -10334,6 +10711,8 @@ var init_mcp_catalog = __esm({
10334
10711
  init_notifications();
10335
10712
  init_support();
10336
10713
  init_lead2();
10714
+ init_team2();
10715
+ init_system();
10337
10716
  MCP_TOOLS = [
10338
10717
  ...ABOUT_TOOLS,
10339
10718
  ...PROJECTS_TOOLS,
@@ -10347,7 +10726,12 @@ var init_mcp_catalog = __esm({
10347
10726
  ...SESSIONS_TOOLS,
10348
10727
  ...NOTIFICATIONS_TOOLS,
10349
10728
  ...SUPPORT_TOOLS,
10350
- ...LEAD_TOOLS
10729
+ ...LEAD_TOOLS,
10730
+ // ADR-0157 · papan Tim (kerja manusia) lalu status instance. Keduanya di ekor daftar dengan
10731
+ // sengaja: urutan di sini = urutan yang dibaca model, dan pekerjaan sehari-hari agen tetap
10732
+ // backlog/sesi/IDE — bukan kartu orang lain.
10733
+ ...TEAM_TOOLS,
10734
+ ...SYSTEM_TOOLS
10351
10735
  ];
10352
10736
  }
10353
10737
  });
@@ -10585,50 +10969,6 @@ var init_presence = __esm({
10585
10969
  }
10586
10970
  });
10587
10971
 
10588
- // ../shared/src/team.ts
10589
- var TASK_STATUSES, zTaskStatus, zEmail, zName, zIso, zCreateMember, zPatchMember, zCreateTask, zPatchTask, ESCALATE_SOURCES, zEscalateTask;
10590
- var init_team = __esm({
10591
- "../shared/src/team.ts"() {
10592
- "use strict";
10593
- init_zod();
10594
- init_enums();
10595
- TASK_STATUSES = ["backlog", "doing", "review", "done"];
10596
- zTaskStatus = external_exports.enum(TASK_STATUSES);
10597
- zEmail = external_exports.string().trim().min(3).max(200).email();
10598
- zName = external_exports.string().trim().min(1).max(120);
10599
- zIso = external_exports.string().datetime({ offset: true });
10600
- zCreateMember = external_exports.object({
10601
- name: zName,
10602
- email: zEmail,
10603
- role: external_exports.string().trim().max(60).nullable().optional()
10604
- });
10605
- zPatchMember = zCreateMember.omit({ email: true }).partial().extend({
10606
- active: external_exports.boolean().optional()
10607
- });
10608
- zCreateTask = external_exports.object({
10609
- title: external_exports.string().trim().min(1).max(300),
10610
- detail: external_exports.string().max(2e4).nullable().optional(),
10611
- projectId: external_exports.string().max(120).nullable().optional(),
10612
- status: zTaskStatus.default("backlog"),
10613
- priority: zPriority.default("sedang"),
10614
- memberId: external_exports.string().max(200).nullable().optional(),
10615
- startDate: zIso.nullable().optional(),
10616
- dueDate: zIso.nullable().optional(),
10617
- order: external_exports.number().finite().optional()
10618
- });
10619
- zPatchTask = zCreateTask.partial();
10620
- ESCALATE_SOURCES = ["brief", "qa", "audit"];
10621
- zEscalateTask = external_exports.object({
10622
- source: external_exports.enum(ESCALATE_SOURCES).default("brief"),
10623
- priority: zPriority.default("sedang"),
10624
- // Dipakai HANYA saat kartunya belum punya project (`nextSpecId` butuh repo, dan repo milik
10625
- // project). Route menolak 400 bila ia menyebut project LAIN — kartu tak boleh berpindah project
10626
- // sebagai efek samping yang tak diminta.
10627
- projectId: external_exports.string().max(120).optional()
10628
- });
10629
- }
10630
- });
10631
-
10632
10972
  // ../shared/src/index.ts
10633
10973
  var init_src = __esm({
10634
10974
  "../shared/src/index.ts"() {
@@ -16897,7 +17237,7 @@ function exactOptional(innerType) {
16897
17237
  innerType
16898
17238
  });
16899
17239
  }
16900
- function nullable(innerType) {
17240
+ function nullable2(innerType) {
16901
17241
  return new ZodNullable2({
16902
17242
  type: "nullable",
16903
17243
  innerType
@@ -17043,10 +17383,10 @@ var init_schemas2 = __esm({
17043
17383
  return exactOptional(this);
17044
17384
  },
17045
17385
  nullable() {
17046
- return nullable(this);
17386
+ return nullable2(this);
17047
17387
  },
17048
17388
  nullish() {
17049
- return optional(nullable(this));
17389
+ return optional(nullable2(this));
17050
17390
  },
17051
17391
  nonoptional(params) {
17052
17392
  return nonoptional(this, params);