agentsmesh 0.39.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/canonical.js CHANGED
@@ -926,6 +926,7 @@ var init_target_descriptor_schema = __esm({
926
926
  emitScopedSettings: z.function().optional(),
927
927
  mergeGeneratedOutputContent: z.function().optional(),
928
928
  postProcessHookOutputs: z.function().optional(),
929
+ hookContextEvents: z.array(z.string()).optional(),
929
930
  preservesManualActivation: z.boolean().optional()
930
931
  }).passthrough();
931
932
  targetDescriptorSchemaBase.superRefine((value, ctx) => {
@@ -1242,10 +1243,16 @@ var init_guards = __esm({
1242
1243
  "src/utils/types/guards.ts"() {
1243
1244
  }
1244
1245
  });
1245
- var RECALL_HOOK_COMMAND;
1246
+ var init_cli_invocation = __esm({
1247
+ "src/lessons/cli-invocation.ts"() {
1248
+ }
1249
+ });
1250
+ var RECALL_SUBCOMMAND, RECALL_HOOK_COMMAND;
1246
1251
  var init_recall_hook_scaffold = __esm({
1247
1252
  "src/lessons/recall-hook-scaffold.ts"() {
1248
- RECALL_HOOK_COMMAND = "agentsmesh lessons hook";
1253
+ init_cli_invocation();
1254
+ RECALL_SUBCOMMAND = "lessons hook";
1255
+ RECALL_HOOK_COMMAND = `agentsmesh ${RECALL_SUBCOMMAND}`;
1249
1256
  }
1250
1257
  });
1251
1258
 
@@ -2177,6 +2184,15 @@ var init_constants = __esm({
2177
2184
  }
2178
2185
  });
2179
2186
 
2187
+ // src/targets/catalog/ignore-output.ts
2188
+ function ignoreOutput(path) {
2189
+ return (canonical) => canonical.ignore.length === 0 ? [] : [{ path, content: canonical.ignore.join("\n") }];
2190
+ }
2191
+ var init_ignore_output = __esm({
2192
+ "src/targets/catalog/ignore-output.ts"() {
2193
+ }
2194
+ });
2195
+
2180
2196
  // src/targets/aider/generator.ts
2181
2197
  function buildAiderConventions(canonical) {
2182
2198
  const root = canonical.rules.find((rule) => rule.root);
@@ -2206,11 +2222,7 @@ function generateAgents(canonical) {
2206
2222
  content: serializeProjectedAgentSkill(agent)
2207
2223
  }));
2208
2224
  }
2209
- function generateIgnore(canonical) {
2210
- if (canonical.ignore.length === 0) return [];
2211
- return [{ path: AIDER_IGNORE, content: canonical.ignore.join("\n") }];
2212
- }
2213
- var generateMcp, generatePermissions;
2225
+ var generateIgnore, generateMcp, generatePermissions;
2214
2226
  var init_generator = __esm({
2215
2227
  "src/targets/aider/generator.ts"() {
2216
2228
  init_no_outputs();
@@ -2219,6 +2231,8 @@ var init_generator = __esm({
2219
2231
  init_projected_agent_skill();
2220
2232
  init_command_skill();
2221
2233
  init_constants();
2234
+ init_ignore_output();
2235
+ generateIgnore = ignoreOutput(AIDER_IGNORE);
2222
2236
  generateMcp = NO_OUTPUTS;
2223
2237
  generatePermissions = NO_OUTPUTS;
2224
2238
  }
@@ -2914,6 +2928,9 @@ var init_link_token_context = __esm({
2914
2928
  });
2915
2929
 
2916
2930
  // src/core/reference/link-rebaser.ts
2931
+ function isSlashCommandToken(normalizedToken) {
2932
+ return /^\/[A-Za-z][A-Za-z0-9-]*$/.test(normalizedToken);
2933
+ }
2917
2934
  function rewriteFileLinks(input) {
2918
2935
  const missing = /* @__PURE__ */ new Set();
2919
2936
  const protectedRefRanges = protectedRanges(input.content);
@@ -2964,6 +2981,7 @@ function rewriteFileLinks(input) {
2964
2981
  if (targetIsDirectory && !normalizedCandidate.includes("/") && !normalizedCandidate.includes("\\")) {
2965
2982
  return match;
2966
2983
  }
2984
+ if (isSlashCommandToken(normalizedCandidate)) return match;
2967
2985
  if (resolvedBeforeTranslate === null) {
2968
2986
  let normTok = normalizeSeparators(punctStripped);
2969
2987
  if (normTok.startsWith("agentsmesh/")) {
@@ -7009,10 +7027,6 @@ function generateAgents4(canonical) {
7009
7027
  content: serializeAntigravityAgent(agent)
7010
7028
  }));
7011
7029
  }
7012
- function generateIgnore3(canonical) {
7013
- if (canonical.ignore.length === 0) return [];
7014
- return [{ path: ANTIGRAVITY_IGNORE_FILE, content: canonical.ignore.join("\n") }];
7015
- }
7016
7030
  function renderAntigravityGlobalInstructions(canonical) {
7017
7031
  const root = canonical.rules.find((rule) => rule.root);
7018
7032
  const nonRootRules = canonical.rules.filter((rule) => {
@@ -7027,7 +7041,7 @@ function generateHooks2(canonical) {
7027
7041
  if (Object.keys(hooks).length === 0) return [];
7028
7042
  return [{ path: ANTIGRAVITY_HOOKS_FILE, content: JSON.stringify(hooks, null, 2) }];
7029
7043
  }
7030
- var generatePermissions3;
7044
+ var generateIgnore3, generatePermissions3;
7031
7045
  var init_generator4 = __esm({
7032
7046
  "src/targets/antigravity/generator.ts"() {
7033
7047
  init_no_outputs();
@@ -7036,6 +7050,8 @@ var init_generator4 = __esm({
7036
7050
  init_hooks_format2();
7037
7051
  init_agents_format();
7038
7052
  init_constants5();
7053
+ init_ignore_output();
7054
+ generateIgnore3 = ignoreOutput(ANTIGRAVITY_IGNORE_FILE);
7039
7055
  generatePermissions3 = NO_OUTPUTS;
7040
7056
  }
7041
7057
  });
@@ -8498,16 +8514,14 @@ function generateHooks3(canonical) {
8498
8514
  const content = JSON.stringify({ hooks: claudeHooks }, null, 2);
8499
8515
  return [{ path: CLAUDE_SETTINGS, content }];
8500
8516
  }
8501
- function generateIgnore5(canonical) {
8502
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
8503
- const content = canonical.ignore.join("\n");
8504
- return [{ path: CLAUDE_IGNORE, content }];
8505
- }
8517
+ var generateIgnore5;
8506
8518
  var init_generator6 = __esm({
8507
8519
  "src/targets/claude-code/generator.ts"() {
8508
8520
  init_markdown();
8509
8521
  init_constants7();
8510
8522
  init_hooks_format2();
8523
+ init_ignore_output();
8524
+ generateIgnore5 = ignoreOutput(CLAUDE_IGNORE);
8511
8525
  }
8512
8526
  });
8513
8527
  function ruleSectionTitle(rule) {
@@ -10326,11 +10340,7 @@ function generateMcp5(canonical) {
10326
10340
  if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
10327
10341
  return [{ path: CODEBUFF_MCP_FILE, content: serializeCodebuffMcp(canonical.mcp) }];
10328
10342
  }
10329
- function generateIgnore7(canonical) {
10330
- if (canonical.ignore.length === 0) return [];
10331
- return [{ path: CODEBUFF_IGNORE_FILE, content: canonical.ignore.join("\n") }];
10332
- }
10333
- var generateAgents8, generateHooks5, generatePermissions6;
10343
+ var generateIgnore7, generateAgents8, generateHooks5, generatePermissions6;
10334
10344
  var init_generator8 = __esm({
10335
10345
  "src/targets/codebuff/generator.ts"() {
10336
10346
  init_no_outputs();
@@ -10340,6 +10350,8 @@ var init_generator8 = __esm({
10340
10350
  init_nested_rules();
10341
10351
  init_mcp_format2();
10342
10352
  init_constants9();
10353
+ init_ignore_output();
10354
+ generateIgnore7 = ignoreOutput(CODEBUFF_IGNORE_FILE);
10343
10355
  generateAgents8 = NO_OUTPUTS;
10344
10356
  generateHooks5 = NO_OUTPUTS;
10345
10357
  generatePermissions6 = NO_OUTPUTS;
@@ -12852,53 +12864,37 @@ var init_mcp_generator = __esm({
12852
12864
  }
12853
12865
  });
12854
12866
 
12855
- // src/targets/copilot/hook-entry.ts
12856
- function hasHookCommand2(entry) {
12857
- return hasHookCommand(entry);
12858
- }
12859
- var init_hook_entry = __esm({
12860
- "src/targets/copilot/hook-entry.ts"() {
12861
- init_hook_command();
12862
- }
12863
- });
12864
-
12865
12867
  // src/targets/copilot/hook-format.ts
12866
- function mapHookEvent(event) {
12867
- switch (event) {
12868
- case "PreToolUse":
12869
- return "preToolUse";
12870
- case "PostToolUse":
12871
- return "postToolUse";
12872
- case "Notification":
12873
- return "notification";
12874
- case "UserPromptSubmit":
12875
- return "userPromptSubmitted";
12876
- default:
12877
- return null;
12878
- }
12868
+ function copilotHookGroups(hooks) {
12869
+ return Object.entries(hooks ?? {}).flatMap(([event, entries]) => {
12870
+ const copilotEvent = CANONICAL_TO_COPILOT.get(event);
12871
+ if (!copilotEvent || !Array.isArray(entries)) return [];
12872
+ const kept = entries.filter(
12873
+ (entry) => typeof entry === "object" && entry !== null && hasHookCommand(entry)
12874
+ );
12875
+ return kept.length > 0 ? [{ event, copilotEvent, entries: kept }] : [];
12876
+ });
12877
+ }
12878
+ function wrapperScriptName(event, index) {
12879
+ return `${event.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase()}-${index}.sh`;
12879
12880
  }
12880
12881
  function buildCopilotHooksObject(hooks) {
12881
- if (!hooks) return null;
12882
- const result2 = Object.fromEntries(
12883
- Object.entries(hooks).flatMap(([event, entries]) => {
12884
- const mappedEvent = mapHookEvent(event);
12885
- if (!mappedEvent || !Array.isArray(entries)) return [];
12886
- const mappedEntries = entries.filter(
12887
- (entry) => typeof entry === "object" && entry !== null && hasHookCommand2(entry)
12888
- ).map((entry, index) => {
12889
- const safePhase = event.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
12882
+ const groups = copilotHookGroups(hooks);
12883
+ if (groups.length === 0) return null;
12884
+ return Object.fromEntries(
12885
+ groups.map(({ event, copilotEvent, entries }) => [
12886
+ copilotEvent,
12887
+ entries.map((entry, index) => {
12890
12888
  const hook = {
12891
12889
  type: "command",
12892
- bash: `./scripts/${safePhase}-${index}.sh`
12890
+ bash: `./scripts/${wrapperScriptName(event, index)}`
12893
12891
  };
12894
12892
  if (entry.matcher && entry.matcher !== "*") hook.matcher = entry.matcher;
12895
12893
  if (entry.timeout !== void 0) hook.timeoutSec = Math.ceil(entry.timeout / 1e3);
12896
12894
  return hook;
12897
- });
12898
- return mappedEntries.length > 0 ? [[mappedEvent, mappedEntries]] : [];
12899
- })
12895
+ })
12896
+ ])
12900
12897
  );
12901
- return Object.keys(result2).length > 0 ? result2 : null;
12902
12898
  }
12903
12899
  function generateHooks8(canonical) {
12904
12900
  const hooks = buildCopilotHooksObject(canonical.hooks);
@@ -12910,10 +12906,24 @@ function generateHooks8(canonical) {
12910
12906
  }
12911
12907
  ];
12912
12908
  }
12909
+ var COPILOT_HOOK_CONTEXT_EVENTS, CANONICAL_TO_COPILOT;
12913
12910
  var init_hook_format = __esm({
12914
12911
  "src/targets/copilot/hook-format.ts"() {
12915
12912
  init_constants32();
12916
- init_hook_entry();
12913
+ init_hook_command();
12914
+ COPILOT_HOOK_CONTEXT_EVENTS = [
12915
+ "SessionStart",
12916
+ "PostToolUse",
12917
+ "PostToolUseFailure"
12918
+ ];
12919
+ CANONICAL_TO_COPILOT = /* @__PURE__ */ new Map([
12920
+ ["PreToolUse", "preToolUse"],
12921
+ ["PostToolUse", "postToolUse"],
12922
+ ["PostToolUseFailure", "postToolUseFailure"],
12923
+ ["Notification", "notification"],
12924
+ ["UserPromptSubmit", "userPromptSubmitted"],
12925
+ ["SessionStart", "sessionStart"]
12926
+ ]);
12917
12927
  }
12918
12928
  });
12919
12929
  function ruleSlug3(source) {
@@ -13019,18 +13029,7 @@ var init_generator12 = __esm({
13019
13029
  }
13020
13030
  });
13021
13031
  function mapCopilotHookEvent(event) {
13022
- switch (event) {
13023
- case "preToolUse":
13024
- return "PreToolUse";
13025
- case "postToolUse":
13026
- return "PostToolUse";
13027
- case "notification":
13028
- return "Notification";
13029
- case "userPromptSubmitted":
13030
- return "UserPromptSubmit";
13031
- default:
13032
- return null;
13033
- }
13032
+ return COPILOT_TO_CANONICAL.get(event) ?? null;
13034
13033
  }
13035
13034
  function extractMatcher(comment) {
13036
13035
  if (typeof comment !== "string") return "*";
@@ -13118,11 +13117,16 @@ async function importHooks(projectRoot, results, options = {}) {
13118
13117
  feature: "hooks"
13119
13118
  });
13120
13119
  }
13120
+ var COPILOT_TO_CANONICAL;
13121
13121
  var init_hook_parser = __esm({
13122
13122
  "src/targets/copilot/hook-parser.ts"() {
13123
13123
  init_canonical_paths();
13124
13124
  init_fs();
13125
13125
  init_constants32();
13126
+ init_hook_format();
13127
+ COPILOT_TO_CANONICAL = new Map(
13128
+ [...CANONICAL_TO_COPILOT].map(([canonical, copilot]) => [copilot, canonical])
13129
+ );
13126
13130
  }
13127
13131
  });
13128
13132
  async function importSkills2(projectRoot, results, normalize, skillsDirRel = COPILOT_SKILLS_DIR) {
@@ -13359,7 +13363,7 @@ function lintCommands4(canonical) {
13359
13363
  }
13360
13364
  function lintHooks9(canonical) {
13361
13365
  if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
13362
- const supported = ["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit"];
13366
+ const supported = [...CANONICAL_TO_COPILOT.keys()];
13363
13367
  const diagnostics = unsupportedHookEventNames(canonical.hooks, supported).map(
13364
13368
  (event) => createUnsupportedHookWarning(event, "copilot", supported, {
13365
13369
  unsupportedBy: "Copilot hooks"
@@ -13382,11 +13386,9 @@ function lintHooks9(canonical) {
13382
13386
  var init_lint10 = __esm({
13383
13387
  "src/targets/copilot/lint.ts"() {
13384
13388
  init_helpers();
13389
+ init_hook_format();
13385
13390
  }
13386
13391
  });
13387
- function safePhaseName(phase) {
13388
- return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
13389
- }
13390
13392
  function toRepoRelative(projectRoot, sourcePath) {
13391
13393
  const repoRelative = relative(projectRoot, sourcePath).replace(/\\/g, "/");
13392
13394
  if (!repoRelative || repoRelative.startsWith("../")) return null;
@@ -13414,9 +13416,6 @@ async function buildAssetOutput(projectRoot, command, hooksDirRel) {
13414
13416
  rewrittenCommand: rewriteWrapperCommand(command, repoRelative)
13415
13417
  };
13416
13418
  }
13417
- function wrapperPath(event, index, hooksDirRel) {
13418
- return `${hooksDirRel}/scripts/${safePhaseName(event)}-${index}.sh`;
13419
- }
13420
13419
  function safeShellLine2(value) {
13421
13420
  return value.replace(/[\r\n]+/g, " ");
13422
13421
  }
@@ -13431,15 +13430,13 @@ function buildWrapper(command, matcher) {
13431
13430
  ].join("\n");
13432
13431
  }
13433
13432
  async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel = COPILOT_HOOKS_DIR) {
13434
- if (!canonical.hooks) return outputs;
13433
+ const groups = copilotHookGroups(canonical.hooks);
13434
+ if (groups.length === 0) return outputs;
13435
13435
  const wrapperOutputs = [];
13436
13436
  const assetOutputs = /* @__PURE__ */ new Map();
13437
- for (const [event, entries] of Object.entries(canonical.hooks)) {
13438
- if (!Array.isArray(entries)) continue;
13439
- let index = 0;
13440
- for (const entry of entries) {
13441
- if (!hasHookCommand2(entry)) continue;
13442
- const scriptPath = wrapperPath(event, index, hooksDirRel);
13437
+ for (const { event, entries } of groups) {
13438
+ for (const [index, entry] of entries.entries()) {
13439
+ const scriptPath = `${hooksDirRel}/scripts/${wrapperScriptName(event, index)}`;
13443
13440
  let command = entry.command;
13444
13441
  const asset = await buildAssetOutput(projectRoot, entry.command, hooksDirRel);
13445
13442
  if (asset) {
@@ -13453,7 +13450,6 @@ async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel
13453
13450
  'set -eu\nHOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n'
13454
13451
  );
13455
13452
  wrapperOutputs.push({ path: scriptPath, content: wrapper });
13456
- index++;
13457
13453
  }
13458
13454
  }
13459
13455
  return [...outputs, ...wrapperOutputs, ...assetOutputs.values()];
@@ -13463,7 +13459,7 @@ var init_hook_assets = __esm({
13463
13459
  "src/targets/copilot/hook-assets.ts"() {
13464
13460
  init_fs();
13465
13461
  init_constants32();
13466
- init_hook_entry();
13462
+ init_hook_format();
13467
13463
  SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
13468
13464
  }
13469
13465
  });
@@ -13781,6 +13777,7 @@ var init_copilot2 = __esm({
13781
13777
  init_command_prompt();
13782
13778
  init_lint10();
13783
13779
  init_hook_assets();
13780
+ init_hook_format();
13784
13781
  init_scope_extras2();
13785
13782
  init_importer_spec2();
13786
13783
  init_capabilities6();
@@ -13911,6 +13908,7 @@ var init_copilot2 = __esm({
13911
13908
  permissions: lintPermissions7
13912
13909
  },
13913
13910
  postProcessHookOutputs: async (projectRoot, canonical, outputs) => addHookScriptAssets(projectRoot, canonical, [...outputs]),
13911
+ hookContextEvents: COPILOT_HOOK_CONTEXT_EVENTS,
13914
13912
  mergeGeneratedOutputContent: mergeCopilotMcpJson,
13915
13913
  project: project7,
13916
13914
  globalSupport: {
@@ -13998,11 +13996,6 @@ function generatePermissions8(canonical) {
13998
13996
  });
13999
13997
  return [{ path: CRUSH_CONFIG_FILE, content: JSON.stringify(crushConfig, null, 2) }];
14000
13998
  }
14001
- function generateIgnore9(canonical) {
14002
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
14003
- const content = canonical.ignore.join("\n");
14004
- return [{ path: CRUSH_IGNORE, content }];
14005
- }
14006
13999
  function buildCrushHooksFromCanonical(canonical) {
14007
14000
  if (!canonical.hooks) return {};
14008
14001
  const result2 = {};
@@ -14020,7 +14013,7 @@ function buildCrushHooksFromCanonical(canonical) {
14020
14013
  }
14021
14014
  return result2;
14022
14015
  }
14023
- var generateRules12;
14016
+ var generateRules12, generateIgnore9;
14024
14017
  var init_generator13 = __esm({
14025
14018
  "src/targets/crush/generator.ts"() {
14026
14019
  init_managed_blocks();
@@ -14029,7 +14022,9 @@ var init_generator13 = __esm({
14029
14022
  init_command_skill();
14030
14023
  init_constants12();
14031
14024
  init_config_format();
14025
+ init_ignore_output();
14032
14026
  generateRules12 = (canonical) => embeddedRootRule(canonical, CRUSH_TARGET, CRUSH_ROOT_FILE);
14027
+ generateIgnore9 = ignoreOutput(CRUSH_IGNORE);
14033
14028
  }
14034
14029
  });
14035
14030
  async function importFromCrush(projectRoot, options = {}) {
@@ -14565,7 +14560,7 @@ function cursorHooksToCanonical(hooks) {
14565
14560
  }
14566
14561
  return result2;
14567
14562
  }
14568
- var CANONICAL_TO_CURSOR, CURSOR_TO_CANONICAL;
14563
+ var CANONICAL_TO_CURSOR, CURSOR_HOOK_CONTEXT_EVENTS, CURSOR_TO_CANONICAL;
14569
14564
  var init_hook_format2 = __esm({
14570
14565
  "src/targets/cursor/hook-format.ts"() {
14571
14566
  init_hook_types();
@@ -14573,6 +14568,7 @@ var init_hook_format2 = __esm({
14573
14568
  CANONICAL_TO_CURSOR = {
14574
14569
  PreToolUse: "preToolUse",
14575
14570
  PostToolUse: "postToolUse",
14571
+ PostToolUseFailure: "postToolUseFailure",
14576
14572
  UserPromptSubmit: "beforeSubmitPrompt",
14577
14573
  SubagentStart: "subagentStart",
14578
14574
  SubagentStop: "subagentStop",
@@ -14581,6 +14577,11 @@ var init_hook_format2 = __esm({
14581
14577
  SessionEnd: "sessionEnd",
14582
14578
  PreCompact: "preCompact"
14583
14579
  };
14580
+ CURSOR_HOOK_CONTEXT_EVENTS = [
14581
+ "SessionStart",
14582
+ "PostToolUse",
14583
+ "PostToolUseFailure"
14584
+ ];
14584
14585
  CURSOR_TO_CANONICAL = new Map(
14585
14586
  Object.entries(CANONICAL_TO_CURSOR).map(([canonical, cursor]) => [cursor, canonical])
14586
14587
  );
@@ -14589,7 +14590,7 @@ var init_hook_format2 = __esm({
14589
14590
 
14590
14591
  // src/targets/cursor/generator/hooks.ts
14591
14592
  function generateHooks10(canonical) {
14592
- if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
14593
+ if (!canonical.hooks) return [];
14593
14594
  const cursorHooks = toCursorHooks(canonical.hooks);
14594
14595
  if (Object.keys(cursorHooks).length === 0) return [];
14595
14596
  const content = JSON.stringify({ version: 1, hooks: cursorHooks }, null, 2);
@@ -14603,14 +14604,12 @@ var init_hooks4 = __esm({
14603
14604
  });
14604
14605
 
14605
14606
  // src/targets/cursor/generator/ignore.ts
14606
- function generateIgnore10(canonical) {
14607
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
14608
- const content = canonical.ignore.join("\n");
14609
- return [{ path: CURSOR_IGNORE, content }];
14610
- }
14607
+ var generateIgnore10;
14611
14608
  var init_ignore = __esm({
14612
14609
  "src/targets/cursor/generator/ignore.ts"() {
14613
14610
  init_constants13();
14611
+ init_ignore_output();
14612
+ generateIgnore10 = ignoreOutput(CURSOR_IGNORE);
14614
14613
  }
14615
14614
  });
14616
14615
 
@@ -15164,7 +15163,7 @@ var init_importer13 = __esm({
15164
15163
  });
15165
15164
 
15166
15165
  // src/targets/cursor/merge.ts
15167
- var mergeMcp3, mergeHooks2, mergePermissions2, mergeCursorOutput;
15166
+ var mergeMcp3, mergeHooks, mergePermissions2, mergeCursorOutput;
15168
15167
  var init_merge4 = __esm({
15169
15168
  "src/targets/cursor/merge.ts"() {
15170
15169
  init_target_descriptor();
@@ -15172,14 +15171,14 @@ var init_merge4 = __esm({
15172
15171
  init_mcp_servers_merge();
15173
15172
  init_constants13();
15174
15173
  mergeMcp3 = mcpServersJsonMerger([CURSOR_MCP], CANONICAL_MCP_SERVER_KEYS);
15175
- mergeHooks2 = ownedJsonKeysMerger([CURSOR_HOOKS], ["version", "hooks"]);
15174
+ mergeHooks = ownedJsonKeysMerger([CURSOR_HOOKS], ["version", "hooks"]);
15176
15175
  mergePermissions2 = ownedJsonKeysMerger(
15177
15176
  [CURSOR_CLI_JSON, CURSOR_GLOBAL_CLI_CONFIG],
15178
15177
  ["permissions"]
15179
15178
  );
15180
15179
  mergeCursorOutput = firstMerger([
15181
15180
  mergeMcp3,
15182
- mergeHooks2,
15181
+ mergeHooks,
15183
15182
  mergePermissions2
15184
15183
  ]);
15185
15184
  }
@@ -15306,6 +15305,7 @@ var init_cursor2 = __esm({
15306
15305
  init_linter13();
15307
15306
  init_import_map_builders();
15308
15307
  init_lint12();
15308
+ init_hook_format2();
15309
15309
  target13 = {
15310
15310
  name: "cursor",
15311
15311
  primaryRootInstructionPath: CURSOR_GENERAL_RULE,
@@ -15427,6 +15427,7 @@ var init_cursor2 = __esm({
15427
15427
  permissions: "native"
15428
15428
  },
15429
15429
  emptyImportMessage: "No Cursor config found (AGENTS.md or .cursor/rules/*.mdc; with --global: ~/.cursor/{rules/*.mdc,AGENTS.md,mcp.json,hooks.json,cursorignore,skills/,agents/,commands/} and legacy ~/.agentsmesh-exports/cursor/user-rules.md).",
15430
+ hookContextEvents: CURSOR_HOOK_CONTEXT_EVENTS,
15430
15431
  lintRules: lintRules13,
15431
15432
  lint: {
15432
15433
  commands: lintCommands6,
@@ -16324,7 +16325,7 @@ var init_importer15 = __esm({
16324
16325
  });
16325
16326
 
16326
16327
  // src/targets/factory-droid/merge.ts
16327
- var mergeMcp4, mergeHooks3, mergeSettings, mergeFactoryDroidOutput;
16328
+ var mergeMcp4, mergeHooks2, mergeSettings, mergeFactoryDroidOutput;
16328
16329
  var init_merge5 = __esm({
16329
16330
  "src/targets/factory-droid/merge.ts"() {
16330
16331
  init_target_descriptor();
@@ -16335,7 +16336,7 @@ var init_merge5 = __esm({
16335
16336
  [FACTORY_DROID_MCP_FILE, FACTORY_DROID_GLOBAL_MCP_FILE],
16336
16337
  CANONICAL_MCP_SERVER_KEYS
16337
16338
  );
16338
- mergeHooks3 = ownedJsonKeysMerger(
16339
+ mergeHooks2 = ownedJsonKeysMerger(
16339
16340
  [FACTORY_DROID_HOOKS_FILE, FACTORY_DROID_GLOBAL_HOOKS_FILE],
16340
16341
  ["hooks"]
16341
16342
  );
@@ -16345,7 +16346,7 @@ var init_merge5 = __esm({
16345
16346
  );
16346
16347
  mergeFactoryDroidOutput = firstMerger([
16347
16348
  mergeMcp4,
16348
- mergeHooks3,
16349
+ mergeHooks2,
16349
16350
  mergeSettings
16350
16351
  ]);
16351
16352
  }
@@ -16688,25 +16689,127 @@ var init_skills3 = __esm({
16688
16689
  }
16689
16690
  });
16690
16691
 
16691
- // src/targets/gemini-cli/generator/settings.ts
16692
- function mapHookEvent2(event) {
16693
- switch (event) {
16694
- case "PreToolUse":
16695
- return "BeforeTool";
16696
- case "PostToolUse":
16697
- return "AfterTool";
16698
- case "Notification":
16699
- return "Notification";
16700
- case "SubagentStart":
16701
- return "BeforeAgent";
16702
- case "SubagentStop":
16703
- return "AfterAgent";
16704
- case "SessionStart":
16705
- return "SessionStart";
16706
- default:
16707
- return null;
16692
+ // src/targets/gemini-cli/hook-map.ts
16693
+ function geminiHookEvent(event) {
16694
+ return CANONICAL_TO_GEMINI.get(event) ?? null;
16695
+ }
16696
+ function mapGeminiHookEvent(event) {
16697
+ return GEMINI_TO_CANONICAL.get(event) ?? null;
16698
+ }
16699
+ function splitNames(list, separator) {
16700
+ return list.split(separator).map((name) => name.trim()).filter((name) => name.length > 0);
16701
+ }
16702
+ function toGeminiMatcher(geminiEvent, matcher) {
16703
+ if (!TOOL_EVENTS.has(geminiEvent) || !NAME_LIST.test(matcher)) return matcher;
16704
+ const tools = unique(
16705
+ splitNames(matcher, /[|,]/).flatMap((name) => CANONICAL_TO_GEMINI_TOOLS.get(name) ?? [name])
16706
+ );
16707
+ return tools.length > 0 ? `^(?:${tools.join("|")})$` : matcher;
16708
+ }
16709
+ function fromGeminiMatcher(geminiEvent, matcher) {
16710
+ if (!TOOL_EVENTS.has(geminiEvent)) return matcher;
16711
+ const list = ANCHORED_LIST.exec(matcher)?.[1] ?? matcher;
16712
+ if (!NAME_LIST.test(list) || list.includes(",")) return matcher;
16713
+ return unique(
16714
+ splitNames(list, /\|/).map((name) => GEMINI_TO_CANONICAL_TOOLS.get(name) ?? name)
16715
+ ).join("|");
16716
+ }
16717
+ var GEMINI_HOOK_CONTEXT_EVENTS, CANONICAL_TO_GEMINI, GEMINI_TO_CANONICAL, TOOL_EVENTS, CANONICAL_TO_GEMINI_TOOLS, GEMINI_TO_CANONICAL_TOOLS, NAME_LIST, ANCHORED_LIST, unique;
16718
+ var init_hook_map = __esm({
16719
+ "src/targets/gemini-cli/hook-map.ts"() {
16720
+ GEMINI_HOOK_CONTEXT_EVENTS = [
16721
+ "UserPromptSubmit",
16722
+ "SessionStart",
16723
+ "PostToolUse"
16724
+ ];
16725
+ CANONICAL_TO_GEMINI = /* @__PURE__ */ new Map([
16726
+ ["PreToolUse", "BeforeTool"],
16727
+ ["PostToolUse", "AfterTool"],
16728
+ ["Notification", "Notification"],
16729
+ // BeforeAgent fires after the user submits a prompt and carries `prompt`.
16730
+ ["UserPromptSubmit", "BeforeAgent"],
16731
+ // Older mapping, kept so existing SubagentStart hooks still reach Gemini.
16732
+ ["SubagentStart", "BeforeAgent"],
16733
+ ["SubagentStop", "AfterAgent"],
16734
+ ["SessionStart", "SessionStart"]
16735
+ ]);
16736
+ GEMINI_TO_CANONICAL = new Map([
16737
+ ...[...CANONICAL_TO_GEMINI].map(([canonical, gemini]) => [gemini, canonical]),
16738
+ // BeforeAgent is shared with SubagentStart; import it as the prompt event.
16739
+ ["BeforeAgent", "UserPromptSubmit"],
16740
+ // Legacy lowercase names.
16741
+ ["preToolUse", "PreToolUse"],
16742
+ ["postToolUse", "PostToolUse"],
16743
+ ["notification", "Notification"]
16744
+ ]);
16745
+ TOOL_EVENTS = /* @__PURE__ */ new Set(["BeforeTool", "AfterTool"]);
16746
+ CANONICAL_TO_GEMINI_TOOLS = /* @__PURE__ */ new Map([
16747
+ ["Bash", ["run_shell_command"]],
16748
+ ["PowerShell", ["run_shell_command"]],
16749
+ ["Edit", ["replace"]],
16750
+ ["MultiEdit", ["replace"]],
16751
+ ["Write", ["write_file"]],
16752
+ ["NotebookEdit", []],
16753
+ ["Read", ["read_file", "read_many_files"]],
16754
+ ["Grep", ["grep_search"]],
16755
+ ["Glob", ["glob"]],
16756
+ ["LS", ["list_directory"]],
16757
+ ["WebFetch", ["web_fetch"]],
16758
+ ["WebSearch", ["google_web_search"]],
16759
+ ["TodoWrite", ["write_todos"]]
16760
+ ]);
16761
+ GEMINI_TO_CANONICAL_TOOLS = /* @__PURE__ */ new Map([
16762
+ ["run_shell_command", "Bash"],
16763
+ ["replace", "Edit"],
16764
+ ["write_file", "Write"],
16765
+ ["read_file", "Read"],
16766
+ ["read_many_files", "Read"],
16767
+ ["grep_search", "Grep"],
16768
+ ["search_file_content", "Grep"],
16769
+ ["glob", "Glob"],
16770
+ ["list_directory", "LS"],
16771
+ ["web_fetch", "WebFetch"],
16772
+ ["google_web_search", "WebSearch"],
16773
+ ["write_todos", "TodoWrite"]
16774
+ ]);
16775
+ NAME_LIST = /^[\w\s,|-]+$/;
16776
+ ANCHORED_LIST = /^\^\(\?:(.*)\)\$$/;
16777
+ unique = (values) => [...new Set(values)];
16708
16778
  }
16779
+ });
16780
+
16781
+ // src/targets/gemini-cli/generator/hooks.ts
16782
+ function buildGeminiHooks(hooks) {
16783
+ const result2 = {};
16784
+ for (const [event, entries] of Object.entries(hooks ?? {})) {
16785
+ const geminiEvent = geminiHookEvent(event);
16786
+ if (!geminiEvent || !Array.isArray(entries)) continue;
16787
+ for (const entry of entries) {
16788
+ if (typeof entry !== "object" || entry === null || !hasHookCommand(entry)) continue;
16789
+ const list = result2[geminiEvent] ??= [];
16790
+ list.push({
16791
+ matcher: typeof entry.matcher === "string" ? toGeminiMatcher(geminiEvent, entry.matcher) : entry.matcher,
16792
+ hooks: [
16793
+ {
16794
+ name: `${geminiEvent}-${list.length + 1}`,
16795
+ type: "command",
16796
+ command: getHookCommand(entry),
16797
+ timeout: entry.timeout
16798
+ }
16799
+ ]
16800
+ });
16801
+ }
16802
+ }
16803
+ return Object.keys(result2).length > 0 ? result2 : null;
16709
16804
  }
16805
+ var init_hooks5 = __esm({
16806
+ "src/targets/gemini-cli/generator/hooks.ts"() {
16807
+ init_hook_command();
16808
+ init_hook_map();
16809
+ }
16810
+ });
16811
+
16812
+ // src/targets/gemini-cli/generator/settings.ts
16710
16813
  function generateGeminiSettingsFiles(canonical, enabledFeatures) {
16711
16814
  const settings = {};
16712
16815
  let hasAnyNativeSettings = false;
@@ -16718,29 +16821,10 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
16718
16821
  settings.experimental = { enableAgents: true };
16719
16822
  hasAnyNativeSettings = true;
16720
16823
  }
16721
- if (enabledFeatures.has("hooks") && canonical.hooks) {
16722
- const hookEntries = Object.entries(canonical.hooks).flatMap(([event, entries]) => {
16723
- const mappedEvent = mapHookEvent2(event);
16724
- if (!mappedEvent || !Array.isArray(entries)) return [];
16725
- const mappedEntries = entries.filter(
16726
- (entry) => typeof entry === "object" && entry !== null && hasHookCommand(entry)
16727
- ).map((entry, index) => ({
16728
- matcher: entry.matcher,
16729
- hooks: [
16730
- {
16731
- name: `${mappedEvent}-${index + 1}`,
16732
- type: "command",
16733
- command: getHookCommand(entry),
16734
- timeout: entry.timeout
16735
- }
16736
- ]
16737
- }));
16738
- return mappedEntries.length > 0 ? [[mappedEvent, mappedEntries]] : [];
16739
- });
16740
- if (hookEntries.length > 0) {
16741
- settings.hooks = Object.fromEntries(hookEntries);
16742
- hasAnyNativeSettings = true;
16743
- }
16824
+ const hooks = enabledFeatures.has("hooks") ? buildGeminiHooks(canonical.hooks) : null;
16825
+ if (hooks) {
16826
+ settings.hooks = hooks;
16827
+ hasAnyNativeSettings = true;
16744
16828
  }
16745
16829
  if (hasAnyNativeSettings) {
16746
16830
  settings.context = { fileName: [GEMINI_ROOT, GEMINI_COMPAT_AGENTS] };
@@ -16750,19 +16834,18 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
16750
16834
  }
16751
16835
  var init_settings2 = __esm({
16752
16836
  "src/targets/gemini-cli/generator/settings.ts"() {
16753
- init_hook_command();
16754
16837
  init_constants33();
16838
+ init_hooks5();
16755
16839
  }
16756
16840
  });
16757
16841
 
16758
16842
  // src/targets/gemini-cli/generator/ignore.ts
16759
- function generateIgnore13(canonical) {
16760
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
16761
- return [{ path: GEMINI_IGNORE, content: canonical.ignore.join("\n") }];
16762
- }
16843
+ var generateIgnore13;
16763
16844
  var init_ignore2 = __esm({
16764
16845
  "src/targets/gemini-cli/generator/ignore.ts"() {
16765
16846
  init_constants33();
16847
+ init_ignore_output();
16848
+ generateIgnore13 = ignoreOutput(GEMINI_IGNORE);
16766
16849
  }
16767
16850
  });
16768
16851
 
@@ -17041,27 +17124,6 @@ var init_layout6 = __esm({
17041
17124
  };
17042
17125
  }
17043
17126
  });
17044
- function mapGeminiHookEvent(event) {
17045
- switch (event) {
17046
- case "BeforeTool":
17047
- case "preToolUse":
17048
- return "PreToolUse";
17049
- case "AfterTool":
17050
- case "postToolUse":
17051
- return "PostToolUse";
17052
- case "Notification":
17053
- case "notification":
17054
- return "Notification";
17055
- case "BeforeAgent":
17056
- return "SubagentStart";
17057
- case "AfterAgent":
17058
- return "SubagentStop";
17059
- case "SessionStart":
17060
- return "SessionStart";
17061
- default:
17062
- return null;
17063
- }
17064
- }
17065
17127
  function parseFlexibleFrontmatter(content) {
17066
17128
  const yamlOpen = content.indexOf("---");
17067
17129
  const tomlOpen = content.indexOf("+++");
@@ -17135,7 +17197,7 @@ async function importGeminiSettings(projectRoot, results) {
17135
17197
  (entry) => entry.hooks.filter(
17136
17198
  (hook) => hook !== null && typeof hook === "object" && hasHookCommand(hook)
17137
17199
  ).map((hook) => ({
17138
- matcher: entry.matcher,
17200
+ matcher: fromGeminiMatcher(event, entry.matcher),
17139
17201
  command: getHookCommand(hook),
17140
17202
  type: "command",
17141
17203
  timeout: typeof hook.timeout === "number" ? hook.timeout : void 0
@@ -17145,7 +17207,7 @@ async function importGeminiSettings(projectRoot, results) {
17145
17207
  const legacyMapped = value.filter(
17146
17208
  (entry) => entry !== null && typeof entry === "object" && typeof entry.matcher === "string" && hasHookCommand(entry)
17147
17209
  ).map((entry) => ({
17148
- matcher: entry.matcher,
17210
+ matcher: fromGeminiMatcher(event, entry.matcher),
17149
17211
  command: getHookCommand(entry),
17150
17212
  type: "command"
17151
17213
  }));
@@ -17174,7 +17236,7 @@ var init_format_helpers_settings = __esm({
17174
17236
  init_hook_command();
17175
17237
  init_fs();
17176
17238
  init_constants33();
17177
- init_format_helpers_shared();
17239
+ init_hook_map();
17178
17240
  }
17179
17241
  });
17180
17242
  async function importGeminiIgnore(projectRoot, results) {
@@ -17670,14 +17732,7 @@ function lintPermissions10(canonical, options) {
17670
17732
  }
17671
17733
  function lintHooks12(canonical) {
17672
17734
  if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
17673
- const supported = [
17674
- "PreToolUse",
17675
- "PostToolUse",
17676
- "Notification",
17677
- "SubagentStart",
17678
- "SubagentStop",
17679
- "SessionStart"
17680
- ];
17735
+ const supported = [...CANONICAL_TO_GEMINI.keys()];
17681
17736
  return unsupportedHookEventNames(canonical.hooks, supported).map(
17682
17737
  (event) => createUnsupportedHookWarning(event, "gemini-cli", supported)
17683
17738
  );
@@ -17685,6 +17740,7 @@ function lintHooks12(canonical) {
17685
17740
  var init_lint15 = __esm({
17686
17741
  "src/targets/gemini-cli/lint.ts"() {
17687
17742
  init_helpers();
17743
+ init_hook_map();
17688
17744
  }
17689
17745
  });
17690
17746
 
@@ -17721,6 +17777,7 @@ var init_gemini_cli2 = __esm({
17721
17777
  init_import_map_builders();
17722
17778
  init_lint15();
17723
17779
  init_scoped_settings_emit();
17780
+ init_hook_map();
17724
17781
  init_settings();
17725
17782
  target16 = {
17726
17783
  name: "gemini-cli",
@@ -17771,6 +17828,7 @@ var init_gemini_cli2 = __esm({
17771
17828
  permissions: lintPermissions10
17772
17829
  },
17773
17830
  emitScopedSettings: emitScopedGeminiSettings,
17831
+ hookContextEvents: GEMINI_HOOK_CONTEXT_EVENTS,
17774
17832
  mergeGeneratedOutputContent(existing, pending, newContent, resolvedPath) {
17775
17833
  const base = pending?.content ?? existing;
17776
17834
  if (base !== null && resolvedPath === GEMINI_SETTINGS) {
@@ -17863,14 +17921,10 @@ function generateAgents17(canonical) {
17863
17921
  content: serializeProjectedAgentSkill(agent)
17864
17922
  }));
17865
17923
  }
17866
- function generateIgnore14(canonical) {
17867
- if (canonical.ignore.length === 0) return [];
17868
- return [{ path: GOOSE_IGNORE, content: canonical.ignore.join("\n") }];
17869
- }
17870
17924
  function generateHooks12(canonical) {
17871
17925
  return buildWrappedCommandHooks(canonical, GOOSE_HOOKS_FILE);
17872
17926
  }
17873
- var generateRules17, generatePermissions12;
17927
+ var generateRules17, generateIgnore14, generatePermissions12;
17874
17928
  var init_generator20 = __esm({
17875
17929
  "src/targets/goose/generator.ts"() {
17876
17930
  init_managed_blocks();
@@ -17880,7 +17934,9 @@ var init_generator20 = __esm({
17880
17934
  init_command_skill();
17881
17935
  init_wrapped_command_hooks();
17882
17936
  init_constants16();
17937
+ init_ignore_output();
17883
17938
  generateRules17 = (canonical) => embeddedRootRule(canonical, GOOSE_TARGET, GOOSE_ROOT_FILE);
17939
+ generateIgnore14 = ignoreOutput(GOOSE_IGNORE);
17884
17940
  generatePermissions12 = NO_OUTPUTS;
17885
17941
  }
17886
17942
  });
@@ -18785,10 +18841,6 @@ function generateAgents18(canonical) {
18785
18841
  };
18786
18842
  });
18787
18843
  }
18788
- function generateIgnore16(canonical) {
18789
- if (canonical.ignore.length === 0) return [];
18790
- return [{ path: JUNIE_IGNORE, content: canonical.ignore.join("\n") }];
18791
- }
18792
18844
  function generateSkills17(canonical) {
18793
18845
  return generateEmbeddedSkills(canonical, JUNIE_SKILLS_DIR);
18794
18846
  }
@@ -18800,6 +18852,7 @@ function renderJunieGlobalInstructions(canonical) {
18800
18852
  });
18801
18853
  return appendEmbeddedRulesBlock(root?.body.trim() ?? "", nonRootRules);
18802
18854
  }
18855
+ var generateIgnore16;
18803
18856
  var init_generator22 = __esm({
18804
18857
  "src/targets/junie/generator.ts"() {
18805
18858
  init_mcp_servers();
@@ -18807,7 +18860,9 @@ var init_generator22 = __esm({
18807
18860
  init_managed_blocks();
18808
18861
  init_markdown();
18809
18862
  init_constants18();
18863
+ init_ignore_output();
18810
18864
  init_global_config2();
18865
+ generateIgnore16 = ignoreOutput(JUNIE_IGNORE);
18811
18866
  }
18812
18867
  });
18813
18868
 
@@ -19223,10 +19278,6 @@ function generateMcp15(canonical) {
19223
19278
  }
19224
19279
  ];
19225
19280
  }
19226
- function generateIgnore17(canonical) {
19227
- if (canonical.ignore.length === 0) return [];
19228
- return [{ path: KILO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
19229
- }
19230
19281
  function generatePermissions15(canonical) {
19231
19282
  if (!canonical.permissions) return [];
19232
19283
  const { allow, deny } = canonical.permissions;
@@ -19241,11 +19292,14 @@ function generatePermissions15(canonical) {
19241
19292
  function generateSkills18(canonical) {
19242
19293
  return generateEmbeddedSkills(canonical, KILO_CODE_SKILLS_DIR);
19243
19294
  }
19295
+ var generateIgnore17;
19244
19296
  var init_generator23 = __esm({
19245
19297
  "src/targets/kilo-code/generator.ts"() {
19246
19298
  init_embedded_skill();
19247
19299
  init_markdown();
19248
19300
  init_constants19();
19301
+ init_ignore_output();
19302
+ generateIgnore17 = ignoreOutput(KILO_CODE_IGNORE);
19249
19303
  }
19250
19304
  });
19251
19305
  var kiloNonRootRuleMapper, kiloCommandMapper, kiloAgentMapper;
@@ -20990,11 +21044,7 @@ function buildKiroAgentOutputs(canonical, rules = []) {
20990
21044
  function generateAgents21(canonical) {
20991
21045
  return buildKiroAgentOutputs(canonical);
20992
21046
  }
20993
- function generateIgnore18(canonical) {
20994
- if (canonical.ignore.length === 0) return [];
20995
- return [{ path: KIRO_IGNORE, content: canonical.ignore.join("\n") }];
20996
- }
20997
- var generatePermissions17;
21047
+ var generateIgnore18, generatePermissions17;
20998
21048
  var init_generator25 = __esm({
20999
21049
  "src/targets/kiro/generator.ts"() {
21000
21050
  init_no_outputs();
@@ -21003,6 +21053,8 @@ var init_generator25 = __esm({
21003
21053
  init_markdown();
21004
21054
  init_hook_format3();
21005
21055
  init_constants21();
21056
+ init_ignore_output();
21057
+ generateIgnore18 = ignoreOutput(KIRO_IGNORE);
21006
21058
  generatePermissions17 = NO_OUTPUTS;
21007
21059
  }
21008
21060
  });
@@ -23645,10 +23697,6 @@ function generateMcp19(canonical) {
23645
23697
  const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
23646
23698
  return [{ path: QWEN_SETTINGS, content }];
23647
23699
  }
23648
- function generateIgnore21(canonical) {
23649
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
23650
- return [{ path: QWEN_IGNORE, content: canonical.ignore.join("\n") }];
23651
- }
23652
23700
  function generateHooks18(canonical) {
23653
23701
  if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
23654
23702
  const hooks = buildClaudeHooksObjectFromCanonical(canonical);
@@ -23666,11 +23714,14 @@ function generatePermissions21(canonical) {
23666
23714
  if (ask.length > 0) permissions.ask = ask;
23667
23715
  return [{ path: QWEN_SETTINGS, content: JSON.stringify({ permissions }, null, 2) }];
23668
23716
  }
23717
+ var generateIgnore21;
23669
23718
  var init_generator29 = __esm({
23670
23719
  "src/targets/qwen-code/generator.ts"() {
23671
23720
  init_markdown();
23672
23721
  init_hooks_format2();
23673
23722
  init_constants25();
23723
+ init_ignore_output();
23724
+ generateIgnore21 = ignoreOutput(QWEN_IGNORE);
23674
23725
  }
23675
23726
  });
23676
23727
 
@@ -25368,10 +25419,6 @@ function generateMcp23(canonical) {
25368
25419
  }
25369
25420
  ];
25370
25421
  }
25371
- function generateIgnore24(canonical) {
25372
- if (canonical.ignore.length === 0) return [];
25373
- return [{ path: TRAE_IGNORE, content: canonical.ignore.join("\n") }];
25374
- }
25375
25422
  function generateHooks20(canonical) {
25376
25423
  if (!canonical.hooks) return [];
25377
25424
  const hooks = {};
@@ -25392,12 +25439,15 @@ function generateHooks20(canonical) {
25392
25439
  if (Object.keys(hooks).length === 0) return [];
25393
25440
  return [{ path: TRAE_HOOKS_FILE, content: JSON.stringify({ version: 1, hooks }, null, 2) }];
25394
25441
  }
25442
+ var generateIgnore24;
25395
25443
  var init_generator33 = __esm({
25396
25444
  "src/targets/trae/generator.ts"() {
25397
25445
  init_embedded_skill();
25398
25446
  init_markdown();
25399
25447
  init_hook_command();
25400
25448
  init_constants29();
25449
+ init_ignore_output();
25450
+ generateIgnore24 = ignoreOutput(TRAE_IGNORE);
25401
25451
  }
25402
25452
  });
25403
25453
 
@@ -25772,7 +25822,7 @@ var init_importer30 = __esm({
25772
25822
  });
25773
25823
 
25774
25824
  // src/targets/trae/merge.ts
25775
- var mergeMcp6, mergeHooks4, mergeTraeOutput;
25825
+ var mergeMcp6, mergeHooks3, mergeTraeOutput;
25776
25826
  var init_merge12 = __esm({
25777
25827
  "src/targets/trae/merge.ts"() {
25778
25828
  init_target_descriptor();
@@ -25783,11 +25833,11 @@ var init_merge12 = __esm({
25783
25833
  [TRAE_MCP_FILE, TRAE_GLOBAL_MCP_FILE],
25784
25834
  CANONICAL_MCP_SERVER_KEYS
25785
25835
  );
25786
- mergeHooks4 = ownedJsonKeysMerger(
25836
+ mergeHooks3 = ownedJsonKeysMerger(
25787
25837
  [TRAE_HOOKS_FILE, TRAE_GLOBAL_HOOKS_FILE],
25788
25838
  ["version", "hooks"]
25789
25839
  );
25790
- mergeTraeOutput = firstMerger([mergeMcp6, mergeHooks4]);
25840
+ mergeTraeOutput = firstMerger([mergeMcp6, mergeHooks3]);
25791
25841
  }
25792
25842
  });
25793
25843
 
@@ -26104,11 +26154,7 @@ function generateMcp24(canonical, ctx) {
26104
26154
  const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
26105
26155
  return [{ path, content }];
26106
26156
  }
26107
- function generateIgnore25(canonical) {
26108
- if (canonical.ignore.length === 0) return [];
26109
- return [{ path: WARP_IGNORE_FILE, content: canonical.ignore.join("\n") }];
26110
- }
26111
- var generateRules31, generatePermissions24, generateHooks21;
26157
+ var generateRules31, generatePermissions24, generateHooks21, generateIgnore25;
26112
26158
  var init_generator34 = __esm({
26113
26159
  "src/targets/warp/generator.ts"() {
26114
26160
  init_managed_blocks();
@@ -26117,9 +26163,11 @@ var init_generator34 = __esm({
26117
26163
  init_projected_agent_skill();
26118
26164
  init_command_skill();
26119
26165
  init_constants30();
26166
+ init_ignore_output();
26120
26167
  generateRules31 = (canonical) => embeddedRootRule(canonical, WARP_TARGET, WARP_ROOT_FILE);
26121
26168
  generatePermissions24 = NO_OUTPUTS;
26122
26169
  generateHooks21 = NO_OUTPUTS;
26170
+ generateIgnore25 = ignoreOutput(WARP_IGNORE_FILE);
26123
26171
  }
26124
26172
  });
26125
26173
 
@@ -26744,13 +26792,12 @@ var init_rules4 = __esm({
26744
26792
  });
26745
26793
 
26746
26794
  // src/targets/windsurf/generator/ignore.ts
26747
- function generateIgnore26(canonical) {
26748
- if (!canonical.ignore || canonical.ignore.length === 0) return [];
26749
- return [{ path: CODEIUM_IGNORE, content: canonical.ignore.join("\n") }];
26750
- }
26795
+ var generateIgnore26;
26751
26796
  var init_ignore3 = __esm({
26752
26797
  "src/targets/windsurf/generator/ignore.ts"() {
26753
26798
  init_constants34();
26799
+ init_ignore_output();
26800
+ generateIgnore26 = ignoreOutput(CODEIUM_IGNORE);
26754
26801
  }
26755
26802
  });
26756
26803
 
@@ -26816,7 +26863,7 @@ function canonicalHookEventName(event) {
26816
26863
  if (KNOWN_CANONICAL_HOOK_EVENTS.includes(event)) return event;
26817
26864
  return WINDSURF_TO_CANONICAL.get(event) ?? null;
26818
26865
  }
26819
- var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_TO_CANONICAL;
26866
+ var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_HOOK_CONTEXT_EVENTS, WINDSURF_TO_CANONICAL;
26820
26867
  var init_hook_events = __esm({
26821
26868
  "src/targets/windsurf/hook-events.ts"() {
26822
26869
  init_hook_types();
@@ -26829,6 +26876,7 @@ var init_hook_events = __esm({
26829
26876
  "SubagentStop",
26830
26877
  ...BEST_EFFORT_HOOK_EVENTS
26831
26878
  ];
26879
+ WINDSURF_HOOK_CONTEXT_EVENTS = [];
26832
26880
  WINDSURF_TO_CANONICAL = new Map(
26833
26881
  KNOWN_CANONICAL_HOOK_EVENTS.map((event) => [windsurfEventName(event), event])
26834
26882
  );
@@ -26854,12 +26902,12 @@ function toWindsurfHooks(hooks) {
26854
26902
  return result2;
26855
26903
  }
26856
26904
  function generateHooks22(canonical) {
26857
- if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
26905
+ if (!canonical.hooks) return [];
26858
26906
  const hooks = toWindsurfHooks(canonical.hooks);
26859
26907
  if (Object.keys(hooks).length === 0) return [];
26860
26908
  return [{ path: WINDSURF_HOOKS_FILE, content: JSON.stringify({ hooks }, null, 2) }];
26861
26909
  }
26862
- var init_hooks5 = __esm({
26910
+ var init_hooks6 = __esm({
26863
26911
  "src/targets/windsurf/generator/hooks.ts"() {
26864
26912
  init_hook_command();
26865
26913
  init_constants34();
@@ -26911,7 +26959,7 @@ var init_generator35 = __esm({
26911
26959
  init_workflows();
26912
26960
  init_agents4();
26913
26961
  init_mcp4();
26914
- init_hooks5();
26962
+ init_hooks6();
26915
26963
  init_skills4();
26916
26964
  init_permissions6();
26917
26965
  }
@@ -27249,7 +27297,7 @@ var init_importer32 = __esm({
27249
27297
  });
27250
27298
 
27251
27299
  // src/targets/windsurf/merge.ts
27252
- var mergeMcp7, mergeHooks5, mergeWindsurfOutput;
27300
+ var mergeMcp7, mergeHooks4, mergeWindsurfOutput;
27253
27301
  var init_merge14 = __esm({
27254
27302
  "src/targets/windsurf/merge.ts"() {
27255
27303
  init_target_descriptor();
@@ -27257,11 +27305,11 @@ var init_merge14 = __esm({
27257
27305
  init_mcp_servers_merge();
27258
27306
  init_constants34();
27259
27307
  mergeMcp7 = mcpServersJsonMerger([WINDSURF_GLOBAL_MCP_FILE], CANONICAL_MCP_SERVER_KEYS);
27260
- mergeHooks5 = ownedJsonKeysMerger(
27308
+ mergeHooks4 = ownedJsonKeysMerger(
27261
27309
  [WINDSURF_HOOKS_FILE, WINDSURF_GLOBAL_HOOKS_FILE],
27262
27310
  ["hooks"]
27263
27311
  );
27264
- mergeWindsurfOutput = firstMerger([mergeMcp7, mergeHooks5]);
27312
+ mergeWindsurfOutput = firstMerger([mergeMcp7, mergeHooks4]);
27265
27313
  }
27266
27314
  });
27267
27315
  function lintRules32(canonical, projectRoot, _projectFiles) {
@@ -27361,6 +27409,7 @@ var init_windsurf2 = __esm({
27361
27409
  init_merge14();
27362
27410
  init_linter32();
27363
27411
  init_lint31();
27412
+ init_hook_events();
27364
27413
  init_import_map_builders();
27365
27414
  init_conversions();
27366
27415
  init_projected_agent_skill();
@@ -27492,6 +27541,7 @@ var init_windsurf2 = __esm({
27492
27541
  },
27493
27542
  emptyImportMessage: "No Windsurf config found (.windsurfrules, .windsurf/rules, .windsurfignore, or .codeiumignore).",
27494
27543
  supportsConversion: { agents: true },
27544
+ hookContextEvents: WINDSURF_HOOK_CONTEXT_EVENTS,
27495
27545
  lintRules: lintRules32,
27496
27546
  lint: {
27497
27547
  commands: lintCommands10,
@@ -29712,10 +29762,10 @@ function ruleSlug(r) {
29712
29762
  function mergeByKey(base, overlay, key) {
29713
29763
  return [...new Map([...base, ...overlay].map((item) => [key(item), item])).values()];
29714
29764
  }
29715
- function mergeCanonicalFiles(base, overlay) {
29765
+ function mergeCanonicalFiles(base, overlay, options = {}) {
29716
29766
  const mcp = mergeMcp(base.mcp, overlay.mcp);
29717
29767
  const permissions = mergePermissions(base.permissions, overlay.permissions);
29718
- const hooks = mergeHooks(base.hooks, overlay.hooks);
29768
+ const hooks = options.hooks === "combine" ? combineHooks(base.hooks, overlay.hooks) : overrideHooks(base.hooks, overlay.hooks);
29719
29769
  const ignore = mergeUniqueStrings(base.ignore, overlay.ignore);
29720
29770
  return {
29721
29771
  rules: mergeByKey(base.rules, overlay.rules, ruleSlug),
@@ -29754,17 +29804,31 @@ function mergeUniqueStrings(base, overlay) {
29754
29804
  }
29755
29805
  return merged;
29756
29806
  }
29757
- function mergeHooks(base, overlay) {
29807
+ function overrideHooks(base, overlay) {
29758
29808
  if (!base && !overlay) return null;
29759
29809
  const result2 = {};
29760
- const keys = /* @__PURE__ */ new Set([...Object.keys(base ?? {}), ...Object.keys(overlay ?? {})]);
29761
- for (const k of keys) {
29810
+ for (const k of hookEvents(base, overlay)) {
29762
29811
  const o = overlay?.[k];
29763
- const b = base?.[k];
29764
- result2[k] = o !== void 0 && o.length > 0 ? o : b ?? [];
29812
+ result2[k] = o !== void 0 && o.length > 0 ? o : base?.[k] ?? [];
29813
+ }
29814
+ return result2;
29815
+ }
29816
+ function combineHooks(first, then) {
29817
+ if (!first && !then) return null;
29818
+ const result2 = {};
29819
+ for (const k of hookEvents(first, then)) {
29820
+ const kept = first?.[k] ?? [];
29821
+ const defined = new Set(kept.map(hookKey));
29822
+ result2[k] = [...kept, ...(then?.[k] ?? []).filter((entry) => !defined.has(hookKey(entry)))];
29765
29823
  }
29766
29824
  return result2;
29767
29825
  }
29826
+ function hookEvents(a, b) {
29827
+ return [.../* @__PURE__ */ new Set([...Object.keys(a ?? {}), ...Object.keys(b ?? {})])];
29828
+ }
29829
+ function hookKey(entry) {
29830
+ return JSON.stringify([entry.type ?? "command", entry.matcher, entry.command]);
29831
+ }
29768
29832
 
29769
29833
  // src/config/resolve/native-format-detector.ts
29770
29834
  init_fs();
@@ -30705,7 +30769,7 @@ async function loadPacksCanonical(abDir) {
30705
30769
  const canonical = await loadPackCanonical(packDir);
30706
30770
  const filtered = filterCanonicalByFeatures(canonical, meta.features);
30707
30771
  const picked = applyExtendPick(filtered, meta.features, meta.pick, meta.name);
30708
- merged = mergeCanonicalFiles(merged, picked);
30772
+ merged = mergeCanonicalFiles(merged, picked, { hooks: "combine" });
30709
30773
  }
30710
30774
  return merged;
30711
30775
  }
@@ -30756,9 +30820,10 @@ async function loadCanonicalWithExtends(config, configDir, options = {}, canonic
30756
30820
  merged = mergeCanonicalFiles(merged, picked);
30757
30821
  }
30758
30822
  const packsCanonical = await loadPacksCanonical(canonicalDir);
30759
- merged = mergeCanonicalFiles(merged, packsCanonical);
30823
+ merged = mergeCanonicalFiles(merged, packsCanonical, { hooks: "combine" });
30760
30824
  const localCanonical = await loadCanonicalFiles(canonicalDir);
30761
30825
  merged = mergeCanonicalFiles(merged, localCanonical);
30826
+ merged = { ...merged, hooks: combineHooks(merged.hooks, packsCanonical.hooks) };
30762
30827
  return { canonical: merged, resolvedExtends };
30763
30828
  }
30764
30829