hanoman 0.9.28 → 0.9.30

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 (35) hide show
  1. package/README.md +5 -2
  2. package/dist/build-info.json +3 -3
  3. package/dist/cli.js +360 -90
  4. package/dist/server.js +2904 -1418
  5. package/docs/agent-integration.md +100 -6
  6. package/package.json +1 -1
  7. package/prisma/migrations/20261014130000_cron_report/migration.sql +19 -0
  8. package/prisma/schema.prisma +25 -0
  9. package/scripts/vps/provision.sh +26 -3
  10. package/web/assets/{DalangHanomanScreen-C3UMPHFg.js → DalangHanomanScreen-Fd7_DcSP.js} +1 -1
  11. package/web/assets/{DocPreviewModal-Bp5stb4M.js → DocPreviewModal-SMRN2K98.js} +1 -1
  12. package/web/assets/{DocsWorkspace-C9yFxK4D.js → DocsWorkspace-pxj0N6QW.js} +1 -1
  13. package/web/assets/{IdeScreen-CRFRAP6E.js → IdeScreen-Cr9Vqdrc.js} +1 -1
  14. package/web/assets/LeadScreen-CQXpJy0y.js +1 -0
  15. package/web/assets/{ReviewScreen-CMHOlmgX.js → ReviewScreen-B7NNEjxk.js} +1 -1
  16. package/web/assets/SchedulerScreen-D3rPdS-F.js +1 -0
  17. package/web/assets/SettingsScreen-Bx13PWKQ.js +62 -0
  18. package/web/assets/{TeamScreen-D4tA34Mj.js → TeamScreen-BBAsYLpT.js} +1 -1
  19. package/web/assets/TerminalScreen-DpVp4h1n.js +2 -0
  20. package/web/assets/{TriageScreen-B8ZCexaX.js → TriageScreen-wAPnttRe.js} +1 -1
  21. package/web/assets/{VpsScreen-BCrLfZh7.js → VpsScreen-DeQVx9Jy.js} +2 -2
  22. package/web/assets/fields-qnBoIMR_.js +1 -0
  23. package/web/assets/index-BQw6xQI4.js +1012 -0
  24. package/web/assets/{index-BqAP-VDq.css → index-C3KwOJxI.css} +2 -2
  25. package/web/assets/{live-DuBdI0MZ.js → live-CONO0GTu.js} +1 -1
  26. package/web/assets/{sched-lead-shared-QqbtjoVv.js → sched-lead-shared-CDR0pOqs.js} +1 -1
  27. package/web/assets/{scheduler-CQt-VP9-.css → scheduler-D64RlGvZ.css} +1 -1
  28. package/web/assets/settings-rebase-CpaFw0Tm.js +1 -0
  29. package/web/index.html +2 -2
  30. package/web/assets/LeadScreen-DfVUawoK.js +0 -1
  31. package/web/assets/SchedulerScreen-CK5QvX5c.js +0 -1
  32. package/web/assets/SettingsScreen-D7P5JgjU.js +0 -62
  33. package/web/assets/TerminalScreen-CKySL63X.js +0 -2
  34. package/web/assets/index-BRR3JL_o.js +0 -1012
  35. package/web/assets/settings-rebase-Cbh-JGJ-.js +0 -1
package/dist/cli.js CHANGED
@@ -582,11 +582,11 @@ function datetimeRegex(args) {
582
582
  regex = `${regex}(${opts.join("|")})`;
583
583
  return new RegExp(`^${regex}$`);
584
584
  }
585
- function isValidIP(ip, version3) {
586
- if ((version3 === "v4" || !version3) && ipv4Regex.test(ip)) {
585
+ function isValidIP(ip, version2) {
586
+ if ((version2 === "v4" || !version2) && ipv4Regex.test(ip)) {
587
587
  return true;
588
588
  }
589
- if ((version3 === "v6" || !version3) && ipv6Regex.test(ip)) {
589
+ if ((version2 === "v6" || !version2) && ipv6Regex.test(ip)) {
590
590
  return true;
591
591
  }
592
592
  return false;
@@ -613,11 +613,11 @@ function isValidJWT(jwt, alg) {
613
613
  return false;
614
614
  }
615
615
  }
616
- function isValidCidr(ip, version3) {
617
- if ((version3 === "v4" || !version3) && ipv4CidrRegex.test(ip)) {
616
+ function isValidCidr(ip, version2) {
617
+ if ((version2 === "v4" || !version2) && ipv4CidrRegex.test(ip)) {
618
618
  return true;
619
619
  }
620
- if ((version3 === "v6" || !version3) && ipv6CidrRegex.test(ip)) {
620
+ if ((version2 === "v6" || !version2) && ipv6CidrRegex.test(ip)) {
621
621
  return true;
622
622
  }
623
623
  return false;
@@ -4133,7 +4133,7 @@ var init_enums = __esm({
4133
4133
  zDocStatus = external_exports.enum(["ok", "drift", "broken"]);
4134
4134
  zPriority = external_exports.enum(["tinggi", "sedang", "rendah"]);
4135
4135
  zProjectKind = external_exports.enum(["from-scratch", "existing"]);
4136
- zAgent = external_exports.enum(["claude", "codex"]);
4136
+ zAgent = external_exports.enum(["claude", "codex", "antigravity"]);
4137
4137
  zSeverity = external_exports.enum(["critical", "major", "minor"]);
4138
4138
  zTicketCategory = external_exports.enum(["bug", "fitur", "pertanyaan", "lainnya"]);
4139
4139
  zTicketStatus = external_exports.enum(["new", "accepted", "rejected"]);
@@ -4210,6 +4210,7 @@ var init_method_catalog = __esm({
4210
4210
  exitSkills: [VERIFICATION_GATE],
4211
4211
  requires: ["superpowers"],
4212
4212
  install: {
4213
+ antigravity: [],
4213
4214
  claude: [
4214
4215
  "claude plugin marketplace add obra/superpowers-marketplace",
4215
4216
  "claude plugin install superpowers@superpowers-marketplace"
@@ -4244,6 +4245,7 @@ var init_method_catalog = __esm({
4244
4245
  // dari sana (INVARIAN 2). codex belum punya plugin native mattpocock — jalur resminya
4245
4246
  // `npx skills`, dan ia INTERAKTIF; itu justru alasan pemasangan hidup di pane yang ditonton.
4246
4247
  install: {
4248
+ antigravity: [],
4247
4249
  claude: [
4248
4250
  "claude plugin install mattpocock-skills",
4249
4251
  "claude plugin marketplace add obra/superpowers-marketplace",
@@ -4280,6 +4282,7 @@ var init_method_catalog = __esm({
4280
4282
  requires: ["agent-skills", "superpowers"],
4281
4283
  // Manifest upstream: marketplace Claude = addy-agent-skills, Codex = agent-skills.
4282
4284
  install: {
4285
+ antigravity: [],
4283
4286
  claude: [
4284
4287
  "claude plugin marketplace add addyosmani/agent-skills",
4285
4288
  "claude plugin install agent-skills@addy-agent-skills",
@@ -4314,15 +4317,18 @@ function methodStatus(m, agent, installed) {
4314
4317
  method: m.id,
4315
4318
  label: m.label,
4316
4319
  agent,
4317
- ready: missingPackages.length === 0 && missingSkills.length === 0,
4320
+ ...agent === "antigravity" ? { available: false, availabilityReason: ANTIGRAVITY_METHOD_UNAVAILABLE_REASON } : {},
4321
+ ready: agent !== "antigravity" && missingPackages.length === 0 && missingSkills.length === 0,
4318
4322
  missingPackages,
4319
4323
  missingSkills,
4320
4324
  install: [...m.install[agent]]
4321
4325
  };
4322
4326
  }
4327
+ var ANTIGRAVITY_METHOD_UNAVAILABLE_REASON;
4323
4328
  var init_method_status = __esm({
4324
4329
  "../shared/src/method-status.ts"() {
4325
4330
  "use strict";
4331
+ ANTIGRAVITY_METHOD_UNAVAILABLE_REASON = "Installer metode Antigravity belum terverifikasi dari upstream";
4326
4332
  }
4327
4333
  });
4328
4334
 
@@ -4342,8 +4348,29 @@ var init_agent_engine = __esm({
4342
4348
  }
4343
4349
  });
4344
4350
 
4351
+ // ../shared/src/antigravity.ts
4352
+ function isAntigravityChildTier(value) {
4353
+ return ANTIGRAVITY_CHILD_TIERS.some((tier) => tier === value);
4354
+ }
4355
+ var ANTIGRAVITY_CHILD_TIERS, BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS, ANTIGRAVITY_MODELS;
4356
+ var init_antigravity = __esm({
4357
+ "../shared/src/antigravity.ts"() {
4358
+ "use strict";
4359
+ ANTIGRAVITY_CHILD_TIERS = ["inherit", "flash", "pro"];
4360
+ BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS = {
4361
+ model: "gemini-3.8-flash-high",
4362
+ effort: "high"
4363
+ };
4364
+ ANTIGRAVITY_MODELS = [{
4365
+ id: BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS.model,
4366
+ label: "Gemini 3.8 Flash High",
4367
+ efforts: [BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS.effort]
4368
+ }];
4369
+ }
4370
+ });
4371
+
4345
4372
  // ../shared/src/telegram.ts
4346
- var zTelegramSettings, TELEGRAM_DEFAULTS, zTelegramReadiness, zTelegramGatewayStatus, zTelegramMemoryRecord, zTelegramChatContext, TELEGRAM_REPLY_KINDS, zTelegramReplyKind, zTelegramConfirmationRequest, zTelegramReplyInput, zTelegramAuditRecord, zTerminalSteerInput;
4373
+ var zTelegramSettings, TELEGRAM_DEFAULTS, zTelegramReadiness, zTelegramGatewayStatus, zTelegramMemoryRecord, zTelegramChatContext, TELEGRAM_REPLY_KINDS, zTelegramReplyKind, zTelegramConfirmationRequest, zTelegramReplyInput, zTelegramAuditRecord, zTerminalSteerInput, SESSION_NAME_MAX, zTerminalRenameInput;
4347
4374
  var init_telegram = __esm({
4348
4375
  "../shared/src/telegram.ts"() {
4349
4376
  "use strict";
@@ -4440,6 +4467,8 @@ var init_telegram = __esm({
4440
4467
  zTerminalSteerInput = external_exports.object({
4441
4468
  text: external_exports.string().trim().min(1).max(16e3)
4442
4469
  });
4470
+ SESSION_NAME_MAX = 80;
4471
+ zTerminalRenameInput = external_exports.object({ name: external_exports.string().max(SESSION_NAME_MAX * 4) });
4443
4472
  }
4444
4473
  });
4445
4474
 
@@ -4702,10 +4731,20 @@ var init_runtime_defaults = __esm({
4702
4731
  model: zRuntimeDefaultState.default("seeded"),
4703
4732
  effort: zRuntimeDefaultState.default("seeded")
4704
4733
  }).default({}),
4734
+ antigravity: external_exports.object({
4735
+ model: zRuntimeDefaultState.default("seeded"),
4736
+ effort: zRuntimeDefaultState.default("seeded")
4737
+ }).default({}),
4705
4738
  orchestration: external_exports.record(external_exports.string(), zRuntimeDefaultState).default({})
4706
4739
  });
4707
4740
  cell = (model, effort) => ({ model, effort });
4708
- flow = (claude, codex, enabled = true) => ({ enabled, executeMode: "inline", claude, codex });
4741
+ flow = (claude, codex, enabled = true) => ({
4742
+ enabled,
4743
+ executeMode: "inline",
4744
+ claude,
4745
+ codex,
4746
+ antigravity: Object.fromEntries(Object.keys(claude).map((phase) => [phase, { model: "inherit", effort: null }]))
4747
+ });
4709
4748
  BUILTIN_ORCHESTRATION_DEFAULTS = {
4710
4749
  feature: flow(
4711
4750
  {
@@ -4813,7 +4852,7 @@ var init_runtime_defaults = __esm({
4813
4852
  };
4814
4853
  seededFlows = Object.fromEntries(ORCHESTRATION_FLOWS.flatMap((flow2) => [
4815
4854
  [`${flow2}.enabled`, "seeded"],
4816
- ...["claude", "codex"].flatMap((runtime) => FLOW_PHASES[flow2].flatMap((phase) => [
4855
+ ...["claude", "codex", "antigravity"].flatMap((runtime) => FLOW_PHASES[flow2].flatMap((phase) => [
4817
4856
  [`${flow2}.${runtime}.${phase}.model`, "seeded"],
4818
4857
  [`${flow2}.${runtime}.${phase}.effort`, "seeded"]
4819
4858
  ]))
@@ -4822,6 +4861,7 @@ var init_runtime_defaults = __esm({
4822
4861
  version: RUNTIME_DEFAULTS_VERSION,
4823
4862
  claude: { model: "seeded", effort: "seeded" },
4824
4863
  codex: { model: "seeded", effort: "seeded" },
4864
+ antigravity: { model: "seeded", effort: "seeded" },
4825
4865
  orchestration: seededFlows
4826
4866
  };
4827
4867
  }
@@ -4837,11 +4877,12 @@ function cmpVersion(a, b) {
4837
4877
  }
4838
4878
  return 0;
4839
4879
  }
4840
- var zProject, zBriefPayload, zQaPayload, zGoalPayload, zSpecBlocker, zSourceChange, zManualDone, zSpec, zSpecListItem, zSpecSlim, NOTIFY_SOUNDS, zCodex, CODEX_DEFAULTS, zSourceCommon, zScheduler, SCHEDULER_DEFAULTS, zGoal, GOAL_DEFAULTS, zConflict, CONFLICT_DEFAULTS, zLeadEngine, zLead, LEAD_DEFAULTS, zPortalChat, PORTAL_CHAT_DEFAULTS, zPhaseCell, PHASE_OVERRIDE_LIMITS, zPhaseOverride, zPhaseOverrides, zFlowOrchestration, zOrchestration, ORCHESTRATION_DEFAULTS, zSetting, zNotification, zDocFile, zDeviceTokenView;
4880
+ var zProject, zBriefPayload, zQaPayload, zGoalPayload, zSpecBlocker, zSourceChange, zManualDone, zSpec, zSpecListItem, zSpecSlim, NOTIFY_SOUNDS, zCodex, CODEX_DEFAULTS, zAntigravity, ANTIGRAVITY_DEFAULTS, zSourceCommon, zScheduler, SCHEDULER_DEFAULTS, zGoal, GOAL_DEFAULTS, zConflict, CONFLICT_DEFAULTS, zLeadEngine, zLead, LEAD_DEFAULTS, zPortalChat, PORTAL_CHAT_DEFAULTS, zPhaseCell, zAntigravityPhaseCell, PHASE_OVERRIDE_LIMITS, zPhaseOverride, zPhaseOverrides, zFlowOrchestration, zOrchestration, ORCHESTRATION_DEFAULTS, zSetting, zNotification, zDocFile, zDeviceTokenView;
4841
4881
  var init_entities = __esm({
4842
4882
  "../shared/src/entities.ts"() {
4843
4883
  "use strict";
4844
4884
  init_zod();
4885
+ init_antigravity();
4845
4886
  init_enums();
4846
4887
  init_telegram();
4847
4888
  init_agent_engine();
@@ -4972,6 +5013,11 @@ var init_entities = __esm({
4972
5013
  effort: external_exports.string().default("medium")
4973
5014
  });
4974
5015
  CODEX_DEFAULTS = zCodex.parse({});
5016
+ zAntigravity = external_exports.object({
5017
+ model: external_exports.string().default(BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS.model),
5018
+ effort: external_exports.string().default(BUILTIN_ANTIGRAVITY_RUNTIME_DEFAULTS.effort)
5019
+ });
5020
+ ANTIGRAVITY_DEFAULTS = zAntigravity.parse({});
4975
5021
  zSourceCommon = { enabled: external_exports.boolean().default(false) };
4976
5022
  zScheduler = external_exports.object({
4977
5023
  enabled: external_exports.boolean().default(false),
@@ -5062,10 +5108,14 @@ var init_entities = __esm({
5062
5108
  model: external_exports.string().nullable().default(null),
5063
5109
  effort: external_exports.string().nullable().default(null)
5064
5110
  });
5111
+ zAntigravityPhaseCell = external_exports.object({
5112
+ model: external_exports.enum(ANTIGRAVITY_CHILD_TIERS).nullable().default(null),
5113
+ effort: external_exports.null().default(null)
5114
+ });
5065
5115
  PHASE_OVERRIDE_LIMITS = { model: 200, effort: 64, phase: 64, phases: 32 };
5066
5116
  zPhaseOverride = external_exports.object({
5067
- model: external_exports.string().min(1).max(PHASE_OVERRIDE_LIMITS.model).optional(),
5068
- effort: external_exports.string().min(1).max(PHASE_OVERRIDE_LIMITS.effort).optional()
5117
+ model: external_exports.string().min(1).max(PHASE_OVERRIDE_LIMITS.model).nullable().optional(),
5118
+ effort: external_exports.string().min(1).max(PHASE_OVERRIDE_LIMITS.effort).nullable().optional()
5069
5119
  });
5070
5120
  zPhaseOverrides = external_exports.record(external_exports.string().min(1).max(PHASE_OVERRIDE_LIMITS.phase), zPhaseOverride).refine(
5071
5121
  (o) => Object.keys(o).length <= PHASE_OVERRIDE_LIMITS.phases,
@@ -5076,7 +5126,8 @@ var init_entities = __esm({
5076
5126
  // Amandemen ADR-0170 P2 · lenient: nilai asing jatuh ke `inline`, bukan Setting gagal parse.
5077
5127
  executeMode: external_exports.enum(["inline", "subagent"]).catch("inline").default("inline"),
5078
5128
  claude: external_exports.record(external_exports.string(), zPhaseCell).default({}),
5079
- codex: external_exports.record(external_exports.string(), zPhaseCell).default({})
5129
+ codex: external_exports.record(external_exports.string(), zPhaseCell).default({}),
5130
+ antigravity: external_exports.record(external_exports.string(), zPhaseCell).default({})
5080
5131
  });
5081
5132
  zOrchestration = external_exports.object({
5082
5133
  feature: zFlowOrchestration.default({}),
@@ -5114,6 +5165,7 @@ var init_entities = __esm({
5114
5165
  // SPEC-338 · ADR-0074 · mesin sesi default
5115
5166
  codex: zCodex.default(CODEX_DEFAULTS),
5116
5167
  // SPEC-338 · ADR-0074 · model/effort codex
5168
+ antigravity: zAntigravity.default(ANTIGRAVITY_DEFAULTS),
5117
5169
  verifyScope: zVerifyScope.default("changed"),
5118
5170
  // SPEC-376 · ADR-0080 · scope verifikasi sesi
5119
5171
  // SPEC-734 · ADR-0113 · metode workflow default. LENIENT (`z.string()`, bukan `z.enum`):
@@ -5189,14 +5241,15 @@ var init_entities = __esm({
5189
5241
  });
5190
5242
 
5191
5243
  // ../shared/src/orchestration-plan.ts
5192
- function codexNativeAgentsSupported(version3) {
5193
- const parsed = version3 ? /(\d+)\.(\d+)\.(\d+)/.exec(version3)?.[0] : null;
5244
+ function codexNativeAgentsSupported(version2) {
5245
+ const parsed = version2 ? /(\d+)\.(\d+)\.(\d+)/.exec(version2)?.[0] : null;
5194
5246
  return parsed ? cmpVersion(parsed, CODEX_NATIVE_AGENTS_MIN_CLIENT) >= 0 : false;
5195
5247
  }
5196
5248
  var CODEX_NATIVE_AGENTS_MIN_CLIENT;
5197
5249
  var init_orchestration_plan = __esm({
5198
5250
  "../shared/src/orchestration-plan.ts"() {
5199
5251
  "use strict";
5252
+ init_antigravity();
5200
5253
  init_entities();
5201
5254
  init_orchestration();
5202
5255
  CODEX_NATIVE_AGENTS_MIN_CLIENT = "0.151.0";
@@ -5358,6 +5411,7 @@ var init_agent = __esm({
5358
5411
 
5359
5412
  // ../shared/src/custom-agent.ts
5360
5413
  function validateCreateWorkspacePolicy(value, ctx) {
5414
+ validateAntigravityChild(value, ctx);
5361
5415
  if (value.workspacePolicy === "isolated-worktree" && value.runtime !== "claude") {
5362
5416
  ctx.addIssue({
5363
5417
  code: external_exports.ZodIssueCode.custom,
@@ -5366,13 +5420,23 @@ function validateCreateWorkspacePolicy(value, ctx) {
5366
5420
  });
5367
5421
  }
5368
5422
  }
5423
+ function validateAntigravityChild(value, ctx) {
5424
+ if (value.runtime !== "antigravity") return;
5425
+ if (value.model != null && !isAntigravityChildTier(value.model)) {
5426
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["model"], message: "Antigravity child memakai tier inherit, flash, atau pro" });
5427
+ }
5428
+ if (value.effort != null) {
5429
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["effort"], message: "Antigravity child tidak mendukung effort independen" });
5430
+ }
5431
+ }
5369
5432
  var AGENT_RUNTIMES, zAgentRuntime, AGENT_ACTIVATIONS, zAgentActivation, zAgentEffort, AGENT_WORKSPACE_POLICIES, zAgentWorkspacePolicy, AGENT_NAME_RE, DEFAULT_AGENT_TOOLS, zCustomAgent, zCreateCustomAgentFields, zCreateCustomAgent, zUpdateCustomAgent;
5370
5433
  var init_custom_agent = __esm({
5371
5434
  "../shared/src/custom-agent.ts"() {
5372
5435
  "use strict";
5373
5436
  init_zod();
5437
+ init_antigravity();
5374
5438
  init_orchestration();
5375
- AGENT_RUNTIMES = ["claude", "codex"];
5439
+ AGENT_RUNTIMES = ["claude", "codex", "antigravity"];
5376
5440
  zAgentRuntime = external_exports.enum(AGENT_RUNTIMES);
5377
5441
  AGENT_ACTIVATIONS = ["always", "smart"];
5378
5442
  zAgentActivation = external_exports.enum(AGENT_ACTIVATIONS);
@@ -5430,6 +5494,7 @@ var init_custom_agent = __esm({
5430
5494
  });
5431
5495
  zCreateCustomAgent = zCreateCustomAgentFields.superRefine(validateCreateWorkspacePolicy);
5432
5496
  zUpdateCustomAgent = zCreateCustomAgentFields.omit({ name: true, projectId: true }).partial().superRefine((value, ctx) => {
5497
+ validateAntigravityChild(value, ctx);
5433
5498
  if (value.workspacePolicy === "isolated-worktree" && value.runtime !== void 0 && value.runtime !== "claude") {
5434
5499
  ctx.addIssue({
5435
5500
  code: external_exports.ZodIssueCode.custom,
@@ -6448,6 +6513,7 @@ var BUILTIN_AGENT_TOOLS;
6448
6513
  var init_agent_catalog = __esm({
6449
6514
  "../shared/src/agent-catalog.ts"() {
6450
6515
  "use strict";
6516
+ init_antigravity();
6451
6517
  init_custom_agent();
6452
6518
  init_entities();
6453
6519
  BUILTIN_AGENT_TOOLS = DEFAULT_AGENT_TOOLS.map((id) => ({
@@ -7236,6 +7302,7 @@ var init_dto = __esm({
7236
7302
  "agent-image",
7237
7303
  "claude",
7238
7304
  "codex",
7305
+ "antigravity",
7239
7306
  "gh"
7240
7307
  ];
7241
7308
  zProvision = external_exports.object({
@@ -7484,6 +7551,7 @@ var init_api = __esm({
7484
7551
  limits: `${API}/limits`,
7485
7552
  // SPEC-339 · versi codex CLI (peringatan lunak model GPT-5.6).
7486
7553
  codexVersion: `${API}/codex/version`,
7554
+ antigravityVersion: `${API}/antigravity/version`,
7487
7555
  // SPEC-739 · ADR-0114 · kesiapan skill metode per agen. LOCAL-only, diturunkan live dari disk.
7488
7556
  methodStatus: `${API}/methods/status`,
7489
7557
  // SPEC-489 · panduan AI agent — markdown MENTAH & PUBLIC (tanpa auth). Satu definisi URL untuk
@@ -7651,6 +7719,9 @@ var init_api = __esm({
7651
7719
  schedulerCron: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}`,
7652
7720
  schedulerCronRunNow: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}/run`,
7653
7721
  schedulerCronRuns: (id) => `${API}/scheduler/crons/${encodeURIComponent(id)}/runs`,
7722
+ // ADR-0222 · laporan run cron (baca-saja).
7723
+ schedulerReports: `${API}/scheduler/reports`,
7724
+ schedulerReport: (id) => `${API}/scheduler/reports/${encodeURIComponent(id)}`,
7654
7725
  // SPEC-409 · ADR-0091 · hanoman-lead. Semua HTTP (polling) — tak ada kanal WS baru (AC-26).
7655
7726
  leadConfig: `${API}/lead/config`,
7656
7727
  leadStatus: `${API}/lead/status`,
@@ -8006,6 +8077,17 @@ var init_config_registry = __esm({
8006
8077
  { key: "HANOMAN_CLAUDE_BIN", group: "claude", label: "Biner claude", kind: "path", apply: "new-session", category: "knob", example: "/opt/homebrew/bin/claude", default: "claude" },
8007
8078
  // codex (SPEC-338 · ADR-0074)
8008
8079
  { key: "HANOMAN_CODEX_BIN", group: "claude", label: "Biner codex", kind: "path", apply: "new-session", category: "knob", example: "/opt/homebrew/bin/codex", default: "codex" },
8080
+ {
8081
+ key: "HANOMAN_ANTIGRAVITY_BIN",
8082
+ group: "claude",
8083
+ label: "Biner Antigravity",
8084
+ kind: "path",
8085
+ apply: "new-session",
8086
+ category: "knob",
8087
+ example: "/opt/homebrew/bin/agy",
8088
+ default: "agy",
8089
+ help: "Executable Antigravity CLI, bukan shell command atau daftar flag."
8090
+ },
8009
8091
  {
8010
8092
  key: "CLAUDE_CONFIG_DIR",
8011
8093
  group: "claude",
@@ -8096,6 +8178,17 @@ var init_config_registry = __esm({
8096
8178
  // runtime
8097
8179
  { key: "HANOMAN_EVENTS_TICK_MS", group: "runtime", label: "Interval events (ms)", kind: "int", apply: "live", category: "knob", example: "1000", default: "1000", min: 100 },
8098
8180
  { key: "HANOMAN_UPDATE_FETCH", group: "runtime", label: "Deteksi update saat boot", kind: "bool", apply: "live", category: "knob", default: "1" },
8181
+ // ADR-0224 · limit Antigravity membaca token agy di Keychain dan memanggil Cloud Code API Google.
8182
+ {
8183
+ key: "HANOMAN_ANTIGRAVITY_LIMITS_FETCH",
8184
+ group: "runtime",
8185
+ label: "Baca limit Antigravity",
8186
+ kind: "bool",
8187
+ apply: "live",
8188
+ category: "knob",
8189
+ default: "1",
8190
+ help: "Membaca token agy di Keychain macOS lalu memanggil API kuota Google (endpoint internal, tak terdokumentasi). Matikan bila tak ingin hanoman menyentuh kredensial agy."
8191
+ },
8099
8192
  // SPEC-398 · ADR-0087 · deteksi update kini membandingkan semver dengan registry npm, bukan
8100
8193
  // menghitung commit di repo git (HANOMAN_REPO_ROOT dicabut bersama jalur git itu).
8101
8194
  {
@@ -10378,7 +10471,7 @@ var init_settings = __esm({
10378
10471
  {
10379
10472
  name: "hanoman_settings_get",
10380
10473
  title: "Baca setelan instance",
10381
- description: "Seluruh setelan instance: agen & model default, effort, notifikasi, mode goal, verifikasi, dan blok Telegram. Panggil ini sebelum hanoman_settings_set \u2014 setelan disimpan sebagai satu blok.",
10474
+ description: "Seluruh setelan instance: runtime Claude/Codex/Antigravity, model parent, effort, tier child native Antigravity, notifikasi, mode goal, verifikasi, dan blok Telegram. Panggil ini sebelum hanoman_settings_set \u2014 setelan disimpan sebagai satu blok.",
10382
10475
  inputSchema: obj({ properties: {} }),
10383
10476
  mode: "read",
10384
10477
  capability: "settings:read",
@@ -10390,7 +10483,7 @@ var init_settings = __esm({
10390
10483
  {
10391
10484
  name: "hanoman_settings_set",
10392
10485
  title: "Simpan setelan instance",
10393
- description: "Menyimpan setelan instance. MENGGANTI blok penuh \u2014 kirim hasil hanoman_settings_get yang sudah diubah, bukan potongan. Panggil hanoman_settings_get TEPAT sebelum tool ini (jangan memakai hasil lama) dan ubah HANYA field yang dimaksud: setiap model/effort/sel orkestrasi yang berbeda dari nilai tersimpan ditandai milik operator dan tak lagi diperbarui default bawaan saat update. Setelan ini berlaku untuk SETIAP sesi baru di seluruh workspace. Menyentuh blok Telegram akan memuat ulang gateway.",
10486
+ description: "Menyimpan setelan instance. MENGGANTI blok penuh \u2014 kirim hasil hanoman_settings_get yang sudah diubah, bukan potongan. Panggil hanoman_settings_get TEPAT sebelum tool ini (jangan memakai hasil lama) dan ubah HANYA field yang dimaksud: setiap model/effort/sel orkestrasi yang berbeda dari nilai tersimpan ditandai milik operator dan tak lagi diperbarui default bawaan saat update. Parent Antigravity memakai blok antigravity.model/effort; sel orchestration.<flow>.antigravity hanya menerima tier inherit|flash|pro atau model null dan effort null, bukan slug parent. Phase override per sesi menerima model/effort null; model null mewarisi tier native, effort tetap unknown, bukan effort parent. Blok runtime Antigravity yang hilang dari klien lama dipertahankan. Setelan ini berlaku untuk SETIAP sesi baru di seluruh workspace. Menyentuh blok Telegram akan memuat ulang gateway.",
10394
10487
  inputSchema: obj({ properties: { settings: WHOLE_BLOCK("setelan") }, required: ["settings"] }),
10395
10488
  mode: "write",
10396
10489
  capability: "settings:write",
@@ -10543,6 +10636,7 @@ var init_agents = __esm({
10543
10636
  "../shared/src/mcp-catalog/agents.ts"() {
10544
10637
  "use strict";
10545
10638
  init_mcp_schema();
10639
+ init_custom_agent();
10546
10640
  init_helpers();
10547
10641
  AGENTS_TOOLS = [
10548
10642
  {
@@ -10564,13 +10658,16 @@ var init_agents = __esm({
10564
10658
  title: "Daftar custom agent",
10565
10659
  description: "Persona custom yang aktif. Tanpa `project` hanya yang global; dengan `project` ia menggabung global + milik project, dan nama yang ditimpa project muncul SEKALI dengan versi project yang menang.",
10566
10660
  inputSchema: obj({
10567
- properties: { project: str("Id project. Kosongkan untuk hanya persona global.") }
10661
+ properties: {
10662
+ project: str("Id project. Kosongkan untuk hanya persona global."),
10663
+ runtime: enumStr(AGENT_RUNTIMES, "Runtime parent untuk availability dan alasan ketidaktersediaan persona.")
10664
+ }
10568
10665
  }),
10569
10666
  mode: "read",
10570
10667
  capability: "agents:read",
10571
10668
  samplePath: "/custom-agents",
10572
10669
  sampleMethod: "GET",
10573
- build: (a) => ({ method: "GET", path: "/custom-agents", query: query({ projectId: s(a.project) }) }),
10670
+ build: (a) => ({ method: "GET", path: "/custom-agents", query: query({ projectId: s(a.project), runtime: s(a.runtime) }) }),
10574
10671
  shape: (raw) => raw
10575
10672
  },
10576
10673
  {
@@ -10584,9 +10681,9 @@ var init_agents = __esm({
10584
10681
  instructions: str("Instruksi persona (1\u201320.000 karakter). Inilah yang dibaca agen."),
10585
10682
  project: str("Id project. Kosongkan untuk persona GLOBAL yang berlaku di semua project."),
10586
10683
  tools: strArray("Tool yang boleh dipakai persona ini. Harus ada di hanoman_agents_catalog. Kosongkan untuk mewarisi."),
10587
- model: str("Model. Harus sah untuk `runtime` yang dipilih."),
10684
+ model: str("Model child. Antigravity hanya tier inherit|flash|pro; effort independen unavailable. Harus sah untuk `runtime` yang dipilih."),
10588
10685
  mentions: strArray("Nama persona lain yang boleh dipanggil."),
10589
- runtime: enumStr(["claude", "codex"], "Penyaring mesin sesi. Kosongkan untuk mengikuti sesi induk."),
10686
+ runtime: enumStr(AGENT_RUNTIMES, "Penyaring mesin sesi. Kosongkan untuk mengikuti sesi induk."),
10590
10687
  enabled: bool("Aktif atau tidak. Default aktif.")
10591
10688
  },
10592
10689
  required: ["name", "description", "instructions"]
@@ -10619,9 +10716,9 @@ var init_agents = __esm({
10619
10716
  description: str("Deskripsi baru."),
10620
10717
  instructions: str("Instruksi baru."),
10621
10718
  tools: strArray("Daftar tool baru."),
10622
- model: str("Model baru."),
10719
+ model: str("Model child baru. Antigravity hanya tier inherit|flash|pro; effort independen unavailable."),
10623
10720
  mentions: strArray("Daftar mention baru."),
10624
- runtime: enumStr(["claude", "codex"], "Penyaring mesin sesi."),
10721
+ runtime: enumStr(AGENT_RUNTIMES, "Penyaring mesin sesi."),
10625
10722
  enabled: bool("Aktif atau tidak.")
10626
10723
  },
10627
10724
  required: ["agent"]
@@ -10666,7 +10763,7 @@ var init_skills = __esm({
10666
10763
  {
10667
10764
  name: "hanoman_skills_list",
10668
10765
  title: "Daftar skill",
10669
- description: "Skill dari semua sumber: global hanoman ($HANOMAN_HOME/skills, disuntik ke setiap sesi), user (~/.claude|~/.codex|~/.agents), plugin (baca-saja), dan per project (.claude/.agents/.codex/skills + folder lain berisi SKILL.md). Tanpa `project`: global + satu grup per project. Dengan `project`: global (bertanda shadowedBy bila ditimpa) + skill project itu.",
10766
+ description: "Skill dari semua sumber: global hanoman ($HANOMAN_HOME/skills, disuntik ke setiap sesi), user (~/.claude|~/.codex|~/.agents|~/.gemini/antigravity-cli), plugin (baca-saja), dan per project (.claude/.agents/.codex/skills + folder lain berisi SKILL.md). Tanpa `project`: global + satu grup per project. Dengan `project`: global (bertanda shadowedBy bila ditimpa) + skill project itu.",
10670
10767
  inputSchema: obj({ properties: { project: str("Id project. Kosongkan untuk semua grup.") } }),
10671
10768
  mode: "read",
10672
10769
  capability: "skills:read",
@@ -10724,7 +10821,7 @@ var init_skills = __esm({
10724
10821
  layer: enumStr(["hanoman", "user", "project"], "Lapis tujuan."),
10725
10822
  name: str("Nama skill (kebab-case)."),
10726
10823
  description: str('Deskripsi \u2014 diawali kapan skill dipakai, mis. "Use when \u2026".'),
10727
- source: enumStr([".claude", ".agents", ".codex"], "Sumber untuk lapis user/project. Default .claude."),
10824
+ source: enumStr([".claude", ".agents", ".codex", ".gemini/antigravity-cli"], "Sumber untuk lapis user/project. .gemini/antigravity-cli hanya user. Default .claude."),
10728
10825
  project: str("Id project (wajib untuk layer project).")
10729
10826
  },
10730
10827
  required: ["layer", "name", "description"]
@@ -10743,13 +10840,13 @@ var init_skills = __esm({
10743
10840
  {
10744
10841
  name: "hanoman_skill_fork",
10745
10842
  title: "Fork skill",
10746
- description: "Menyalin skill mana pun (termasuk plugin yang baca-saja) ke global hanoman atau ke project, supaya bisa disunting. `name` default = nama asal.",
10843
+ description: "Menyalin skill mana pun (termasuk plugin yang baca-saja) ke global hanoman, user, atau project, supaya bisa disunting. `name` default = nama asal.",
10747
10844
  inputSchema: obj({
10748
10845
  properties: {
10749
10846
  key: str("Key skill sumber."),
10750
- layer: enumStr(["hanoman", "project"], "Tujuan. Default hanoman."),
10847
+ layer: enumStr(["hanoman", "user", "project"], "Tujuan. Default hanoman."),
10751
10848
  project: str("Id project (wajib untuk layer project)."),
10752
- source: enumStr([".claude", ".agents", ".codex"], "Sumber tujuan untuk layer project."),
10849
+ source: enumStr([".claude", ".agents", ".codex", ".gemini/antigravity-cli"], "Sumber tujuan user/project; .gemini/antigravity-cli hanya user."),
10753
10850
  name: str("Nama baru (opsional).")
10754
10851
  },
10755
10852
  required: ["key"]
@@ -11309,6 +11406,7 @@ var CORE3, MORE2, SESSIONS_TOOLS;
11309
11406
  var init_sessions = __esm({
11310
11407
  "../shared/src/mcp-catalog/sessions.ts"() {
11311
11408
  "use strict";
11409
+ init_entities();
11312
11410
  init_mcp_schema();
11313
11411
  init_mcp_shape();
11314
11412
  init_helpers();
@@ -11330,7 +11428,7 @@ var init_sessions = __esm({
11330
11428
  {
11331
11429
  name: "hanoman_session_phases",
11332
11430
  title: "Fase sesi",
11333
- description: "Pipeline fase sebuah sesi beserta posisinya sekarang. Menjawab 404 bila sesi itu bukan sesi ber-flow (terminal biasa tak punya fase).",
11431
+ description: "Pipeline fase sebuah sesi beserta posisinya sekarang. Antigravity menggunakan tier child native inherit|flash|pro, effort unknown dan protocol wait asynchronous; reviewer fase read-only instruksional, bukan enforcement runtime. Marker Execute menunggu review independen lulus. Menjawab 404 bila sesi itu bukan sesi ber-flow (terminal biasa tak punya fase).",
11334
11432
  inputSchema: obj({ properties: { session: str("Id sesi, dari hanoman_sessions_list.") }, required: ["session"] }),
11335
11433
  mode: "read",
11336
11434
  capability: "sessions:read",
@@ -11456,10 +11554,25 @@ var init_sessions = __esm({
11456
11554
  build: (a) => ({ method: "POST", path: `/terminal/sessions/${enc(String(a.session))}/interrupt` }),
11457
11555
  shape: (raw) => raw
11458
11556
  },
11557
+ {
11558
+ name: "hanoman_session_rename",
11559
+ title: "Ganti nama sesi",
11560
+ description: "Memberi nama kustom pada sesi terminal (hidup atau yang panenya masih ada) supaya mudah dikenali di Terminal. Nama maksimal 80 karakter, satu baris. Nama kosong menghapus nama kustom dan UI kembali memakai label turunan (backlog/flow/project).",
11561
+ inputSchema: obj({
11562
+ properties: { session: str("Id sesi."), name: str("Nama baru. Kosong = hapus nama kustom.") },
11563
+ required: ["session", "name"]
11564
+ }),
11565
+ mode: "write",
11566
+ capability: "sessions:write",
11567
+ samplePath: "/terminal/sessions/s1",
11568
+ sampleMethod: "PATCH",
11569
+ build: (a) => ({ method: "PATCH", path: `/terminal/sessions/${enc(String(a.session))}`, body: { name: String(a.name) } }),
11570
+ shape: (raw) => raw
11571
+ },
11459
11572
  {
11460
11573
  name: "hanoman_session_create",
11461
11574
  title: "Buka sesi agen baru (BERBAHAYA)",
11462
- description: "BERBAHAYA \u2014 membuka sesi agen BARU: hanoman menjalankan claude/codex dengan IZIN PENUH di worktree project, dan sesi itu bisa menulis berkas, menjalankan perintah, serta membuat commit tanpa manusia di pane. Menuntut capability `sessions:spawn`; `sessions:write` \u2014 yang cukup untuk mengendalikan sesi yang SUDAH ada \u2014 tidak cukup di sini. Panggil hanoman_sessions_list lebih dulu: sesi yang sudah berjalan untuk backlog yang sama akan DILANJUTKAN, bukan digandakan. Hanya muncul saat tingkat `--danger` menyala.",
11575
+ description: "BERBAHAYA \u2014 membuka sesi agen BARU: hanoman menjalankan claude/codex/antigravity dengan IZIN PENUH di worktree project, dan sesi itu bisa menulis berkas, menjalankan perintah, serta membuat commit tanpa manusia di pane. Menuntut capability `sessions:spawn`; `sessions:write` \u2014 yang cukup untuk mengendalikan sesi yang SUDAH ada \u2014 tidak cukup di sini. Panggil hanoman_sessions_list lebih dulu: sesi yang sudah berjalan untuk backlog yang sama akan DILANJUTKAN, bukan digandakan. Hanya muncul saat tingkat `--danger` menyala.",
11463
11576
  inputSchema: obj({
11464
11577
  properties: {
11465
11578
  spec: str("Id backlog, mis. `SPEC-482`. Mengisinya membuka sesi BACKLOG dan mewajibkan `flow`."),
@@ -11469,13 +11582,23 @@ var init_sessions = __esm({
11469
11582
  "Alur sesi. Wajib bila `spec` diisi. `reverse`/`prd`/`breakdown`/`scaffold` adalah sesi tingkat-project dan dipasangkan dengan `project`."
11470
11583
  ),
11471
11584
  shell: bool("true = terminal shell biasa di repo project, tanpa agen. Hanya dengan `project`."),
11472
- agent: enumStr(["claude", "codex"], "Mesin sesi. Kosong = default global."),
11585
+ agent: enumStr(["claude", "codex", "antigravity"], "Mesin sesi. Kosong = default global."),
11473
11586
  model: str("Model. Kosong = default global."),
11474
11587
  effort: str("Effort. Kosong = default global."),
11475
11588
  goal: bool("Mode goal per-sesi. Kosong = ikut setelan global."),
11476
11589
  goalCondition: str("Kondisi selesai mode goal (maks 4000 karakter)."),
11477
11590
  verifyScope: enumStr(["changed", "full"], "Scope verifikasi. Kosong = ikut setelan global."),
11478
11591
  method: str("Metode workflow. Id tak dikenal jatuh ke default, bukan ditolak."),
11592
+ phaseOverrides: {
11593
+ type: "object",
11594
+ maxProperties: PHASE_OVERRIDE_LIMITS.phases,
11595
+ propertyNames: { type: "string", minLength: 1, maxLength: PHASE_OVERRIDE_LIMITS.phase },
11596
+ description: "Override fase backlog. Antigravity memakai tier inherit|flash|pro, effort null; validasi mengikuti runtime efektif.",
11597
+ additionalProperties: obj({ properties: {
11598
+ model: { oneOf: [{ type: "string", minLength: 1, maxLength: PHASE_OVERRIDE_LIMITS.model }, { type: "null" }] },
11599
+ effort: { oneOf: [{ type: "string", minLength: 1, maxLength: PHASE_OVERRIDE_LIMITS.effort }, { type: "null" }] }
11600
+ } })
11601
+ },
11479
11602
  prdPath: str("flow `breakdown`: jalur PRD yang dipecah. WAJIB untuk alur itu."),
11480
11603
  force: bool("Lewati gerbang dependency. Pakai HANYA sesudah melihat daftar pemblokirnya.")
11481
11604
  },
@@ -11496,6 +11619,7 @@ var init_sessions = __esm({
11496
11619
  const body2 = { spec: String(a.spec), flow: String(a.flow) };
11497
11620
  for (const k of ["model", "effort", "goalCondition", "agent", "verifyScope", "method"])
11498
11621
  if (s(a[k]) !== void 0) body2[k] = s(a[k]);
11622
+ if (a.phaseOverrides && typeof a.phaseOverrides === "object" && !Array.isArray(a.phaseOverrides)) body2.phaseOverrides = a.phaseOverrides;
11499
11623
  for (const k of ["goal", "force"]) if (typeof a[k] === "boolean") body2[k] = a[k];
11500
11624
  return { method: "POST", path: "/terminal/sessions", body: body2 };
11501
11625
  }
@@ -12582,6 +12706,18 @@ var init_system = __esm({
12582
12706
  build: () => ({ method: "GET", path: "/limits/codex" }),
12583
12707
  shape: (raw) => raw
12584
12708
  },
12709
+ {
12710
+ name: "hanoman_limits_antigravity",
12711
+ title: "Sisa kuota Antigravity",
12712
+ description: "Sisa kuota Antigravity CLI (agy) per grup model (Gemini; Claude/GPT) untuk jendela mingguan dan 5 jam, berikut kapan resetnya. Dibaca live dari Cloud Code API Google memakai token agy yang sedang hidup dan di-cache 60 detik; token yang kedaluwarsa (agy tak berjalan) memberi `stale` atau `unavailable`, bukan angka karangan. Endpoint terpisah dari hanoman_limits karena sumbernya beda. Tak menuntut capability apa pun.",
12713
+ inputSchema: obj({ properties: {} }),
12714
+ mode: "read",
12715
+ capability: null,
12716
+ samplePath: "/limits/antigravity",
12717
+ sampleMethod: "GET",
12718
+ build: () => ({ method: "GET", path: "/limits/antigravity" }),
12719
+ shape: (raw) => raw
12720
+ },
12585
12721
  {
12586
12722
  name: "hanoman_overview_get",
12587
12723
  title: "Ringkasan kinerja hari ini (Overview)",
@@ -12681,10 +12817,10 @@ var init_observability = __esm({
12681
12817
  {
12682
12818
  name: "hanoman_models",
12683
12819
  title: "Katalog model agen",
12684
- description: 'Katalog model claude & codex yang tersedia di MESIN ini: id, label, effort yang diterima, serta status probe per penyedia (`providers`: sumber `cli`/`cache`/`bundled`, kapan terakhir dicek, galatnya). Katalog dibaca dari CLI yang terpasang dan di-refresh server tiap 5 menit, jadi ini jawaban yang benar untuk "model/effort apa yang sah dipakai hanoman_session_create atau hanoman_agent_create" \u2014 jangan menebak id model. Hanya menampilkan data yang sudah disaring parser (detail akun CLI tak pernah tersimpan). Tak menuntut capability apa pun.',
12820
+ description: 'Katalog model claude, codex & antigravity yang tersedia di MESIN ini: id, label, effort yang diterima, serta status probe per penyedia (`providers`: sumber `cli`/`cache`/`bundled`, kapan terakhir dicek, galatnya). Katalog dibaca dari CLI yang terpasang dan di-refresh server tiap 5 menit, jadi ini jawaban yang benar untuk "model/effort apa yang sah dipakai hanoman_session_create atau hanoman_agent_create" \u2014 jangan menebak id model. Hanya menampilkan data yang sudah disaring parser (detail akun CLI tak pernah tersimpan). Tak menuntut capability apa pun.',
12685
12821
  inputSchema: obj({
12686
12822
  properties: {
12687
- agent: enumStr(["claude", "codex"], "Batasi ke satu mesin. Kosong = keduanya.")
12823
+ agent: enumStr(["claude", "codex", "antigravity"], "Batasi ke satu mesin. Kosong = semua runtime.")
12688
12824
  }
12689
12825
  }),
12690
12826
  mode: "read",
@@ -12695,7 +12831,7 @@ var init_observability = __esm({
12695
12831
  shape: (raw, a) => {
12696
12832
  const agent = s(a.agent);
12697
12833
  const r = raw ?? {};
12698
- if (agent !== "claude" && agent !== "codex") return raw;
12834
+ if (agent !== "claude" && agent !== "codex" && agent !== "antigravity") return raw;
12699
12835
  const providers = r.providers ?? {};
12700
12836
  return { [agent]: r[agent], providers: { [agent]: providers[agent] } };
12701
12837
  }
@@ -12712,10 +12848,22 @@ var init_observability = __esm({
12712
12848
  build: () => ({ method: "GET", path: "/codex/version" }),
12713
12849
  shape: (raw) => raw
12714
12850
  },
12851
+ {
12852
+ name: "hanoman_antigravity_version",
12853
+ title: "Versi Antigravity CLI",
12854
+ description: "Versi Antigravity CLI pada boundary sesi saat ini: `{version,error}`. Versi semver atau null beserta alasan aman bila biner hilang, timeout, keluaran tidak dikenal, atau sandbox belum didukung. Tidak memuat keluaran CLI mentah atau kredensial; kegagalan observasi tidak memblokir sesi host. Cache 5 menit, invalidasi saat biner/boundary berubah. Tak menuntut capability apa pun.",
12855
+ inputSchema: obj({ properties: {} }),
12856
+ mode: "read",
12857
+ capability: null,
12858
+ samplePath: "/antigravity/version",
12859
+ sampleMethod: "GET",
12860
+ build: () => ({ method: "GET", path: "/antigravity/version" }),
12861
+ shape: (raw) => raw
12862
+ },
12715
12863
  {
12716
12864
  name: "hanoman_methods_status",
12717
12865
  title: "Kesiapan metode workflow",
12718
- description: "Metode workflow mana yang benar-benar siap dipakai di MESIN ini, per agen (claude/codex): skill/paket apa yang sudah terpasang dan apa yang masih kurang. Diturunkan dari disk tiap dipanggil (tanpa cache), jadi hasilnya segar sesudah operator memasang skill. Baca-saja dan tak pernah memblokir kelahiran sesi \u2014 metode yang belum siap hanya ditandai; memasangnya tetap tindakan manusia di dashboard. Berisi path home/roots skill di mesin. Tak menuntut capability apa pun.",
12866
+ description: "Metode workflow mana yang benar-benar siap dipakai di MESIN ini, per agen (claude/codex/antigravity; installer Antigravity unavailable sampai upstream terverifikasi): skill/paket apa yang sudah terpasang dan apa yang masih kurang. Diturunkan dari disk tiap dipanggil (tanpa cache), jadi hasilnya segar sesudah operator memasang skill. Baca-saja dan tak pernah memblokir kelahiran sesi \u2014 metode yang belum siap hanya ditandai; memasangnya tetap tindakan manusia di dashboard. Berisi path home/roots skill di mesin. Tak menuntut capability apa pun.",
12719
12867
  inputSchema: obj({ properties: {} }),
12720
12868
  mode: "read",
12721
12869
  capability: null,
@@ -13383,7 +13531,7 @@ var init_gates = __esm({
13383
13531
  name: str("Nama cron (1\u2013120 karakter)."),
13384
13532
  expr: str("Cron expression 5 kolom (menit jam tanggal bulan hari-minggu), mis. `0 7 * * *`. Ekspresi tak sah ditolak 400."),
13385
13533
  prompt: str("Prompt awal yang dikirim ke sesi agen setiap kali cron jatuh tempo (maks 8000 karakter).", { maxLength: 8e3 }),
13386
- agent: enumStr(["claude", "codex"], "Mesin sesi. Kosong = default global."),
13534
+ agent: enumStr(["claude", "codex", "antigravity"], "Mesin sesi. Kosong = default global."),
13387
13535
  model: str("Model. Kosong = default global."),
13388
13536
  effort: str("Effort. Kosong = default global.")
13389
13537
  };
@@ -13420,6 +13568,45 @@ var init_gates = __esm({
13420
13568
  }),
13421
13569
  shape: (raw) => raw
13422
13570
  },
13571
+ {
13572
+ name: "hanoman_scheduler_reports",
13573
+ title: "Daftar laporan run cron",
13574
+ description: "Laporan hasil run cron (ADR-0222): pesan akhir agen yang disimpan sebagai dokumen markdown, satu per run, tersync antar mesin. Amplop berhalaman `{items,total,page,pageSize}`, terbaru dulu, TANPA isi (`id`, `cronId`, `cronName`, `runDate`, `dueAt`, `bytes`, `filename`). Isi dibaca lewat hanoman_scheduler_report_get. Saring menurut `cron` / `project`; cron dari mesin lain tetap terdaftar (cron tak harus ada di instance ini).",
13575
+ inputSchema: obj({ properties: {
13576
+ cron: str("Saring menurut id cron."),
13577
+ project: str("Saring menurut id project."),
13578
+ ...PAGE_PARAMS
13579
+ } }),
13580
+ mode: "read",
13581
+ capability: "scheduler:read",
13582
+ samplePath: "/scheduler/reports",
13583
+ sampleMethod: "GET",
13584
+ build: (a) => ({
13585
+ method: "GET",
13586
+ path: "/scheduler/reports",
13587
+ query: query({ cronId: s(a.cron), projectId: s(a.project), page: n(a.page)?.toString(), limit: n(a.limit)?.toString() })
13588
+ }),
13589
+ shape: (raw) => raw
13590
+ },
13591
+ {
13592
+ name: "hanoman_scheduler_report_get",
13593
+ title: "Baca laporan run cron",
13594
+ description: 'Baca SATU laporan run cron berikut isi markdown-nya (`body`) dan `filename` turunan. `report` = id laporan (sama dengan id run), atau `latest` (default) untuk laporan terbaru \u2014 saring dengan `cron` / `project`. 404 bila belum ada laporan. Contoh laporan terakhir sebuah cron: `{cron:"<id cron>"}`.',
13595
+ inputSchema: obj({ properties: {
13596
+ report: str("Id laporan, atau `latest` (default)."),
13597
+ cron: str("Untuk `latest`: batasi ke id cron ini."),
13598
+ project: str("Untuk `latest`: batasi ke id project ini.")
13599
+ } }),
13600
+ mode: "read",
13601
+ capability: "scheduler:read",
13602
+ samplePath: "/scheduler/reports/latest",
13603
+ sampleMethod: "GET",
13604
+ build: (a) => {
13605
+ const id = s(a.report);
13606
+ return id && id !== "latest" ? { method: "GET", path: `/scheduler/reports/${enc(id)}` } : { method: "GET", path: "/scheduler/reports/latest", query: query({ cronId: s(a.cron), projectId: s(a.project) }) };
13607
+ },
13608
+ shape: (raw) => raw
13609
+ },
13423
13610
  {
13424
13611
  name: "hanoman_scheduler_cron_create",
13425
13612
  title: "Buat cronjob (BERBAHAYA)",
@@ -14701,6 +14888,16 @@ var init_mcp = __esm({
14701
14888
  }
14702
14889
  });
14703
14890
 
14891
+ // ../shared/src/cron-report.ts
14892
+ var CRON_REPORT_MAX_BYTES, enc2;
14893
+ var init_cron_report = __esm({
14894
+ "../shared/src/cron-report.ts"() {
14895
+ "use strict";
14896
+ CRON_REPORT_MAX_BYTES = 64 * 1024;
14897
+ enc2 = new TextEncoder();
14898
+ }
14899
+ });
14900
+
14704
14901
  // ../shared/src/terminal-workspace.ts
14705
14902
  var zSessionId, zTrackSizes, zTerminalGroup, zTerminalWorkspaceV1, zTerminalWorkspaceWrite, zTerminalWorkspaceSnapshot;
14706
14903
  var init_terminal_workspace = __esm({
@@ -14867,6 +15064,7 @@ var PRESENCE_PROTOCOL, MAX_PRESENCE_SESSIONS, PRESENCE_MAX_FRAME_BYTES, zPresenc
14867
15064
  var init_presence = __esm({
14868
15065
  "../shared/src/presence.ts"() {
14869
15066
  "use strict";
15067
+ init_enums();
14870
15068
  init_zod();
14871
15069
  init_session_admission();
14872
15070
  PRESENCE_PROTOCOL = 1;
@@ -14879,7 +15077,7 @@ var init_presence = __esm({
14879
15077
  flow: external_exports.string().max(40).optional(),
14880
15078
  /** Fase `active` dari `readPhases()`. Absen = sesi tanpa berkas fase (mis. konsol VPS). */
14881
15079
  phase: external_exports.string().max(80).optional(),
14882
- agent: external_exports.enum(["claude", "codex"]),
15080
+ agent: zAgent,
14883
15081
  status: external_exports.enum(["working", "waiting", "exited"]),
14884
15082
  startedAt: external_exports.string().max(40)
14885
15083
  }).strict();
@@ -14914,6 +15112,7 @@ var init_pending = __esm({
14914
15112
  var init_model_catalog = __esm({
14915
15113
  "../shared/src/model-catalog.ts"() {
14916
15114
  "use strict";
15115
+ init_antigravity();
14917
15116
  init_entities();
14918
15117
  }
14919
15118
  });
@@ -14968,6 +15167,7 @@ var init_src = __esm({
14968
15167
  init_auto_merge();
14969
15168
  init_handled_by();
14970
15169
  init_cron_expr();
15170
+ init_cron_report();
14971
15171
  init_terminal_workspace();
14972
15172
  init_terminal_io();
14973
15173
  init_session_dialog();
@@ -14981,6 +15181,7 @@ var init_src = __esm({
14981
15181
  init_model_catalog();
14982
15182
  init_runtime_defaults();
14983
15183
  init_skills2();
15184
+ init_antigravity();
14984
15185
  }
14985
15186
  });
14986
15187
 
@@ -15383,6 +15584,7 @@ import { homedir as homedir2 } from "node:os";
15383
15584
  import { basename, dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
15384
15585
  import { existsSync, readdirSync, readFileSync } from "node:fs";
15385
15586
  function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
15587
+ if (agent === "antigravity") return join2(osHome, ".gemini", "antigravity-cli");
15386
15588
  const own = (agent === "codex" ? env.HANOMAN_CODEX_HOME : env.HANOMAN_CLAUDE_HOME)?.trim();
15387
15589
  if (own) return own;
15388
15590
  if (agent === "codex") {
@@ -15477,12 +15679,13 @@ function cacheRoots(home) {
15477
15679
  const out = [];
15478
15680
  for (const marketplace of dirsIn(cache))
15479
15681
  for (const pkg of dirsIn(join2(cache, marketplace)))
15480
- for (const version3 of dirsIn(join2(cache, marketplace, pkg)))
15481
- out.push({ pkg, marketplace, dir: join2(cache, marketplace, pkg, version3) });
15682
+ for (const version2 of dirsIn(join2(cache, marketplace, pkg)))
15683
+ out.push({ pkg, marketplace, dir: join2(cache, marketplace, pkg, version2) });
15482
15684
  return out;
15483
15685
  }
15484
15686
  function disabledPlugins(agent, home) {
15485
15687
  const out = /* @__PURE__ */ new Set();
15688
+ if (agent === "antigravity") return out;
15486
15689
  if (agent === "claude") {
15487
15690
  const en = readJson(join2(home, "settings.json"))?.enabledPlugins;
15488
15691
  if (en && typeof en === "object") {
@@ -15530,7 +15733,7 @@ function scanAgentSkills(agent, env = process.env, osHome = homedir2()) {
15530
15733
  };
15531
15734
  const userDir = join2(home, "skills");
15532
15735
  add(userDir, skillsUnder(userDir, null));
15533
- for (const r of [...manifestRoots(home), ...cacheRoots(home)]) {
15736
+ for (const r of agent === "antigravity" ? [] : [...manifestRoots(home), ...cacheRoots(home)]) {
15534
15737
  if (disabled.has(`${r.pkg}@${r.marketplace}`)) continue;
15535
15738
  const found = pluginSkills(r.dir, r.pkg);
15536
15739
  if (!found.length) continue;
@@ -15645,6 +15848,25 @@ var init_config_env = __esm({
15645
15848
  }
15646
15849
  });
15647
15850
 
15851
+ // ../runner/src/agent-env.ts
15852
+ function agentEnvironment(agent, env) {
15853
+ const result = { ...env };
15854
+ if (agent === "antigravity") {
15855
+ delete result.CLAUDE_CODE_OAUTH_TOKEN;
15856
+ delete result.ANTHROPIC_API_KEY;
15857
+ } else {
15858
+ for (const key of ANTIGRAVITY_ENV_KEYS) delete result[key];
15859
+ }
15860
+ return result;
15861
+ }
15862
+ var ANTIGRAVITY_ENV_KEYS;
15863
+ var init_agent_env = __esm({
15864
+ "../runner/src/agent-env.ts"() {
15865
+ "use strict";
15866
+ ANTIGRAVITY_ENV_KEYS = ["GEMINI_API_KEY", "GOOGLE_GEMINI_BASE_URL"];
15867
+ }
15868
+ });
15869
+
15648
15870
  // ../runner/src/sandbox-probe.ts
15649
15871
  import { execFileSync } from "node:child_process";
15650
15872
  import { accessSync, constants } from "node:fs";
@@ -15709,15 +15931,15 @@ function prerequisites(env, facts) {
15709
15931
  function allReady(rows) {
15710
15932
  return rows.every((r) => r.ok);
15711
15933
  }
15712
- function run(file, args) {
15934
+ function run(file, args, env) {
15713
15935
  try {
15714
- return execFileSync(file, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
15936
+ return execFileSync(file, args, { encoding: "utf8", env: agentEnvironment(null, env), stdio: ["ignore", "pipe", "ignore"] }).trim();
15715
15937
  } catch {
15716
15938
  return null;
15717
15939
  }
15718
15940
  }
15719
15941
  function collectProbeFacts(env) {
15720
- const podman = run("podman", ["--version"]);
15942
+ const podman = run("podman", ["--version"], env);
15721
15943
  const network = env.HANOMAN_SESSION_NETWORK ?? "hanoman-egress";
15722
15944
  const dir = env.HANOMAN_AGENT_CREDENTIAL_DIR;
15723
15945
  let credentialDirReadable = false;
@@ -15730,8 +15952,8 @@ function collectProbeFacts(env) {
15730
15952
  }
15731
15953
  return {
15732
15954
  podman,
15733
- rootless: podman ? run("podman", ["info", "--format", "{{.Host.Security.Rootless}}"]) === "true" : false,
15734
- networkExists: podman ? run("podman", ["network", "exists", network]) !== null : false,
15955
+ rootless: podman ? run("podman", ["info", "--format", "{{.Host.Security.Rootless}}"], env) === "true" : false,
15956
+ networkExists: podman ? run("podman", ["network", "exists", network], env) !== null : false,
15735
15957
  credentialDirReadable
15736
15958
  };
15737
15959
  }
@@ -15739,6 +15961,7 @@ var filled2;
15739
15961
  var init_sandbox_probe = __esm({
15740
15962
  "../runner/src/sandbox-probe.ts"() {
15741
15963
  "use strict";
15964
+ init_agent_env();
15742
15965
  filled2 = (v) => !!v && v.trim() !== "";
15743
15966
  }
15744
15967
  });
@@ -15795,6 +16018,16 @@ var init_skill_files = __esm({
15795
16018
  }
15796
16019
  });
15797
16020
 
16021
+ // ../runner/src/antigravity-agent-config.ts
16022
+ var init_antigravity_agent_config = __esm({
16023
+ "../runner/src/antigravity-agent-config.ts"() {
16024
+ "use strict";
16025
+ init_src();
16026
+ init_agent_env();
16027
+ init_custom_agents();
16028
+ }
16029
+ });
16030
+
15798
16031
  // ../runner/src/index.ts
15799
16032
  var init_src2 = __esm({
15800
16033
  "../runner/src/index.ts"() {
@@ -15826,6 +16059,8 @@ var init_src2 = __esm({
15826
16059
  init_subagent_statusline();
15827
16060
  init_skill_library();
15828
16061
  init_skill_files();
16062
+ init_agent_env();
16063
+ init_antigravity_agent_config();
15829
16064
  }
15830
16065
  });
15831
16066
 
@@ -16211,6 +16446,8 @@ var doctor_exports = {};
16211
16446
  __export(doctor_exports, {
16212
16447
  default: () => doctor,
16213
16448
  doctorReport: () => doctorReport,
16449
+ probeDoctorVersion: () => probeDoctorVersion,
16450
+ resolveDoctorAntigravityBin: () => resolveDoctorAntigravityBin,
16214
16451
  resolveDoctorCodexBin: () => resolveDoctorCodexBin
16215
16452
  });
16216
16453
  import { execFileSync as execFileSync4 } from "node:child_process";
@@ -16228,6 +16465,11 @@ function doctorReport(p3) {
16228
16465
  text: p3.codex ? `codex ${p3.codex} \u2014 custom agent native ${codexNativeAgentsSupported(p3.codex) ? "siap" : `butuh >= ${CODEX_NATIVE_AGENTS_MIN_CLIENT}; sesi parent tetap bisa berjalan`}` : "codex \u2014 tak ada",
16229
16466
  fatal: false
16230
16467
  },
16468
+ {
16469
+ mark: p3.antigravity ? p3.sandboxRequired ? "!" : "\u2713" : "\xB7",
16470
+ text: p3.antigravity ? `Antigravity CLI ${p3.antigravity} \u2014 auth manual; ${p3.sandboxRequired ? "sandbox belum didukung" : "host/lab; jalankan agy untuk login; autentikasi belum diverifikasi"}` : p3.sandboxRequired ? "Antigravity CLI \u2014 host/lab saja; sandbox belum didukung; probe/login tidak dijalankan" : "Antigravity CLI \u2014 tak ada (opsional; install/login manual)",
16471
+ fatal: false
16472
+ },
16231
16473
  // SPEC-471 · ADR-0095 · `gh` opsional: tanpa dia tarik issue jatuh ke HTTPS + GITHUB_TOKEN.
16232
16474
  {
16233
16475
  mark: p3.gh ? "\u2713" : "\xB7",
@@ -16257,16 +16499,16 @@ function doctorReport(p3) {
16257
16499
  }
16258
16500
  ];
16259
16501
  for (const m of p3.methods) {
16260
- const agent = m.agent === "codex" ? "Codex CLI" : "Claude Code";
16502
+ const agent = m.agent === "antigravity" ? "Antigravity CLI" : m.agent === "codex" ? "Codex CLI" : "Claude Code";
16261
16503
  rows.push({
16262
16504
  mark: m.ready ? "\u2713" : "!",
16263
- text: m.ready ? `metode ${m.method} \xB7 ${agent} \u2014 siap` : `metode ${m.method} \xB7 ${agent} \u2014 belum siap: ` + [...m.missingPackages, ...m.missingSkills].join(", ") + m.install.map((c) => `
16505
+ text: m.available === false ? `metode ${m.method} \xB7 ${agent} \u2014 tidak tersedia: ${m.availabilityReason}` : m.ready ? `metode ${m.method} \xB7 ${agent} \u2014 siap` : `metode ${m.method} \xB7 ${agent} \u2014 belum siap: ` + [...m.missingPackages, ...m.missingSkills].join(", ") + m.install.map((c) => `
16264
16506
  ${c}`).join(""),
16265
16507
  fatal: false
16266
16508
  });
16267
16509
  }
16268
- if (!p3.claude && !p3.codex) {
16269
- rows.push({ mark: "\u2717", text: "tak ada CLI agen (claude ATAU codex wajib ada)", fatal: true });
16510
+ if (!p3.claude && !p3.codex && (!p3.antigravity || p3.sandboxRequired)) {
16511
+ rows.push({ mark: "\u2717", text: "tak ada CLI agen (claude, codex ATAU Antigravity host/lab wajib ada)", fatal: true });
16270
16512
  }
16271
16513
  return { lines: rows.map((r) => ` ${r.mark} ${r.text}`), ok: !rows.some((r) => r.fatal) };
16272
16514
  }
@@ -16285,9 +16527,23 @@ function writable(path) {
16285
16527
  p3 = up;
16286
16528
  }
16287
16529
  }
16288
- function version(bin, args) {
16530
+ function probeDoctorVersion(bin, args, env, agent = null) {
16531
+ if (agent === "antigravity" && (resolveHardening(env) || (env.HANOMAN_SESSION_SANDBOX ?? "off") !== "off")) return null;
16289
16532
  try {
16290
- return execFileSync4(bin, args, { encoding: "utf8", timeout: 1e4, stdio: ["ignore", "pipe", "ignore"] }).trim().split("\n")[0] ?? null;
16533
+ const output = execFileSync4(bin, args, {
16534
+ encoding: "utf8",
16535
+ env: agentEnvironment(agent, env),
16536
+ timeout: 1e4,
16537
+ ...agent === "antigravity" ? { maxBuffer: 16 * 1024, killSignal: "SIGKILL" } : {},
16538
+ stdio: ["ignore", "pipe", "ignore"]
16539
+ }).trim();
16540
+ if (agent === "antigravity") {
16541
+ const numeric = "(?:0|[1-9]\\d*)";
16542
+ const identifier = "(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)";
16543
+ const semver = new RegExp(`^${numeric}\\.${numeric}\\.${numeric}(?:-${identifier}(?:\\.${identifier})*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$`);
16544
+ return semver.test(output) ? output : null;
16545
+ }
16546
+ return output.split("\n")[0] || null;
16291
16547
  } catch {
16292
16548
  return null;
16293
16549
  }
@@ -16300,6 +16556,14 @@ async function resolveDoctorCodexBin(env, dbUrl, read = readRuntimeConfig) {
16300
16556
  }
16301
16557
  return env.HANOMAN_CODEX_BIN?.trim() || "codex";
16302
16558
  }
16559
+ async function resolveDoctorAntigravityBin(env, dbUrl, read = readRuntimeConfig) {
16560
+ try {
16561
+ const configured = (await read(dbUrl, "HANOMAN_ANTIGRAVITY_BIN"))?.trim();
16562
+ if (configured) return configured;
16563
+ } catch {
16564
+ }
16565
+ return env.HANOMAN_ANTIGRAVITY_BIN?.trim() || "agy";
16566
+ }
16303
16567
  async function doctor(_argv, ctx) {
16304
16568
  let layout;
16305
16569
  let db;
@@ -16320,11 +16584,13 @@ async function doctor(_argv, ctx) {
16320
16584
  { label: "upload", path: d.uploads, writable: writable(d.uploads), fatal: false },
16321
16585
  { label: "key SSH", path: d.sshKeys, writable: writable(d.sshKeys), fatal: false }
16322
16586
  ];
16323
- const claude = version(ctx.env.HANOMAN_CLAUDE_BIN ?? "claude", ["--version"]);
16587
+ const version2 = (bin, args) => probeDoctorVersion(bin, args, ctx.env);
16588
+ const claude = version2(ctx.env.HANOMAN_CLAUDE_BIN ?? "claude", ["--version"]);
16589
+ const antigravity = probeDoctorVersion(await resolveDoctorAntigravityBin(ctx.env, dbUrl), ["--version"], ctx.env, "antigravity");
16324
16590
  const codexProbe = codexNativeVersionProbe(ctx.env, await resolveDoctorCodexBin(ctx.env, dbUrl));
16325
- const codex = version(codexProbe.bin, codexProbe.args);
16591
+ const codex = version2(codexProbe.bin, codexProbe.args);
16326
16592
  const method = METHODS[DEFAULT_METHOD];
16327
- const methods = zAgent.options.filter((a) => (a === "codex" ? codex : claude) !== null).map((a) => {
16593
+ const methods = zAgent.options.filter((a) => ({ claude, codex, antigravity })[a] !== null).map((a) => {
16328
16594
  const s2 = scanAgentSkills(a, ctx.env);
16329
16595
  return methodStatus(method, a, { skills: s2.skills.map((k) => k.id), packages: s2.packages });
16330
16596
  });
@@ -16334,12 +16600,13 @@ async function doctor(_argv, ctx) {
16334
16600
  const sandboxReady = allReady(prerequisites(ctx.env, podmanFacts));
16335
16601
  const r = doctorReport({
16336
16602
  node: process.version,
16337
- git: version("git", ["--version"]),
16338
- tmux: version("tmux", ["-V"]),
16603
+ git: version2("git", ["--version"]),
16604
+ tmux: version2("tmux", ["-V"]),
16339
16605
  claude,
16340
16606
  codex,
16341
- gh: version(ctx.env.HANOMAN_GH_BIN ?? "gh", ["--version"]),
16342
- curl: version("curl", ["--version"]),
16607
+ antigravity,
16608
+ gh: version2(ctx.env.HANOMAN_GH_BIN ?? "gh", ["--version"]),
16609
+ curl: version2("curl", ["--version"]),
16343
16610
  dirs,
16344
16611
  web: layout.web !== null,
16345
16612
  db,
@@ -17423,10 +17690,10 @@ var init_regexes = __esm({
17423
17690
  nanoid = /^[a-zA-Z0-9_-]{21}$/;
17424
17691
  duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
17425
17692
  guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
17426
- uuid = (version3) => {
17427
- if (!version3)
17693
+ uuid = (version2) => {
17694
+ if (!version2)
17428
17695
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
17429
- return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version3}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
17696
+ return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
17430
17697
  };
17431
17698
  email = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
17432
17699
  _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
@@ -17894,10 +18161,10 @@ var init_doc = __esm({
17894
18161
  });
17895
18162
 
17896
18163
  // ../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
17897
- var version2;
18164
+ var version;
17898
18165
  var init_versions = __esm({
17899
18166
  "../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js"() {
17900
- version2 = {
18167
+ version = {
17901
18168
  major: 4,
17902
18169
  minor: 4,
17903
18170
  patch: 3
@@ -18203,7 +18470,7 @@ var init_schemas = __esm({
18203
18470
  inst ?? (inst = {});
18204
18471
  inst._zod.def = def;
18205
18472
  inst._zod.bag = inst._zod.bag || {};
18206
- inst._zod.version = version2;
18473
+ inst._zod.version = version;
18207
18474
  const checks = [...inst._zod.def.checks ?? []];
18208
18475
  if (inst._zod.traits.has("$ZodCheck")) {
18209
18476
  checks.unshift(inst);
@@ -23288,14 +23555,14 @@ function missingClientCapabilities(required2, declared) {
23288
23555
  }
23289
23556
  return Object.keys(missing).length > 0 ? missing : void 0;
23290
23557
  }
23291
- function isModernProtocolVersion(version3) {
23292
- return version3 >= FIRST_MODERN_PROTOCOL_VERSION;
23558
+ function isModernProtocolVersion(version2) {
23559
+ return version2 >= FIRST_MODERN_PROTOCOL_VERSION;
23293
23560
  }
23294
23561
  function legacyProtocolVersions(versions) {
23295
- return versions.filter((version3) => !isModernProtocolVersion(version3));
23562
+ return versions.filter((version2) => !isModernProtocolVersion(version2));
23296
23563
  }
23297
23564
  function modernProtocolVersions(versions) {
23298
- return versions.filter((version3) => isModernProtocolVersion(version3));
23565
+ return versions.filter((version2) => isModernProtocolVersion(version2));
23299
23566
  }
23300
23567
  function appendTextFallbackForNonObject(result) {
23301
23568
  const sc = result.structuredContent;
@@ -25409,8 +25676,8 @@ function getWireResultSchemas() {
25409
25676
  };
25410
25677
  return wireResultSchemasMemo;
25411
25678
  }
25412
- function codecForVersion(version3) {
25413
- return version3 !== void 0 && isModernProtocolVersion(version3) ? rev2026Codec : rev2025Codec;
25679
+ function codecForVersion(version2) {
25680
+ return version2 !== void 0 && isModernProtocolVersion(version2) ? rev2026Codec : rev2025Codec;
25414
25681
  }
25415
25682
  function classifiedWireEra(classification) {
25416
25683
  if (classification.revision !== void 0) return codecForVersion(classification.revision).era;
@@ -25847,8 +26114,8 @@ function withRequestStateValue(ctx, value) {
25847
26114
  }
25848
26115
  };
25849
26116
  }
25850
- function setNegotiatedProtocolVersion(instance, version3) {
25851
- writeNegotiatedProtocolVersion(instance, version3);
26117
+ function setNegotiatedProtocolVersion(instance, version2) {
26118
+ writeNegotiatedProtocolVersion(instance, version2);
25852
26119
  }
25853
26120
  function isPlainObject$1(value) {
25854
26121
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -27078,8 +27345,8 @@ var init_src_CX2iR2pK = __esm({
27078
27345
  */
27079
27346
  _negotiatedProtocolVersion;
27080
27347
  static {
27081
- writeNegotiatedProtocolVersion = (instance, version3) => {
27082
- instance._negotiatedProtocolVersion = version3;
27348
+ writeNegotiatedProtocolVersion = (instance, version2) => {
27349
+ instance._negotiatedProtocolVersion = version2;
27083
27350
  };
27084
27351
  }
27085
27352
  _supportedProtocolVersions;
@@ -35294,7 +35561,7 @@ var init_mcp_DXXb3Vv3 = __esm({
35294
35561
  if (identity.clientInfo !== void 0) server._clientVersion = identity.clientInfo;
35295
35562
  };
35296
35563
  installDiscoverHandler = (server, servedModernVersions) => {
35297
- const missing = servedModernVersions.filter((version3) => !server._supportedProtocolVersions.includes(version3));
35564
+ const missing = servedModernVersions.filter((version2) => !server._supportedProtocolVersions.includes(version2));
35298
35565
  if (missing.length > 0) server._supportedProtocolVersions = [...server._supportedProtocolVersions, ...missing];
35299
35566
  server.setRequestHandler("server/discover", () => server._ondiscover());
35300
35567
  };
@@ -36852,8 +37119,8 @@ var init_stdio = __esm({
36852
37119
  if (this._outboundIntercept?.(message) === "handled") return;
36853
37120
  return this._wire.send(message, options);
36854
37121
  }
36855
- setProtocolVersion = (version3) => {
36856
- this._wire.setProtocolVersion?.(version3);
37122
+ setProtocolVersion = (version2) => {
37123
+ this._wire.setProtocolVersion?.(version2);
36857
37124
  };
36858
37125
  /** Forwards one inbound message to the connected instance. */
36859
37126
  deliver(message, extra) {
@@ -37642,7 +37909,7 @@ function localScriptPath(cwd = process.cwd()) {
37642
37909
  }
37643
37910
  function runScript(env, ctx) {
37644
37911
  return new Promise((resolve6) => {
37645
- const p3 = spawn2("bash", [localScriptPath(ctx.cwd)], { env: { ...process.env, ...env } });
37912
+ const p3 = spawn2("bash", [localScriptPath(ctx.cwd)], { env: { ...agentEnvironment(null, ctx.env), ...env } });
37646
37913
  p3.stdout.on("data", (d) => ctx.stdout(String(d)));
37647
37914
  p3.stderr.on("data", (d) => ctx.stderr(String(d)));
37648
37915
  p3.on("close", (code) => resolve6(code ?? 1));
@@ -37677,6 +37944,7 @@ var PROFILES, flag;
37677
37944
  var init_provision = __esm({
37678
37945
  "src/commands/provision.ts"() {
37679
37946
  "use strict";
37947
+ init_src2();
37680
37948
  PROFILES = ["lab", "production"];
37681
37949
  flag = (args, name) => args.find((a) => a.startsWith(`--${name}=`))?.split("=").slice(1).join("=");
37682
37950
  }
@@ -37920,7 +38188,9 @@ var init_migrate_pg = __esm({
37920
38188
  "QaReport",
37921
38189
  "QaCase",
37922
38190
  "QaFinding",
37923
- "QaAttachment"
38191
+ "QaAttachment",
38192
+ // ADR-0222 · CronReport sesudah Project (FK projectId, cascade); tak ada di sumber Postgres lama.
38193
+ "CronReport"
37924
38194
  ];
37925
38195
  CHUNK = 200;
37926
38196
  INT8_OID = 20;
@@ -38164,10 +38434,10 @@ var init_docs_link = __esm({
38164
38434
 
38165
38435
  // src/release/pack.ts
38166
38436
  import { join as join15 } from "node:path";
38167
- function packageJsonFor(version3, deps) {
38437
+ function packageJsonFor(version2, deps) {
38168
38438
  return {
38169
38439
  name: PKG_NAME,
38170
- version: version3,
38440
+ version: version2,
38171
38441
  description: "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
38172
38442
  type: "module",
38173
38443
  repository: { type: "git", url: REPO_URL },
@@ -38297,8 +38567,8 @@ async function pack(argv, ctx) {
38297
38567
  }
38298
38568
  const outIdx = argv.indexOf("--out");
38299
38569
  const out = outIdx === -1 ? join16(repo, "dist-npm") : join16(repo, argv[outIdx + 1] ?? "dist-npm");
38300
- const version3 = JSON.parse(readFileSync9(join16(repo, "package.json"), "utf8")).version;
38301
- if (!version3) {
38570
+ const version2 = JSON.parse(readFileSync9(join16(repo, "package.json"), "utf8")).version;
38571
+ if (!version2) {
38302
38572
  ctx.stderr("pack: root package.json tanpa field version\n");
38303
38573
  return 1;
38304
38574
  }
@@ -38323,14 +38593,14 @@ async function pack(argv, ctx) {
38323
38593
  cpSync(item.from, dest, item.dir ? { recursive: true } : {});
38324
38594
  }
38325
38595
  writeFileSync3(join16(out, "bin/hanoman.mjs"), BIN_SHIM);
38326
- writeFileSync3(join16(out, "package.json"), JSON.stringify(packageJsonFor(version3, deps), null, 2) + "\n");
38596
+ writeFileSync3(join16(out, "package.json"), JSON.stringify(packageJsonFor(version2, deps), null, 2) + "\n");
38327
38597
  const missing = REQUIRED_ARTIFACTS.filter((a) => !existsSync10(join16(out, a)));
38328
38598
  if (missing.length) {
38329
38599
  ctx.stderr(`pack: artefak wajib hilang: ${missing.join(", ")}
38330
38600
  `);
38331
38601
  return 1;
38332
38602
  }
38333
- ctx.stdout(`pack \xB7 ${out} \xB7 hanoman@${version3} \xB7 ${REQUIRED_ARTIFACTS.length} artefak wajib ada
38603
+ ctx.stdout(`pack \xB7 ${out} \xB7 hanoman@${version2} \xB7 ${REQUIRED_ARTIFACTS.length} artefak wajib ada
38334
38604
  `);
38335
38605
  ctx.stdout("terbitkan MANUAL: cd dist-npm && npm publish --otp <kode>\n");
38336
38606
  return 0;
@@ -38439,10 +38709,10 @@ var init_router = __esm({
38439
38709
  doctor periksa prasyarat: node, git, tmux, CLI agen, data dir
38440
38710
  update [--check] bandingkan versi dengan registry npm; pasang yang terbaru
38441
38711
  provision [--with=a,b] [--probe] pasang komponen di MESIN INI (hanoman, caddy, claude,
38442
- [--profile=lab|production] codex, gh, \u2026). --probe hanya melaporkan apa yang ada.
38712
+ [--profile=lab|production] codex, antigravity (host/lab), gh, \u2026). --probe hanya melaporkan apa yang ada.
38443
38713
  [--domain=<d>] [--dry-run] [--yes]
38444
38714
  mcp [--read-only] [--host <url>] MCP server stdio untuk klien AI (Claude Code/Desktop,
38445
- [--max-bytes <n>] Codex, Cursor, Copilot). Token dari HANOMAN_AGENT_TOKEN.
38715
+ [--max-bytes <n>] Codex, Antigravity, Cursor, Copilot). Token dari HANOMAN_AGENT_TOKEN.
38446
38716
  [--transfer-dir <d>] direktori tambahan untuk unggah/unduh berkas (ADR-0183)
38447
38717
  migrate-from-postgres --from <url> pindahkan data Postgres lama ke SQLite
38448
38718
  [--to <file>] [--dry-run] [--force]