agentsmesh 0.40.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/CHANGELOG.md +75 -0
- package/README.md +1 -1
- package/dist/canonical.js +299 -238
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +271 -332
- package/dist/engine.d.ts +7 -8
- package/dist/engine.js +771 -276
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1733 -521
- package/dist/index.js.map +1 -1
- package/dist/{init-B1qdo3Dl.d.ts → init-DruMEhnc.d.ts} +97 -42
- package/dist/lessons.d.ts +7 -4
- package/dist/lessons.js +2091 -613
- package/dist/lessons.js.map +1 -1
- package/dist/{target-descriptor-CvTJyDxd.d.ts → target-descriptor-CMV6vxVE.d.ts} +7 -0
- package/dist/targets.d.ts +2 -2
- package/dist/targets.js +265 -219
- package/dist/targets.js.map +1 -1
- package/package.json +3 -2
package/dist/engine.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { parse, stringify, parseDocument, isMap, Document, isSeq, isScalar, Scalar, Pair, YAMLSeq } from 'yaml';
|
|
3
1
|
import { existsSync, readFileSync, constants, readdirSync, realpathSync, statSync } from 'fs';
|
|
4
2
|
import { basename, join, dirname, relative, extname, win32, posix, sep, resolve } from 'path';
|
|
3
|
+
import { parse, stringify, parseDocument, isMap, Document, isSeq, isScalar, Scalar, Pair, YAMLSeq } from 'yaml';
|
|
4
|
+
import { z } from 'zod';
|
|
5
5
|
import { readFile, rm, mkdir, readdir, lstat, open, access, stat, realpath, rename, writeFile, mkdtemp, cp } from 'fs/promises';
|
|
6
6
|
import { setTimeout } from 'timers/promises';
|
|
7
7
|
import { randomUUID, createHash } from 'crypto';
|
|
@@ -9,7 +9,7 @@ import picomatch from 'picomatch';
|
|
|
9
9
|
import { parse as parse$1, stringify as stringify$1 } from 'smol-toml';
|
|
10
10
|
import { Buffer } from 'buffer';
|
|
11
11
|
import { homedir, tmpdir } from 'os';
|
|
12
|
-
import { execFile } from 'child_process';
|
|
12
|
+
import { execFile, spawnSync } from 'child_process';
|
|
13
13
|
import { fileURLToPath, pathToFileURL, URL as URL$1 } from 'url';
|
|
14
14
|
import { promisify } from 'util';
|
|
15
15
|
import * as tar from 'tar';
|
|
@@ -24,6 +24,21 @@ var __export = (target34, all) => {
|
|
|
24
24
|
for (var name in all)
|
|
25
25
|
__defProp(target34, name, { get: all[name], enumerable: true });
|
|
26
26
|
};
|
|
27
|
+
var init_cli_invocation = __esm({
|
|
28
|
+
"src/lessons/cli-invocation.ts"() {
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
function isRecallHookCommand(command) {
|
|
32
|
+
return typeof command === "string" && command.includes(RECALL_HOOK_COMMAND);
|
|
33
|
+
}
|
|
34
|
+
var RECALL_SUBCOMMAND, RECALL_HOOK_COMMAND;
|
|
35
|
+
var init_recall_hook_scaffold = __esm({
|
|
36
|
+
"src/lessons/recall-hook-scaffold.ts"() {
|
|
37
|
+
init_cli_invocation();
|
|
38
|
+
RECALL_SUBCOMMAND = "lessons hook";
|
|
39
|
+
RECALL_HOOK_COMMAND = `agentsmesh ${RECALL_SUBCOMMAND}`;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
27
42
|
function capabilityLevel(capability) {
|
|
28
43
|
return typeof capability === "string" ? capability : capability.level;
|
|
29
44
|
}
|
|
@@ -183,6 +198,7 @@ var init_target_descriptor_schema = __esm({
|
|
|
183
198
|
emitScopedSettings: z.function().optional(),
|
|
184
199
|
mergeGeneratedOutputContent: z.function().optional(),
|
|
185
200
|
postProcessHookOutputs: z.function().optional(),
|
|
201
|
+
hookContextEvents: z.array(z.string()).optional(),
|
|
186
202
|
preservesManualActivation: z.boolean().optional()
|
|
187
203
|
}).passthrough();
|
|
188
204
|
targetDescriptorSchema = targetDescriptorSchemaBase.superRefine((value, ctx) => {
|
|
@@ -578,12 +594,6 @@ var init_guards = __esm({
|
|
|
578
594
|
"src/utils/types/guards.ts"() {
|
|
579
595
|
}
|
|
580
596
|
});
|
|
581
|
-
var RECALL_HOOK_COMMAND;
|
|
582
|
-
var init_recall_hook_scaffold = __esm({
|
|
583
|
-
"src/lessons/recall-hook-scaffold.ts"() {
|
|
584
|
-
RECALL_HOOK_COMMAND = "agentsmesh lessons hook";
|
|
585
|
-
}
|
|
586
|
-
});
|
|
587
597
|
|
|
588
598
|
// src/core/hook-types.ts
|
|
589
599
|
function isBestEffortHookEvent(event, entries) {
|
|
@@ -911,8 +921,10 @@ function executableModeFor(path) {
|
|
|
911
921
|
}
|
|
912
922
|
function normalizeTextPayload(path, content) {
|
|
913
923
|
if (!shouldNormalizeLineEndings(path)) return content;
|
|
914
|
-
|
|
915
|
-
|
|
924
|
+
return normalizeLineEndings(stripBom(content));
|
|
925
|
+
}
|
|
926
|
+
function stripBom(text) {
|
|
927
|
+
return text.startsWith(UTF8_BOM) ? text.slice(UTF8_BOM.length) : text;
|
|
916
928
|
}
|
|
917
929
|
var UTF8_BOM, TEXT_EXTENSIONS, TEXT_DOTFILES, BINARY_EXTENSIONS, EXECUTABLE_SCRIPT_EXTENSIONS;
|
|
918
930
|
var init_fs_text_encoding = __esm({
|
|
@@ -2110,6 +2122,15 @@ var init_constants = __esm({
|
|
|
2110
2122
|
}
|
|
2111
2123
|
});
|
|
2112
2124
|
|
|
2125
|
+
// src/targets/catalog/ignore-output.ts
|
|
2126
|
+
function ignoreOutput(path) {
|
|
2127
|
+
return (canonical) => canonical.ignore.length === 0 ? [] : [{ path, content: canonical.ignore.join("\n") }];
|
|
2128
|
+
}
|
|
2129
|
+
var init_ignore_output = __esm({
|
|
2130
|
+
"src/targets/catalog/ignore-output.ts"() {
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2113
2134
|
// src/targets/aider/generator.ts
|
|
2114
2135
|
function buildAiderConventions(canonical) {
|
|
2115
2136
|
const root = canonical.rules.find((rule) => rule.root);
|
|
@@ -2139,11 +2160,7 @@ function generateAgents(canonical) {
|
|
|
2139
2160
|
content: serializeProjectedAgentSkill(agent)
|
|
2140
2161
|
}));
|
|
2141
2162
|
}
|
|
2142
|
-
|
|
2143
|
-
if (canonical.ignore.length === 0) return [];
|
|
2144
|
-
return [{ path: AIDER_IGNORE, content: canonical.ignore.join("\n") }];
|
|
2145
|
-
}
|
|
2146
|
-
var generateMcp, generatePermissions;
|
|
2163
|
+
var generateIgnore, generateMcp, generatePermissions;
|
|
2147
2164
|
var init_generator = __esm({
|
|
2148
2165
|
"src/targets/aider/generator.ts"() {
|
|
2149
2166
|
init_no_outputs();
|
|
@@ -2152,6 +2169,8 @@ var init_generator = __esm({
|
|
|
2152
2169
|
init_projected_agent_skill();
|
|
2153
2170
|
init_command_skill();
|
|
2154
2171
|
init_constants();
|
|
2172
|
+
init_ignore_output();
|
|
2173
|
+
generateIgnore = ignoreOutput(AIDER_IGNORE);
|
|
2155
2174
|
generateMcp = NO_OUTPUTS;
|
|
2156
2175
|
generatePermissions = NO_OUTPUTS;
|
|
2157
2176
|
}
|
|
@@ -7045,10 +7064,6 @@ function generateAgents4(canonical) {
|
|
|
7045
7064
|
content: serializeAntigravityAgent(agent)
|
|
7046
7065
|
}));
|
|
7047
7066
|
}
|
|
7048
|
-
function generateIgnore3(canonical) {
|
|
7049
|
-
if (canonical.ignore.length === 0) return [];
|
|
7050
|
-
return [{ path: ANTIGRAVITY_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
7051
|
-
}
|
|
7052
7067
|
function renderAntigravityGlobalInstructions(canonical) {
|
|
7053
7068
|
const root = canonical.rules.find((rule) => rule.root);
|
|
7054
7069
|
const nonRootRules = canonical.rules.filter((rule) => {
|
|
@@ -7063,7 +7078,7 @@ function generateHooks2(canonical) {
|
|
|
7063
7078
|
if (Object.keys(hooks).length === 0) return [];
|
|
7064
7079
|
return [{ path: ANTIGRAVITY_HOOKS_FILE, content: JSON.stringify(hooks, null, 2) }];
|
|
7065
7080
|
}
|
|
7066
|
-
var generatePermissions3;
|
|
7081
|
+
var generateIgnore3, generatePermissions3;
|
|
7067
7082
|
var init_generator4 = __esm({
|
|
7068
7083
|
"src/targets/antigravity/generator.ts"() {
|
|
7069
7084
|
init_no_outputs();
|
|
@@ -7072,6 +7087,8 @@ var init_generator4 = __esm({
|
|
|
7072
7087
|
init_hooks_format2();
|
|
7073
7088
|
init_agents_format();
|
|
7074
7089
|
init_constants5();
|
|
7090
|
+
init_ignore_output();
|
|
7091
|
+
generateIgnore3 = ignoreOutput(ANTIGRAVITY_IGNORE_FILE);
|
|
7075
7092
|
generatePermissions3 = NO_OUTPUTS;
|
|
7076
7093
|
}
|
|
7077
7094
|
});
|
|
@@ -8665,16 +8682,14 @@ function generateHooks3(canonical) {
|
|
|
8665
8682
|
const content = JSON.stringify({ hooks: claudeHooks }, null, 2);
|
|
8666
8683
|
return [{ path: CLAUDE_SETTINGS, content }];
|
|
8667
8684
|
}
|
|
8668
|
-
|
|
8669
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
8670
|
-
const content = canonical.ignore.join("\n");
|
|
8671
|
-
return [{ path: CLAUDE_IGNORE, content }];
|
|
8672
|
-
}
|
|
8685
|
+
var generateIgnore5;
|
|
8673
8686
|
var init_generator6 = __esm({
|
|
8674
8687
|
"src/targets/claude-code/generator.ts"() {
|
|
8675
8688
|
init_markdown();
|
|
8676
8689
|
init_constants7();
|
|
8677
8690
|
init_hooks_format2();
|
|
8691
|
+
init_ignore_output();
|
|
8692
|
+
generateIgnore5 = ignoreOutput(CLAUDE_IGNORE);
|
|
8678
8693
|
}
|
|
8679
8694
|
});
|
|
8680
8695
|
function ruleSectionTitle(rule) {
|
|
@@ -10493,11 +10508,7 @@ function generateMcp5(canonical) {
|
|
|
10493
10508
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
10494
10509
|
return [{ path: CODEBUFF_MCP_FILE, content: serializeCodebuffMcp(canonical.mcp) }];
|
|
10495
10510
|
}
|
|
10496
|
-
|
|
10497
|
-
if (canonical.ignore.length === 0) return [];
|
|
10498
|
-
return [{ path: CODEBUFF_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
10499
|
-
}
|
|
10500
|
-
var generateAgents8, generateHooks5, generatePermissions6;
|
|
10511
|
+
var generateIgnore7, generateAgents8, generateHooks5, generatePermissions6;
|
|
10501
10512
|
var init_generator8 = __esm({
|
|
10502
10513
|
"src/targets/codebuff/generator.ts"() {
|
|
10503
10514
|
init_no_outputs();
|
|
@@ -10507,6 +10518,8 @@ var init_generator8 = __esm({
|
|
|
10507
10518
|
init_nested_rules();
|
|
10508
10519
|
init_mcp_format2();
|
|
10509
10520
|
init_constants9();
|
|
10521
|
+
init_ignore_output();
|
|
10522
|
+
generateIgnore7 = ignoreOutput(CODEBUFF_IGNORE_FILE);
|
|
10510
10523
|
generateAgents8 = NO_OUTPUTS;
|
|
10511
10524
|
generateHooks5 = NO_OUTPUTS;
|
|
10512
10525
|
generatePermissions6 = NO_OUTPUTS;
|
|
@@ -13019,53 +13032,37 @@ var init_mcp_generator = __esm({
|
|
|
13019
13032
|
}
|
|
13020
13033
|
});
|
|
13021
13034
|
|
|
13022
|
-
// src/targets/copilot/hook-entry.ts
|
|
13023
|
-
function hasHookCommand2(entry) {
|
|
13024
|
-
return hasHookCommand(entry);
|
|
13025
|
-
}
|
|
13026
|
-
var init_hook_entry = __esm({
|
|
13027
|
-
"src/targets/copilot/hook-entry.ts"() {
|
|
13028
|
-
init_hook_command();
|
|
13029
|
-
}
|
|
13030
|
-
});
|
|
13031
|
-
|
|
13032
13035
|
// src/targets/copilot/hook-format.ts
|
|
13033
|
-
function
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
}
|
|
13036
|
+
function copilotHookGroups(hooks) {
|
|
13037
|
+
return Object.entries(hooks ?? {}).flatMap(([event, entries]) => {
|
|
13038
|
+
const copilotEvent = CANONICAL_TO_COPILOT.get(event);
|
|
13039
|
+
if (!copilotEvent || !Array.isArray(entries)) return [];
|
|
13040
|
+
const kept = entries.filter(
|
|
13041
|
+
(entry) => typeof entry === "object" && entry !== null && hasHookCommand(entry)
|
|
13042
|
+
);
|
|
13043
|
+
return kept.length > 0 ? [{ event, copilotEvent, entries: kept }] : [];
|
|
13044
|
+
});
|
|
13045
|
+
}
|
|
13046
|
+
function wrapperScriptName(event, index) {
|
|
13047
|
+
return `${event.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase()}-${index}.sh`;
|
|
13046
13048
|
}
|
|
13047
13049
|
function buildCopilotHooksObject(hooks) {
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
(entry) => typeof entry === "object" && entry !== null && hasHookCommand2(entry)
|
|
13055
|
-
).map((entry, index) => {
|
|
13056
|
-
const safePhase = event.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
13050
|
+
const groups = copilotHookGroups(hooks);
|
|
13051
|
+
if (groups.length === 0) return null;
|
|
13052
|
+
return Object.fromEntries(
|
|
13053
|
+
groups.map(({ event, copilotEvent, entries }) => [
|
|
13054
|
+
copilotEvent,
|
|
13055
|
+
entries.map((entry, index) => {
|
|
13057
13056
|
const hook = {
|
|
13058
13057
|
type: "command",
|
|
13059
|
-
bash: `./scripts/${
|
|
13058
|
+
bash: `./scripts/${wrapperScriptName(event, index)}`
|
|
13060
13059
|
};
|
|
13061
13060
|
if (entry.matcher && entry.matcher !== "*") hook.matcher = entry.matcher;
|
|
13062
13061
|
if (entry.timeout !== void 0) hook.timeoutSec = Math.ceil(entry.timeout / 1e3);
|
|
13063
13062
|
return hook;
|
|
13064
|
-
})
|
|
13065
|
-
|
|
13066
|
-
})
|
|
13063
|
+
})
|
|
13064
|
+
])
|
|
13067
13065
|
);
|
|
13068
|
-
return Object.keys(result2).length > 0 ? result2 : null;
|
|
13069
13066
|
}
|
|
13070
13067
|
function generateHooks8(canonical) {
|
|
13071
13068
|
const hooks = buildCopilotHooksObject(canonical.hooks);
|
|
@@ -13077,10 +13074,24 @@ function generateHooks8(canonical) {
|
|
|
13077
13074
|
}
|
|
13078
13075
|
];
|
|
13079
13076
|
}
|
|
13077
|
+
var COPILOT_HOOK_CONTEXT_EVENTS, CANONICAL_TO_COPILOT;
|
|
13080
13078
|
var init_hook_format = __esm({
|
|
13081
13079
|
"src/targets/copilot/hook-format.ts"() {
|
|
13082
13080
|
init_constants32();
|
|
13083
|
-
|
|
13081
|
+
init_hook_command();
|
|
13082
|
+
COPILOT_HOOK_CONTEXT_EVENTS = [
|
|
13083
|
+
"SessionStart",
|
|
13084
|
+
"PostToolUse",
|
|
13085
|
+
"PostToolUseFailure"
|
|
13086
|
+
];
|
|
13087
|
+
CANONICAL_TO_COPILOT = /* @__PURE__ */ new Map([
|
|
13088
|
+
["PreToolUse", "preToolUse"],
|
|
13089
|
+
["PostToolUse", "postToolUse"],
|
|
13090
|
+
["PostToolUseFailure", "postToolUseFailure"],
|
|
13091
|
+
["Notification", "notification"],
|
|
13092
|
+
["UserPromptSubmit", "userPromptSubmitted"],
|
|
13093
|
+
["SessionStart", "sessionStart"]
|
|
13094
|
+
]);
|
|
13084
13095
|
}
|
|
13085
13096
|
});
|
|
13086
13097
|
function ruleSlug2(source) {
|
|
@@ -13186,18 +13197,7 @@ var init_generator12 = __esm({
|
|
|
13186
13197
|
}
|
|
13187
13198
|
});
|
|
13188
13199
|
function mapCopilotHookEvent(event) {
|
|
13189
|
-
|
|
13190
|
-
case "preToolUse":
|
|
13191
|
-
return "PreToolUse";
|
|
13192
|
-
case "postToolUse":
|
|
13193
|
-
return "PostToolUse";
|
|
13194
|
-
case "notification":
|
|
13195
|
-
return "Notification";
|
|
13196
|
-
case "userPromptSubmitted":
|
|
13197
|
-
return "UserPromptSubmit";
|
|
13198
|
-
default:
|
|
13199
|
-
return null;
|
|
13200
|
-
}
|
|
13200
|
+
return COPILOT_TO_CANONICAL.get(event) ?? null;
|
|
13201
13201
|
}
|
|
13202
13202
|
function extractMatcher(comment) {
|
|
13203
13203
|
if (typeof comment !== "string") return "*";
|
|
@@ -13285,11 +13285,16 @@ async function importHooks(projectRoot, results, options = {}) {
|
|
|
13285
13285
|
feature: "hooks"
|
|
13286
13286
|
});
|
|
13287
13287
|
}
|
|
13288
|
+
var COPILOT_TO_CANONICAL;
|
|
13288
13289
|
var init_hook_parser = __esm({
|
|
13289
13290
|
"src/targets/copilot/hook-parser.ts"() {
|
|
13290
13291
|
init_canonical_paths();
|
|
13291
13292
|
init_fs();
|
|
13292
13293
|
init_constants32();
|
|
13294
|
+
init_hook_format();
|
|
13295
|
+
COPILOT_TO_CANONICAL = new Map(
|
|
13296
|
+
[...CANONICAL_TO_COPILOT].map(([canonical, copilot]) => [copilot, canonical])
|
|
13297
|
+
);
|
|
13293
13298
|
}
|
|
13294
13299
|
});
|
|
13295
13300
|
async function importSkills2(projectRoot, results, normalize, skillsDirRel = COPILOT_SKILLS_DIR) {
|
|
@@ -13526,7 +13531,7 @@ function lintCommands4(canonical) {
|
|
|
13526
13531
|
}
|
|
13527
13532
|
function lintHooks9(canonical) {
|
|
13528
13533
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
13529
|
-
const supported = [
|
|
13534
|
+
const supported = [...CANONICAL_TO_COPILOT.keys()];
|
|
13530
13535
|
const diagnostics = unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
13531
13536
|
(event) => createUnsupportedHookWarning(event, "copilot", supported, {
|
|
13532
13537
|
unsupportedBy: "Copilot hooks"
|
|
@@ -13549,11 +13554,9 @@ function lintHooks9(canonical) {
|
|
|
13549
13554
|
var init_lint10 = __esm({
|
|
13550
13555
|
"src/targets/copilot/lint.ts"() {
|
|
13551
13556
|
init_helpers();
|
|
13557
|
+
init_hook_format();
|
|
13552
13558
|
}
|
|
13553
13559
|
});
|
|
13554
|
-
function safePhaseName(phase) {
|
|
13555
|
-
return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
13556
|
-
}
|
|
13557
13560
|
function toRepoRelative(projectRoot, sourcePath) {
|
|
13558
13561
|
const repoRelative = relative(projectRoot, sourcePath).replace(/\\/g, "/");
|
|
13559
13562
|
if (!repoRelative || repoRelative.startsWith("../")) return null;
|
|
@@ -13581,9 +13584,6 @@ async function buildAssetOutput(projectRoot, command, hooksDirRel) {
|
|
|
13581
13584
|
rewrittenCommand: rewriteWrapperCommand(command, repoRelative)
|
|
13582
13585
|
};
|
|
13583
13586
|
}
|
|
13584
|
-
function wrapperPath(event, index, hooksDirRel) {
|
|
13585
|
-
return `${hooksDirRel}/scripts/${safePhaseName(event)}-${index}.sh`;
|
|
13586
|
-
}
|
|
13587
13587
|
function safeShellLine2(value) {
|
|
13588
13588
|
return value.replace(/[\r\n]+/g, " ");
|
|
13589
13589
|
}
|
|
@@ -13598,15 +13598,13 @@ function buildWrapper(command, matcher) {
|
|
|
13598
13598
|
].join("\n");
|
|
13599
13599
|
}
|
|
13600
13600
|
async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel = COPILOT_HOOKS_DIR) {
|
|
13601
|
-
|
|
13601
|
+
const groups = copilotHookGroups(canonical.hooks);
|
|
13602
|
+
if (groups.length === 0) return outputs;
|
|
13602
13603
|
const wrapperOutputs = [];
|
|
13603
13604
|
const assetOutputs = /* @__PURE__ */ new Map();
|
|
13604
|
-
for (const
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
for (const entry of entries) {
|
|
13608
|
-
if (!hasHookCommand2(entry)) continue;
|
|
13609
|
-
const scriptPath = wrapperPath(event, index, hooksDirRel);
|
|
13605
|
+
for (const { event, entries } of groups) {
|
|
13606
|
+
for (const [index, entry] of entries.entries()) {
|
|
13607
|
+
const scriptPath = `${hooksDirRel}/scripts/${wrapperScriptName(event, index)}`;
|
|
13610
13608
|
let command = entry.command;
|
|
13611
13609
|
const asset = await buildAssetOutput(projectRoot, entry.command, hooksDirRel);
|
|
13612
13610
|
if (asset) {
|
|
@@ -13620,7 +13618,6 @@ async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel
|
|
|
13620
13618
|
'set -eu\nHOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n'
|
|
13621
13619
|
);
|
|
13622
13620
|
wrapperOutputs.push({ path: scriptPath, content: wrapper });
|
|
13623
|
-
index++;
|
|
13624
13621
|
}
|
|
13625
13622
|
}
|
|
13626
13623
|
return [...outputs, ...wrapperOutputs, ...assetOutputs.values()];
|
|
@@ -13630,7 +13627,7 @@ var init_hook_assets = __esm({
|
|
|
13630
13627
|
"src/targets/copilot/hook-assets.ts"() {
|
|
13631
13628
|
init_fs();
|
|
13632
13629
|
init_constants32();
|
|
13633
|
-
|
|
13630
|
+
init_hook_format();
|
|
13634
13631
|
SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
|
|
13635
13632
|
}
|
|
13636
13633
|
});
|
|
@@ -13948,6 +13945,7 @@ var init_copilot2 = __esm({
|
|
|
13948
13945
|
init_command_prompt();
|
|
13949
13946
|
init_lint10();
|
|
13950
13947
|
init_hook_assets();
|
|
13948
|
+
init_hook_format();
|
|
13951
13949
|
init_scope_extras2();
|
|
13952
13950
|
init_importer_spec2();
|
|
13953
13951
|
init_capabilities6();
|
|
@@ -14078,6 +14076,7 @@ var init_copilot2 = __esm({
|
|
|
14078
14076
|
permissions: lintPermissions7
|
|
14079
14077
|
},
|
|
14080
14078
|
postProcessHookOutputs: async (projectRoot, canonical, outputs) => addHookScriptAssets(projectRoot, canonical, [...outputs]),
|
|
14079
|
+
hookContextEvents: COPILOT_HOOK_CONTEXT_EVENTS,
|
|
14081
14080
|
mergeGeneratedOutputContent: mergeCopilotMcpJson,
|
|
14082
14081
|
project: project7,
|
|
14083
14082
|
globalSupport: {
|
|
@@ -14165,11 +14164,6 @@ function generatePermissions8(canonical) {
|
|
|
14165
14164
|
});
|
|
14166
14165
|
return [{ path: CRUSH_CONFIG_FILE, content: JSON.stringify(crushConfig, null, 2) }];
|
|
14167
14166
|
}
|
|
14168
|
-
function generateIgnore9(canonical) {
|
|
14169
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
14170
|
-
const content = canonical.ignore.join("\n");
|
|
14171
|
-
return [{ path: CRUSH_IGNORE, content }];
|
|
14172
|
-
}
|
|
14173
14167
|
function buildCrushHooksFromCanonical(canonical) {
|
|
14174
14168
|
if (!canonical.hooks) return {};
|
|
14175
14169
|
const result2 = {};
|
|
@@ -14187,7 +14181,7 @@ function buildCrushHooksFromCanonical(canonical) {
|
|
|
14187
14181
|
}
|
|
14188
14182
|
return result2;
|
|
14189
14183
|
}
|
|
14190
|
-
var generateRules12;
|
|
14184
|
+
var generateRules12, generateIgnore9;
|
|
14191
14185
|
var init_generator13 = __esm({
|
|
14192
14186
|
"src/targets/crush/generator.ts"() {
|
|
14193
14187
|
init_managed_blocks();
|
|
@@ -14196,7 +14190,9 @@ var init_generator13 = __esm({
|
|
|
14196
14190
|
init_command_skill();
|
|
14197
14191
|
init_constants12();
|
|
14198
14192
|
init_config_format();
|
|
14193
|
+
init_ignore_output();
|
|
14199
14194
|
generateRules12 = (canonical) => embeddedRootRule(canonical, CRUSH_TARGET, CRUSH_ROOT_FILE);
|
|
14195
|
+
generateIgnore9 = ignoreOutput(CRUSH_IGNORE);
|
|
14200
14196
|
}
|
|
14201
14197
|
});
|
|
14202
14198
|
async function importFromCrush(projectRoot, options = {}) {
|
|
@@ -14732,7 +14728,7 @@ function cursorHooksToCanonical(hooks) {
|
|
|
14732
14728
|
}
|
|
14733
14729
|
return result2;
|
|
14734
14730
|
}
|
|
14735
|
-
var CANONICAL_TO_CURSOR, CURSOR_TO_CANONICAL;
|
|
14731
|
+
var CANONICAL_TO_CURSOR, CURSOR_HOOK_CONTEXT_EVENTS, CURSOR_TO_CANONICAL;
|
|
14736
14732
|
var init_hook_format2 = __esm({
|
|
14737
14733
|
"src/targets/cursor/hook-format.ts"() {
|
|
14738
14734
|
init_hook_types();
|
|
@@ -14740,6 +14736,7 @@ var init_hook_format2 = __esm({
|
|
|
14740
14736
|
CANONICAL_TO_CURSOR = {
|
|
14741
14737
|
PreToolUse: "preToolUse",
|
|
14742
14738
|
PostToolUse: "postToolUse",
|
|
14739
|
+
PostToolUseFailure: "postToolUseFailure",
|
|
14743
14740
|
UserPromptSubmit: "beforeSubmitPrompt",
|
|
14744
14741
|
SubagentStart: "subagentStart",
|
|
14745
14742
|
SubagentStop: "subagentStop",
|
|
@@ -14748,6 +14745,11 @@ var init_hook_format2 = __esm({
|
|
|
14748
14745
|
SessionEnd: "sessionEnd",
|
|
14749
14746
|
PreCompact: "preCompact"
|
|
14750
14747
|
};
|
|
14748
|
+
CURSOR_HOOK_CONTEXT_EVENTS = [
|
|
14749
|
+
"SessionStart",
|
|
14750
|
+
"PostToolUse",
|
|
14751
|
+
"PostToolUseFailure"
|
|
14752
|
+
];
|
|
14751
14753
|
CURSOR_TO_CANONICAL = new Map(
|
|
14752
14754
|
Object.entries(CANONICAL_TO_CURSOR).map(([canonical, cursor]) => [cursor, canonical])
|
|
14753
14755
|
);
|
|
@@ -14756,7 +14758,7 @@ var init_hook_format2 = __esm({
|
|
|
14756
14758
|
|
|
14757
14759
|
// src/targets/cursor/generator/hooks.ts
|
|
14758
14760
|
function generateHooks10(canonical) {
|
|
14759
|
-
if (!canonical.hooks
|
|
14761
|
+
if (!canonical.hooks) return [];
|
|
14760
14762
|
const cursorHooks = toCursorHooks(canonical.hooks);
|
|
14761
14763
|
if (Object.keys(cursorHooks).length === 0) return [];
|
|
14762
14764
|
const content = JSON.stringify({ version: 1, hooks: cursorHooks }, null, 2);
|
|
@@ -14770,14 +14772,12 @@ var init_hooks3 = __esm({
|
|
|
14770
14772
|
});
|
|
14771
14773
|
|
|
14772
14774
|
// src/targets/cursor/generator/ignore.ts
|
|
14773
|
-
|
|
14774
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
14775
|
-
const content = canonical.ignore.join("\n");
|
|
14776
|
-
return [{ path: CURSOR_IGNORE, content }];
|
|
14777
|
-
}
|
|
14775
|
+
var generateIgnore10;
|
|
14778
14776
|
var init_ignore = __esm({
|
|
14779
14777
|
"src/targets/cursor/generator/ignore.ts"() {
|
|
14780
14778
|
init_constants13();
|
|
14779
|
+
init_ignore_output();
|
|
14780
|
+
generateIgnore10 = ignoreOutput(CURSOR_IGNORE);
|
|
14781
14781
|
}
|
|
14782
14782
|
});
|
|
14783
14783
|
|
|
@@ -15473,6 +15473,7 @@ var init_cursor2 = __esm({
|
|
|
15473
15473
|
init_linter13();
|
|
15474
15474
|
init_import_map_builders();
|
|
15475
15475
|
init_lint12();
|
|
15476
|
+
init_hook_format2();
|
|
15476
15477
|
target13 = {
|
|
15477
15478
|
name: "cursor",
|
|
15478
15479
|
primaryRootInstructionPath: CURSOR_GENERAL_RULE,
|
|
@@ -15594,6 +15595,7 @@ var init_cursor2 = __esm({
|
|
|
15594
15595
|
permissions: "native"
|
|
15595
15596
|
},
|
|
15596
15597
|
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).",
|
|
15598
|
+
hookContextEvents: CURSOR_HOOK_CONTEXT_EVENTS,
|
|
15597
15599
|
lintRules: lintRules13,
|
|
15598
15600
|
lint: {
|
|
15599
15601
|
commands: lintCommands6,
|
|
@@ -16855,25 +16857,127 @@ var init_skills3 = __esm({
|
|
|
16855
16857
|
}
|
|
16856
16858
|
});
|
|
16857
16859
|
|
|
16858
|
-
// src/targets/gemini-cli/
|
|
16859
|
-
function
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16871
|
-
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16860
|
+
// src/targets/gemini-cli/hook-map.ts
|
|
16861
|
+
function geminiHookEvent(event) {
|
|
16862
|
+
return CANONICAL_TO_GEMINI.get(event) ?? null;
|
|
16863
|
+
}
|
|
16864
|
+
function mapGeminiHookEvent(event) {
|
|
16865
|
+
return GEMINI_TO_CANONICAL.get(event) ?? null;
|
|
16866
|
+
}
|
|
16867
|
+
function splitNames(list, separator) {
|
|
16868
|
+
return list.split(separator).map((name) => name.trim()).filter((name) => name.length > 0);
|
|
16869
|
+
}
|
|
16870
|
+
function toGeminiMatcher(geminiEvent, matcher) {
|
|
16871
|
+
if (!TOOL_EVENTS.has(geminiEvent) || !NAME_LIST.test(matcher)) return matcher;
|
|
16872
|
+
const tools = unique(
|
|
16873
|
+
splitNames(matcher, /[|,]/).flatMap((name) => CANONICAL_TO_GEMINI_TOOLS.get(name) ?? [name])
|
|
16874
|
+
);
|
|
16875
|
+
return tools.length > 0 ? `^(?:${tools.join("|")})$` : matcher;
|
|
16876
|
+
}
|
|
16877
|
+
function fromGeminiMatcher(geminiEvent, matcher) {
|
|
16878
|
+
if (!TOOL_EVENTS.has(geminiEvent)) return matcher;
|
|
16879
|
+
const list = ANCHORED_LIST.exec(matcher)?.[1] ?? matcher;
|
|
16880
|
+
if (!NAME_LIST.test(list) || list.includes(",")) return matcher;
|
|
16881
|
+
return unique(
|
|
16882
|
+
splitNames(list, /\|/).map((name) => GEMINI_TO_CANONICAL_TOOLS.get(name) ?? name)
|
|
16883
|
+
).join("|");
|
|
16884
|
+
}
|
|
16885
|
+
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;
|
|
16886
|
+
var init_hook_map = __esm({
|
|
16887
|
+
"src/targets/gemini-cli/hook-map.ts"() {
|
|
16888
|
+
GEMINI_HOOK_CONTEXT_EVENTS = [
|
|
16889
|
+
"UserPromptSubmit",
|
|
16890
|
+
"SessionStart",
|
|
16891
|
+
"PostToolUse"
|
|
16892
|
+
];
|
|
16893
|
+
CANONICAL_TO_GEMINI = /* @__PURE__ */ new Map([
|
|
16894
|
+
["PreToolUse", "BeforeTool"],
|
|
16895
|
+
["PostToolUse", "AfterTool"],
|
|
16896
|
+
["Notification", "Notification"],
|
|
16897
|
+
// BeforeAgent fires after the user submits a prompt and carries `prompt`.
|
|
16898
|
+
["UserPromptSubmit", "BeforeAgent"],
|
|
16899
|
+
// Older mapping, kept so existing SubagentStart hooks still reach Gemini.
|
|
16900
|
+
["SubagentStart", "BeforeAgent"],
|
|
16901
|
+
["SubagentStop", "AfterAgent"],
|
|
16902
|
+
["SessionStart", "SessionStart"]
|
|
16903
|
+
]);
|
|
16904
|
+
GEMINI_TO_CANONICAL = new Map([
|
|
16905
|
+
...[...CANONICAL_TO_GEMINI].map(([canonical, gemini]) => [gemini, canonical]),
|
|
16906
|
+
// BeforeAgent is shared with SubagentStart; import it as the prompt event.
|
|
16907
|
+
["BeforeAgent", "UserPromptSubmit"],
|
|
16908
|
+
// Legacy lowercase names.
|
|
16909
|
+
["preToolUse", "PreToolUse"],
|
|
16910
|
+
["postToolUse", "PostToolUse"],
|
|
16911
|
+
["notification", "Notification"]
|
|
16912
|
+
]);
|
|
16913
|
+
TOOL_EVENTS = /* @__PURE__ */ new Set(["BeforeTool", "AfterTool"]);
|
|
16914
|
+
CANONICAL_TO_GEMINI_TOOLS = /* @__PURE__ */ new Map([
|
|
16915
|
+
["Bash", ["run_shell_command"]],
|
|
16916
|
+
["PowerShell", ["run_shell_command"]],
|
|
16917
|
+
["Edit", ["replace"]],
|
|
16918
|
+
["MultiEdit", ["replace"]],
|
|
16919
|
+
["Write", ["write_file"]],
|
|
16920
|
+
["NotebookEdit", []],
|
|
16921
|
+
["Read", ["read_file", "read_many_files"]],
|
|
16922
|
+
["Grep", ["grep_search"]],
|
|
16923
|
+
["Glob", ["glob"]],
|
|
16924
|
+
["LS", ["list_directory"]],
|
|
16925
|
+
["WebFetch", ["web_fetch"]],
|
|
16926
|
+
["WebSearch", ["google_web_search"]],
|
|
16927
|
+
["TodoWrite", ["write_todos"]]
|
|
16928
|
+
]);
|
|
16929
|
+
GEMINI_TO_CANONICAL_TOOLS = /* @__PURE__ */ new Map([
|
|
16930
|
+
["run_shell_command", "Bash"],
|
|
16931
|
+
["replace", "Edit"],
|
|
16932
|
+
["write_file", "Write"],
|
|
16933
|
+
["read_file", "Read"],
|
|
16934
|
+
["read_many_files", "Read"],
|
|
16935
|
+
["grep_search", "Grep"],
|
|
16936
|
+
["search_file_content", "Grep"],
|
|
16937
|
+
["glob", "Glob"],
|
|
16938
|
+
["list_directory", "LS"],
|
|
16939
|
+
["web_fetch", "WebFetch"],
|
|
16940
|
+
["google_web_search", "WebSearch"],
|
|
16941
|
+
["write_todos", "TodoWrite"]
|
|
16942
|
+
]);
|
|
16943
|
+
NAME_LIST = /^[\w\s,|-]+$/;
|
|
16944
|
+
ANCHORED_LIST = /^\^\(\?:(.*)\)\$$/;
|
|
16945
|
+
unique = (values) => [...new Set(values)];
|
|
16946
|
+
}
|
|
16947
|
+
});
|
|
16948
|
+
|
|
16949
|
+
// src/targets/gemini-cli/generator/hooks.ts
|
|
16950
|
+
function buildGeminiHooks(hooks) {
|
|
16951
|
+
const result2 = {};
|
|
16952
|
+
for (const [event, entries] of Object.entries(hooks ?? {})) {
|
|
16953
|
+
const geminiEvent = geminiHookEvent(event);
|
|
16954
|
+
if (!geminiEvent || !Array.isArray(entries)) continue;
|
|
16955
|
+
for (const entry of entries) {
|
|
16956
|
+
if (typeof entry !== "object" || entry === null || !hasHookCommand(entry)) continue;
|
|
16957
|
+
const list = result2[geminiEvent] ??= [];
|
|
16958
|
+
list.push({
|
|
16959
|
+
matcher: typeof entry.matcher === "string" ? toGeminiMatcher(geminiEvent, entry.matcher) : entry.matcher,
|
|
16960
|
+
hooks: [
|
|
16961
|
+
{
|
|
16962
|
+
name: `${geminiEvent}-${list.length + 1}`,
|
|
16963
|
+
type: "command",
|
|
16964
|
+
command: getHookCommand(entry),
|
|
16965
|
+
timeout: entry.timeout
|
|
16966
|
+
}
|
|
16967
|
+
]
|
|
16968
|
+
});
|
|
16969
|
+
}
|
|
16875
16970
|
}
|
|
16971
|
+
return Object.keys(result2).length > 0 ? result2 : null;
|
|
16876
16972
|
}
|
|
16973
|
+
var init_hooks4 = __esm({
|
|
16974
|
+
"src/targets/gemini-cli/generator/hooks.ts"() {
|
|
16975
|
+
init_hook_command();
|
|
16976
|
+
init_hook_map();
|
|
16977
|
+
}
|
|
16978
|
+
});
|
|
16979
|
+
|
|
16980
|
+
// src/targets/gemini-cli/generator/settings.ts
|
|
16877
16981
|
function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
16878
16982
|
const settings = {};
|
|
16879
16983
|
let hasAnyNativeSettings = false;
|
|
@@ -16885,29 +16989,10 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
|
16885
16989
|
settings.experimental = { enableAgents: true };
|
|
16886
16990
|
hasAnyNativeSettings = true;
|
|
16887
16991
|
}
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
const mappedEntries = entries.filter(
|
|
16893
|
-
(entry) => typeof entry === "object" && entry !== null && hasHookCommand(entry)
|
|
16894
|
-
).map((entry, index) => ({
|
|
16895
|
-
matcher: entry.matcher,
|
|
16896
|
-
hooks: [
|
|
16897
|
-
{
|
|
16898
|
-
name: `${mappedEvent}-${index + 1}`,
|
|
16899
|
-
type: "command",
|
|
16900
|
-
command: getHookCommand(entry),
|
|
16901
|
-
timeout: entry.timeout
|
|
16902
|
-
}
|
|
16903
|
-
]
|
|
16904
|
-
}));
|
|
16905
|
-
return mappedEntries.length > 0 ? [[mappedEvent, mappedEntries]] : [];
|
|
16906
|
-
});
|
|
16907
|
-
if (hookEntries.length > 0) {
|
|
16908
|
-
settings.hooks = Object.fromEntries(hookEntries);
|
|
16909
|
-
hasAnyNativeSettings = true;
|
|
16910
|
-
}
|
|
16992
|
+
const hooks = enabledFeatures.has("hooks") ? buildGeminiHooks(canonical.hooks) : null;
|
|
16993
|
+
if (hooks) {
|
|
16994
|
+
settings.hooks = hooks;
|
|
16995
|
+
hasAnyNativeSettings = true;
|
|
16911
16996
|
}
|
|
16912
16997
|
if (hasAnyNativeSettings) {
|
|
16913
16998
|
settings.context = { fileName: [GEMINI_ROOT, GEMINI_COMPAT_AGENTS] };
|
|
@@ -16917,19 +17002,18 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
|
16917
17002
|
}
|
|
16918
17003
|
var init_settings2 = __esm({
|
|
16919
17004
|
"src/targets/gemini-cli/generator/settings.ts"() {
|
|
16920
|
-
init_hook_command();
|
|
16921
17005
|
init_constants33();
|
|
17006
|
+
init_hooks4();
|
|
16922
17007
|
}
|
|
16923
17008
|
});
|
|
16924
17009
|
|
|
16925
17010
|
// src/targets/gemini-cli/generator/ignore.ts
|
|
16926
|
-
|
|
16927
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
16928
|
-
return [{ path: GEMINI_IGNORE, content: canonical.ignore.join("\n") }];
|
|
16929
|
-
}
|
|
17011
|
+
var generateIgnore13;
|
|
16930
17012
|
var init_ignore2 = __esm({
|
|
16931
17013
|
"src/targets/gemini-cli/generator/ignore.ts"() {
|
|
16932
17014
|
init_constants33();
|
|
17015
|
+
init_ignore_output();
|
|
17016
|
+
generateIgnore13 = ignoreOutput(GEMINI_IGNORE);
|
|
16933
17017
|
}
|
|
16934
17018
|
});
|
|
16935
17019
|
|
|
@@ -17208,27 +17292,6 @@ var init_layout6 = __esm({
|
|
|
17208
17292
|
};
|
|
17209
17293
|
}
|
|
17210
17294
|
});
|
|
17211
|
-
function mapGeminiHookEvent(event) {
|
|
17212
|
-
switch (event) {
|
|
17213
|
-
case "BeforeTool":
|
|
17214
|
-
case "preToolUse":
|
|
17215
|
-
return "PreToolUse";
|
|
17216
|
-
case "AfterTool":
|
|
17217
|
-
case "postToolUse":
|
|
17218
|
-
return "PostToolUse";
|
|
17219
|
-
case "Notification":
|
|
17220
|
-
case "notification":
|
|
17221
|
-
return "Notification";
|
|
17222
|
-
case "BeforeAgent":
|
|
17223
|
-
return "SubagentStart";
|
|
17224
|
-
case "AfterAgent":
|
|
17225
|
-
return "SubagentStop";
|
|
17226
|
-
case "SessionStart":
|
|
17227
|
-
return "SessionStart";
|
|
17228
|
-
default:
|
|
17229
|
-
return null;
|
|
17230
|
-
}
|
|
17231
|
-
}
|
|
17232
17295
|
function parseFlexibleFrontmatter(content) {
|
|
17233
17296
|
const yamlOpen = content.indexOf("---");
|
|
17234
17297
|
const tomlOpen = content.indexOf("+++");
|
|
@@ -17302,7 +17365,7 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
17302
17365
|
(entry) => entry.hooks.filter(
|
|
17303
17366
|
(hook) => hook !== null && typeof hook === "object" && hasHookCommand(hook)
|
|
17304
17367
|
).map((hook) => ({
|
|
17305
|
-
matcher: entry.matcher,
|
|
17368
|
+
matcher: fromGeminiMatcher(event, entry.matcher),
|
|
17306
17369
|
command: getHookCommand(hook),
|
|
17307
17370
|
type: "command",
|
|
17308
17371
|
timeout: typeof hook.timeout === "number" ? hook.timeout : void 0
|
|
@@ -17312,7 +17375,7 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
17312
17375
|
const legacyMapped = value.filter(
|
|
17313
17376
|
(entry) => entry !== null && typeof entry === "object" && typeof entry.matcher === "string" && hasHookCommand(entry)
|
|
17314
17377
|
).map((entry) => ({
|
|
17315
|
-
matcher: entry.matcher,
|
|
17378
|
+
matcher: fromGeminiMatcher(event, entry.matcher),
|
|
17316
17379
|
command: getHookCommand(entry),
|
|
17317
17380
|
type: "command"
|
|
17318
17381
|
}));
|
|
@@ -17341,7 +17404,7 @@ var init_format_helpers_settings = __esm({
|
|
|
17341
17404
|
init_hook_command();
|
|
17342
17405
|
init_fs();
|
|
17343
17406
|
init_constants33();
|
|
17344
|
-
|
|
17407
|
+
init_hook_map();
|
|
17345
17408
|
}
|
|
17346
17409
|
});
|
|
17347
17410
|
async function importGeminiIgnore(projectRoot, results) {
|
|
@@ -17837,14 +17900,7 @@ function lintPermissions10(canonical, options) {
|
|
|
17837
17900
|
}
|
|
17838
17901
|
function lintHooks12(canonical) {
|
|
17839
17902
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
17840
|
-
const supported = [
|
|
17841
|
-
"PreToolUse",
|
|
17842
|
-
"PostToolUse",
|
|
17843
|
-
"Notification",
|
|
17844
|
-
"SubagentStart",
|
|
17845
|
-
"SubagentStop",
|
|
17846
|
-
"SessionStart"
|
|
17847
|
-
];
|
|
17903
|
+
const supported = [...CANONICAL_TO_GEMINI.keys()];
|
|
17848
17904
|
return unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
17849
17905
|
(event) => createUnsupportedHookWarning(event, "gemini-cli", supported)
|
|
17850
17906
|
);
|
|
@@ -17852,6 +17908,7 @@ function lintHooks12(canonical) {
|
|
|
17852
17908
|
var init_lint15 = __esm({
|
|
17853
17909
|
"src/targets/gemini-cli/lint.ts"() {
|
|
17854
17910
|
init_helpers();
|
|
17911
|
+
init_hook_map();
|
|
17855
17912
|
}
|
|
17856
17913
|
});
|
|
17857
17914
|
|
|
@@ -17888,6 +17945,7 @@ var init_gemini_cli2 = __esm({
|
|
|
17888
17945
|
init_import_map_builders();
|
|
17889
17946
|
init_lint15();
|
|
17890
17947
|
init_scoped_settings_emit();
|
|
17948
|
+
init_hook_map();
|
|
17891
17949
|
init_settings();
|
|
17892
17950
|
target16 = {
|
|
17893
17951
|
name: "gemini-cli",
|
|
@@ -17938,6 +17996,7 @@ var init_gemini_cli2 = __esm({
|
|
|
17938
17996
|
permissions: lintPermissions10
|
|
17939
17997
|
},
|
|
17940
17998
|
emitScopedSettings: emitScopedGeminiSettings,
|
|
17999
|
+
hookContextEvents: GEMINI_HOOK_CONTEXT_EVENTS,
|
|
17941
18000
|
mergeGeneratedOutputContent(existing, pending, newContent, resolvedPath) {
|
|
17942
18001
|
const base = pending?.content ?? existing;
|
|
17943
18002
|
if (base !== null && resolvedPath === GEMINI_SETTINGS) {
|
|
@@ -18030,14 +18089,10 @@ function generateAgents17(canonical) {
|
|
|
18030
18089
|
content: serializeProjectedAgentSkill(agent)
|
|
18031
18090
|
}));
|
|
18032
18091
|
}
|
|
18033
|
-
function generateIgnore14(canonical) {
|
|
18034
|
-
if (canonical.ignore.length === 0) return [];
|
|
18035
|
-
return [{ path: GOOSE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
18036
|
-
}
|
|
18037
18092
|
function generateHooks12(canonical) {
|
|
18038
18093
|
return buildWrappedCommandHooks(canonical, GOOSE_HOOKS_FILE);
|
|
18039
18094
|
}
|
|
18040
|
-
var generateRules17, generatePermissions12;
|
|
18095
|
+
var generateRules17, generateIgnore14, generatePermissions12;
|
|
18041
18096
|
var init_generator20 = __esm({
|
|
18042
18097
|
"src/targets/goose/generator.ts"() {
|
|
18043
18098
|
init_managed_blocks();
|
|
@@ -18047,7 +18102,9 @@ var init_generator20 = __esm({
|
|
|
18047
18102
|
init_command_skill();
|
|
18048
18103
|
init_wrapped_command_hooks();
|
|
18049
18104
|
init_constants16();
|
|
18105
|
+
init_ignore_output();
|
|
18050
18106
|
generateRules17 = (canonical) => embeddedRootRule(canonical, GOOSE_TARGET, GOOSE_ROOT_FILE);
|
|
18107
|
+
generateIgnore14 = ignoreOutput(GOOSE_IGNORE);
|
|
18051
18108
|
generatePermissions12 = NO_OUTPUTS;
|
|
18052
18109
|
}
|
|
18053
18110
|
});
|
|
@@ -18952,10 +19009,6 @@ function generateAgents18(canonical) {
|
|
|
18952
19009
|
};
|
|
18953
19010
|
});
|
|
18954
19011
|
}
|
|
18955
|
-
function generateIgnore16(canonical) {
|
|
18956
|
-
if (canonical.ignore.length === 0) return [];
|
|
18957
|
-
return [{ path: JUNIE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
18958
|
-
}
|
|
18959
19012
|
function generateSkills17(canonical) {
|
|
18960
19013
|
return generateEmbeddedSkills(canonical, JUNIE_SKILLS_DIR);
|
|
18961
19014
|
}
|
|
@@ -18967,6 +19020,7 @@ function renderJunieGlobalInstructions(canonical) {
|
|
|
18967
19020
|
});
|
|
18968
19021
|
return appendEmbeddedRulesBlock(root?.body.trim() ?? "", nonRootRules);
|
|
18969
19022
|
}
|
|
19023
|
+
var generateIgnore16;
|
|
18970
19024
|
var init_generator22 = __esm({
|
|
18971
19025
|
"src/targets/junie/generator.ts"() {
|
|
18972
19026
|
init_mcp_servers();
|
|
@@ -18974,7 +19028,9 @@ var init_generator22 = __esm({
|
|
|
18974
19028
|
init_managed_blocks();
|
|
18975
19029
|
init_markdown();
|
|
18976
19030
|
init_constants18();
|
|
19031
|
+
init_ignore_output();
|
|
18977
19032
|
init_global_config2();
|
|
19033
|
+
generateIgnore16 = ignoreOutput(JUNIE_IGNORE);
|
|
18978
19034
|
}
|
|
18979
19035
|
});
|
|
18980
19036
|
|
|
@@ -19390,10 +19446,6 @@ function generateMcp15(canonical) {
|
|
|
19390
19446
|
}
|
|
19391
19447
|
];
|
|
19392
19448
|
}
|
|
19393
|
-
function generateIgnore17(canonical) {
|
|
19394
|
-
if (canonical.ignore.length === 0) return [];
|
|
19395
|
-
return [{ path: KILO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
19396
|
-
}
|
|
19397
19449
|
function generatePermissions15(canonical) {
|
|
19398
19450
|
if (!canonical.permissions) return [];
|
|
19399
19451
|
const { allow, deny } = canonical.permissions;
|
|
@@ -19408,11 +19460,14 @@ function generatePermissions15(canonical) {
|
|
|
19408
19460
|
function generateSkills18(canonical) {
|
|
19409
19461
|
return generateEmbeddedSkills(canonical, KILO_CODE_SKILLS_DIR);
|
|
19410
19462
|
}
|
|
19463
|
+
var generateIgnore17;
|
|
19411
19464
|
var init_generator23 = __esm({
|
|
19412
19465
|
"src/targets/kilo-code/generator.ts"() {
|
|
19413
19466
|
init_embedded_skill();
|
|
19414
19467
|
init_markdown();
|
|
19415
19468
|
init_constants19();
|
|
19469
|
+
init_ignore_output();
|
|
19470
|
+
generateIgnore17 = ignoreOutput(KILO_CODE_IGNORE);
|
|
19416
19471
|
}
|
|
19417
19472
|
});
|
|
19418
19473
|
var kiloNonRootRuleMapper, kiloCommandMapper, kiloAgentMapper;
|
|
@@ -21157,11 +21212,7 @@ function buildKiroAgentOutputs(canonical, rules = []) {
|
|
|
21157
21212
|
function generateAgents21(canonical) {
|
|
21158
21213
|
return buildKiroAgentOutputs(canonical);
|
|
21159
21214
|
}
|
|
21160
|
-
|
|
21161
|
-
if (canonical.ignore.length === 0) return [];
|
|
21162
|
-
return [{ path: KIRO_IGNORE, content: canonical.ignore.join("\n") }];
|
|
21163
|
-
}
|
|
21164
|
-
var generatePermissions17;
|
|
21215
|
+
var generateIgnore18, generatePermissions17;
|
|
21165
21216
|
var init_generator25 = __esm({
|
|
21166
21217
|
"src/targets/kiro/generator.ts"() {
|
|
21167
21218
|
init_no_outputs();
|
|
@@ -21170,6 +21221,8 @@ var init_generator25 = __esm({
|
|
|
21170
21221
|
init_markdown();
|
|
21171
21222
|
init_hook_format3();
|
|
21172
21223
|
init_constants21();
|
|
21224
|
+
init_ignore_output();
|
|
21225
|
+
generateIgnore18 = ignoreOutput(KIRO_IGNORE);
|
|
21173
21226
|
generatePermissions17 = NO_OUTPUTS;
|
|
21174
21227
|
}
|
|
21175
21228
|
});
|
|
@@ -23812,10 +23865,6 @@ function generateMcp19(canonical) {
|
|
|
23812
23865
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
23813
23866
|
return [{ path: QWEN_SETTINGS, content }];
|
|
23814
23867
|
}
|
|
23815
|
-
function generateIgnore21(canonical) {
|
|
23816
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
23817
|
-
return [{ path: QWEN_IGNORE, content: canonical.ignore.join("\n") }];
|
|
23818
|
-
}
|
|
23819
23868
|
function generateHooks18(canonical) {
|
|
23820
23869
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
23821
23870
|
const hooks = buildClaudeHooksObjectFromCanonical(canonical);
|
|
@@ -23833,11 +23882,14 @@ function generatePermissions21(canonical) {
|
|
|
23833
23882
|
if (ask.length > 0) permissions.ask = ask;
|
|
23834
23883
|
return [{ path: QWEN_SETTINGS, content: JSON.stringify({ permissions }, null, 2) }];
|
|
23835
23884
|
}
|
|
23885
|
+
var generateIgnore21;
|
|
23836
23886
|
var init_generator29 = __esm({
|
|
23837
23887
|
"src/targets/qwen-code/generator.ts"() {
|
|
23838
23888
|
init_markdown();
|
|
23839
23889
|
init_hooks_format2();
|
|
23840
23890
|
init_constants25();
|
|
23891
|
+
init_ignore_output();
|
|
23892
|
+
generateIgnore21 = ignoreOutput(QWEN_IGNORE);
|
|
23841
23893
|
}
|
|
23842
23894
|
});
|
|
23843
23895
|
|
|
@@ -25535,10 +25587,6 @@ function generateMcp23(canonical) {
|
|
|
25535
25587
|
}
|
|
25536
25588
|
];
|
|
25537
25589
|
}
|
|
25538
|
-
function generateIgnore24(canonical) {
|
|
25539
|
-
if (canonical.ignore.length === 0) return [];
|
|
25540
|
-
return [{ path: TRAE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
25541
|
-
}
|
|
25542
25590
|
function generateHooks20(canonical) {
|
|
25543
25591
|
if (!canonical.hooks) return [];
|
|
25544
25592
|
const hooks = {};
|
|
@@ -25559,12 +25607,15 @@ function generateHooks20(canonical) {
|
|
|
25559
25607
|
if (Object.keys(hooks).length === 0) return [];
|
|
25560
25608
|
return [{ path: TRAE_HOOKS_FILE, content: JSON.stringify({ version: 1, hooks }, null, 2) }];
|
|
25561
25609
|
}
|
|
25610
|
+
var generateIgnore24;
|
|
25562
25611
|
var init_generator33 = __esm({
|
|
25563
25612
|
"src/targets/trae/generator.ts"() {
|
|
25564
25613
|
init_embedded_skill();
|
|
25565
25614
|
init_markdown();
|
|
25566
25615
|
init_hook_command();
|
|
25567
25616
|
init_constants29();
|
|
25617
|
+
init_ignore_output();
|
|
25618
|
+
generateIgnore24 = ignoreOutput(TRAE_IGNORE);
|
|
25568
25619
|
}
|
|
25569
25620
|
});
|
|
25570
25621
|
|
|
@@ -26271,11 +26322,7 @@ function generateMcp24(canonical, ctx) {
|
|
|
26271
26322
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
26272
26323
|
return [{ path, content }];
|
|
26273
26324
|
}
|
|
26274
|
-
|
|
26275
|
-
if (canonical.ignore.length === 0) return [];
|
|
26276
|
-
return [{ path: WARP_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
26277
|
-
}
|
|
26278
|
-
var generateRules31, generatePermissions24, generateHooks21;
|
|
26325
|
+
var generateRules31, generatePermissions24, generateHooks21, generateIgnore25;
|
|
26279
26326
|
var init_generator34 = __esm({
|
|
26280
26327
|
"src/targets/warp/generator.ts"() {
|
|
26281
26328
|
init_managed_blocks();
|
|
@@ -26284,9 +26331,11 @@ var init_generator34 = __esm({
|
|
|
26284
26331
|
init_projected_agent_skill();
|
|
26285
26332
|
init_command_skill();
|
|
26286
26333
|
init_constants30();
|
|
26334
|
+
init_ignore_output();
|
|
26287
26335
|
generateRules31 = (canonical) => embeddedRootRule(canonical, WARP_TARGET, WARP_ROOT_FILE);
|
|
26288
26336
|
generatePermissions24 = NO_OUTPUTS;
|
|
26289
26337
|
generateHooks21 = NO_OUTPUTS;
|
|
26338
|
+
generateIgnore25 = ignoreOutput(WARP_IGNORE_FILE);
|
|
26290
26339
|
}
|
|
26291
26340
|
});
|
|
26292
26341
|
|
|
@@ -26911,13 +26960,12 @@ var init_rules4 = __esm({
|
|
|
26911
26960
|
});
|
|
26912
26961
|
|
|
26913
26962
|
// src/targets/windsurf/generator/ignore.ts
|
|
26914
|
-
|
|
26915
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
26916
|
-
return [{ path: CODEIUM_IGNORE, content: canonical.ignore.join("\n") }];
|
|
26917
|
-
}
|
|
26963
|
+
var generateIgnore26;
|
|
26918
26964
|
var init_ignore3 = __esm({
|
|
26919
26965
|
"src/targets/windsurf/generator/ignore.ts"() {
|
|
26920
26966
|
init_constants34();
|
|
26967
|
+
init_ignore_output();
|
|
26968
|
+
generateIgnore26 = ignoreOutput(CODEIUM_IGNORE);
|
|
26921
26969
|
}
|
|
26922
26970
|
});
|
|
26923
26971
|
|
|
@@ -26983,7 +27031,7 @@ function canonicalHookEventName(event) {
|
|
|
26983
27031
|
if (KNOWN_CANONICAL_HOOK_EVENTS.includes(event)) return event;
|
|
26984
27032
|
return WINDSURF_TO_CANONICAL.get(event) ?? null;
|
|
26985
27033
|
}
|
|
26986
|
-
var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_TO_CANONICAL;
|
|
27034
|
+
var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_HOOK_CONTEXT_EVENTS, WINDSURF_TO_CANONICAL;
|
|
26987
27035
|
var init_hook_events = __esm({
|
|
26988
27036
|
"src/targets/windsurf/hook-events.ts"() {
|
|
26989
27037
|
init_hook_types();
|
|
@@ -26996,6 +27044,7 @@ var init_hook_events = __esm({
|
|
|
26996
27044
|
"SubagentStop",
|
|
26997
27045
|
...BEST_EFFORT_HOOK_EVENTS
|
|
26998
27046
|
];
|
|
27047
|
+
WINDSURF_HOOK_CONTEXT_EVENTS = [];
|
|
26999
27048
|
WINDSURF_TO_CANONICAL = new Map(
|
|
27000
27049
|
KNOWN_CANONICAL_HOOK_EVENTS.map((event) => [windsurfEventName(event), event])
|
|
27001
27050
|
);
|
|
@@ -27021,12 +27070,12 @@ function toWindsurfHooks(hooks) {
|
|
|
27021
27070
|
return result2;
|
|
27022
27071
|
}
|
|
27023
27072
|
function generateHooks22(canonical) {
|
|
27024
|
-
if (!canonical.hooks
|
|
27073
|
+
if (!canonical.hooks) return [];
|
|
27025
27074
|
const hooks = toWindsurfHooks(canonical.hooks);
|
|
27026
27075
|
if (Object.keys(hooks).length === 0) return [];
|
|
27027
27076
|
return [{ path: WINDSURF_HOOKS_FILE, content: JSON.stringify({ hooks }, null, 2) }];
|
|
27028
27077
|
}
|
|
27029
|
-
var
|
|
27078
|
+
var init_hooks5 = __esm({
|
|
27030
27079
|
"src/targets/windsurf/generator/hooks.ts"() {
|
|
27031
27080
|
init_hook_command();
|
|
27032
27081
|
init_constants34();
|
|
@@ -27078,7 +27127,7 @@ var init_generator35 = __esm({
|
|
|
27078
27127
|
init_workflows();
|
|
27079
27128
|
init_agents4();
|
|
27080
27129
|
init_mcp4();
|
|
27081
|
-
|
|
27130
|
+
init_hooks5();
|
|
27082
27131
|
init_skills4();
|
|
27083
27132
|
init_permissions6();
|
|
27084
27133
|
}
|
|
@@ -27197,7 +27246,7 @@ async function parseHooks(hooksPath, onParseError) {
|
|
|
27197
27246
|
return result2;
|
|
27198
27247
|
}
|
|
27199
27248
|
var VALID_TYPES;
|
|
27200
|
-
var
|
|
27249
|
+
var init_hooks6 = __esm({
|
|
27201
27250
|
"src/canonical/features/hooks.ts"() {
|
|
27202
27251
|
init_syntax_error();
|
|
27203
27252
|
init_fs();
|
|
@@ -27278,7 +27327,7 @@ var WILDCARD_MATCHER;
|
|
|
27278
27327
|
var init_importer_hooks2 = __esm({
|
|
27279
27328
|
"src/targets/windsurf/importer-hooks.ts"() {
|
|
27280
27329
|
init_canonical_paths();
|
|
27281
|
-
|
|
27330
|
+
init_hooks6();
|
|
27282
27331
|
init_fs();
|
|
27283
27332
|
init_constants34();
|
|
27284
27333
|
init_hook_events();
|
|
@@ -27579,6 +27628,7 @@ var init_windsurf2 = __esm({
|
|
|
27579
27628
|
init_merge14();
|
|
27580
27629
|
init_linter32();
|
|
27581
27630
|
init_lint31();
|
|
27631
|
+
init_hook_events();
|
|
27582
27632
|
init_import_map_builders();
|
|
27583
27633
|
init_conversions();
|
|
27584
27634
|
init_projected_agent_skill();
|
|
@@ -27710,6 +27760,7 @@ var init_windsurf2 = __esm({
|
|
|
27710
27760
|
},
|
|
27711
27761
|
emptyImportMessage: "No Windsurf config found (.windsurfrules, .windsurf/rules, .windsurfignore, or .codeiumignore).",
|
|
27712
27762
|
supportsConversion: { agents: true },
|
|
27763
|
+
hookContextEvents: WINDSURF_HOOK_CONTEXT_EVENTS,
|
|
27713
27764
|
lintRules: lintRules32,
|
|
27714
27765
|
lint: {
|
|
27715
27766
|
commands: lintCommands10,
|
|
@@ -28854,6 +28905,23 @@ var init_builtin_targets = __esm({
|
|
|
28854
28905
|
}
|
|
28855
28906
|
});
|
|
28856
28907
|
|
|
28908
|
+
// src/targets/catalog/recall-hook-targets.ts
|
|
28909
|
+
init_recall_hook_scaffold();
|
|
28910
|
+
init_builtin_targets();
|
|
28911
|
+
init_registry();
|
|
28912
|
+
function withTargetRecallHooks(canonical, target34) {
|
|
28913
|
+
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
28914
|
+
const contextEvents = descriptor34?.hookContextEvents;
|
|
28915
|
+
if (contextEvents === void 0 || canonical.hooks === null) return canonical;
|
|
28916
|
+
const hooks = {};
|
|
28917
|
+
for (const [event, entries] of Object.entries(canonical.hooks)) {
|
|
28918
|
+
if (!Array.isArray(entries)) continue;
|
|
28919
|
+
const kept = contextEvents.includes(event) ? entries : entries.filter((entry) => !isRecallHookCommand(entry?.command));
|
|
28920
|
+
if (kept.length > 0) hooks[event] = kept;
|
|
28921
|
+
}
|
|
28922
|
+
return { ...canonical, hooks };
|
|
28923
|
+
}
|
|
28924
|
+
|
|
28857
28925
|
// src/core/generate/engine.ts
|
|
28858
28926
|
init_builtin_targets();
|
|
28859
28927
|
init_registry();
|
|
@@ -29756,11 +29824,12 @@ async function generateHooksFeature(results, targets, canonical, projectRoot, sc
|
|
|
29756
29824
|
const gen = resolveTargetFeatureGenerator(target34, "hooks", config, scope) ?? getDescriptor(target34)?.generators.generateHooks;
|
|
29757
29825
|
if (!gen) continue;
|
|
29758
29826
|
const ctx = featureContext(target34, "hooks", scope);
|
|
29759
|
-
|
|
29827
|
+
const projected = withTargetRecallHooks(canonical, target34);
|
|
29828
|
+
let outputs = [...gen(projected, ctx)];
|
|
29760
29829
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29761
29830
|
const post = descriptor34?.postProcessHookOutputs;
|
|
29762
29831
|
if (post) {
|
|
29763
|
-
outputs = [...await post(projectRoot,
|
|
29832
|
+
outputs = [...await post(projectRoot, projected, outputs)];
|
|
29764
29833
|
}
|
|
29765
29834
|
const options = outputMergeOptions(target34);
|
|
29766
29835
|
for (const out2 of outputs) {
|
|
@@ -29773,7 +29842,7 @@ async function generateScopedSettingsFeature(results, targets, canonical, projec
|
|
|
29773
29842
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29774
29843
|
const emit = descriptor34?.emitScopedSettings;
|
|
29775
29844
|
if (!emit) continue;
|
|
29776
|
-
const outputs = emit(canonical, scope, enabledFeatures);
|
|
29845
|
+
const outputs = emit(withTargetRecallHooks(canonical, target34), scope, enabledFeatures);
|
|
29777
29846
|
if (outputs.length === 0) continue;
|
|
29778
29847
|
const options = outputMergeOptions(target34);
|
|
29779
29848
|
for (const out2 of outputs) {
|
|
@@ -29816,7 +29885,12 @@ async function generate(ctx) {
|
|
|
29816
29885
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29817
29886
|
const scopeExtras = descriptor34?.globalSupport?.scopeExtras;
|
|
29818
29887
|
if (scopeExtras) {
|
|
29819
|
-
const extras = await scopeExtras(
|
|
29888
|
+
const extras = await scopeExtras(
|
|
29889
|
+
withTargetRecallHooks(canonical, target34),
|
|
29890
|
+
projectRoot,
|
|
29891
|
+
scope,
|
|
29892
|
+
enabledFeatures
|
|
29893
|
+
);
|
|
29820
29894
|
await emitScopeExtras(results, target34, extras, projectRoot);
|
|
29821
29895
|
}
|
|
29822
29896
|
}
|
|
@@ -31123,7 +31197,7 @@ async function parsePermissions(permissionsPath, onParseError) {
|
|
|
31123
31197
|
}
|
|
31124
31198
|
|
|
31125
31199
|
// src/canonical/load/loader.ts
|
|
31126
|
-
|
|
31200
|
+
init_hooks6();
|
|
31127
31201
|
|
|
31128
31202
|
// src/canonical/features/ignore.ts
|
|
31129
31203
|
init_fs();
|
|
@@ -31172,10 +31246,10 @@ function ruleSlug4(r) {
|
|
|
31172
31246
|
function mergeByKey(base, overlay, key) {
|
|
31173
31247
|
return [...new Map([...base, ...overlay].map((item) => [key(item), item])).values()];
|
|
31174
31248
|
}
|
|
31175
|
-
function mergeCanonicalFiles(base, overlay) {
|
|
31249
|
+
function mergeCanonicalFiles(base, overlay, options = {}) {
|
|
31176
31250
|
const mcp = mergeMcp7(base.mcp, overlay.mcp);
|
|
31177
31251
|
const permissions = mergePermissions2(base.permissions, overlay.permissions);
|
|
31178
|
-
const hooks =
|
|
31252
|
+
const hooks = options.hooks === "combine" ? combineHooks(base.hooks, overlay.hooks) : overrideHooks(base.hooks, overlay.hooks);
|
|
31179
31253
|
const ignore = mergeUniqueStrings(base.ignore, overlay.ignore);
|
|
31180
31254
|
return {
|
|
31181
31255
|
rules: mergeByKey(base.rules, overlay.rules, ruleSlug4),
|
|
@@ -31214,17 +31288,31 @@ function mergeUniqueStrings(base, overlay) {
|
|
|
31214
31288
|
}
|
|
31215
31289
|
return merged;
|
|
31216
31290
|
}
|
|
31217
|
-
function
|
|
31291
|
+
function overrideHooks(base, overlay) {
|
|
31218
31292
|
if (!base && !overlay) return null;
|
|
31219
31293
|
const result2 = {};
|
|
31220
|
-
const
|
|
31221
|
-
for (const k of keys) {
|
|
31294
|
+
for (const k of hookEvents(base, overlay)) {
|
|
31222
31295
|
const o = overlay?.[k];
|
|
31223
|
-
|
|
31224
|
-
|
|
31296
|
+
result2[k] = o !== void 0 && o.length > 0 ? o : base?.[k] ?? [];
|
|
31297
|
+
}
|
|
31298
|
+
return result2;
|
|
31299
|
+
}
|
|
31300
|
+
function combineHooks(first, then) {
|
|
31301
|
+
if (!first && !then) return null;
|
|
31302
|
+
const result2 = {};
|
|
31303
|
+
for (const k of hookEvents(first, then)) {
|
|
31304
|
+
const kept = first?.[k] ?? [];
|
|
31305
|
+
const defined = new Set(kept.map(hookKey));
|
|
31306
|
+
result2[k] = [...kept, ...(then?.[k] ?? []).filter((entry) => !defined.has(hookKey(entry)))];
|
|
31225
31307
|
}
|
|
31226
31308
|
return result2;
|
|
31227
31309
|
}
|
|
31310
|
+
function hookEvents(a, b) {
|
|
31311
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(a ?? {}), ...Object.keys(b ?? {})])];
|
|
31312
|
+
}
|
|
31313
|
+
function hookKey(entry) {
|
|
31314
|
+
return JSON.stringify([entry.type ?? "command", entry.matcher, entry.command]);
|
|
31315
|
+
}
|
|
31228
31316
|
|
|
31229
31317
|
// src/config/resolve/native-format-detector.ts
|
|
31230
31318
|
init_fs();
|
|
@@ -31995,7 +32083,7 @@ function gateExtendElevatedArtifacts(canonical, ext) {
|
|
|
31995
32083
|
});
|
|
31996
32084
|
}
|
|
31997
32085
|
init_mcp();
|
|
31998
|
-
|
|
32086
|
+
init_hooks6();
|
|
31999
32087
|
|
|
32000
32088
|
// src/install/pack/pack-reader.ts
|
|
32001
32089
|
init_fs();
|
|
@@ -32082,7 +32170,7 @@ async function loadPacksCanonical(abDir) {
|
|
|
32082
32170
|
const canonical = await loadPackCanonical(packDir);
|
|
32083
32171
|
const filtered = filterCanonicalByFeatures(canonical, meta.features);
|
|
32084
32172
|
const picked = applyExtendPick(filtered, meta.features, meta.pick, meta.name);
|
|
32085
|
-
merged = mergeCanonicalFiles(merged, picked);
|
|
32173
|
+
merged = mergeCanonicalFiles(merged, picked, { hooks: "combine" });
|
|
32086
32174
|
}
|
|
32087
32175
|
return merged;
|
|
32088
32176
|
}
|
|
@@ -32133,9 +32221,10 @@ async function loadCanonicalWithExtends(config, configDir, options = {}, canonic
|
|
|
32133
32221
|
merged = mergeCanonicalFiles(merged, picked);
|
|
32134
32222
|
}
|
|
32135
32223
|
const packsCanonical = await loadPacksCanonical(canonicalDir);
|
|
32136
|
-
merged = mergeCanonicalFiles(merged, packsCanonical);
|
|
32224
|
+
merged = mergeCanonicalFiles(merged, packsCanonical, { hooks: "combine" });
|
|
32137
32225
|
const localCanonical = await loadCanonicalFiles(canonicalDir);
|
|
32138
32226
|
merged = mergeCanonicalFiles(merged, localCanonical);
|
|
32227
|
+
merged = { ...merged, hooks: combineHooks(merged.hooks, packsCanonical.hooks) };
|
|
32139
32228
|
return { canonical: merged, resolvedExtends };
|
|
32140
32229
|
}
|
|
32141
32230
|
|
|
@@ -32414,6 +32503,9 @@ function lintRuleScopeInversion(input) {
|
|
|
32414
32503
|
}
|
|
32415
32504
|
return out2;
|
|
32416
32505
|
}
|
|
32506
|
+
|
|
32507
|
+
// src/lessons/graph-store.ts
|
|
32508
|
+
init_fs_text_encoding();
|
|
32417
32509
|
var VersionSchema = z.union([z.literal(1), z.literal(2)]);
|
|
32418
32510
|
var IdSchema = z.string().regex(/^[a-z0-9-]+$/, "id must be kebab-case");
|
|
32419
32511
|
var DateSchema = z.string().regex(
|
|
@@ -32457,13 +32549,13 @@ function parseGraph(raw) {
|
|
|
32457
32549
|
}
|
|
32458
32550
|
|
|
32459
32551
|
// src/lessons/graph-store.ts
|
|
32460
|
-
var
|
|
32552
|
+
var LESSONS_GRAPH_PATH = ".agentsmesh/lessons/lessons.json";
|
|
32461
32553
|
function graphFilePath(projectRoot) {
|
|
32462
|
-
return resolve(projectRoot,
|
|
32554
|
+
return resolve(projectRoot, LESSONS_GRAPH_PATH);
|
|
32463
32555
|
}
|
|
32464
32556
|
function loadLessonsGraph(projectRoot) {
|
|
32465
32557
|
const raw = readFileSync(graphFilePath(projectRoot), "utf8");
|
|
32466
|
-
return parseGraph(JSON.parse(raw));
|
|
32558
|
+
return parseGraph(JSON.parse(stripBom(raw)));
|
|
32467
32559
|
}
|
|
32468
32560
|
var BASE_REL = ".agentsmesh/lessons";
|
|
32469
32561
|
function lessonsPaths(projectRoot) {
|
|
@@ -32480,9 +32572,76 @@ function lessonsPaths(projectRoot) {
|
|
|
32480
32572
|
function toRelPath(projectRoot, absolute) {
|
|
32481
32573
|
return relative(projectRoot, absolute).split(sep).join("/");
|
|
32482
32574
|
}
|
|
32575
|
+
var MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
32576
|
+
function runGit2(cwd, args, timeoutMs) {
|
|
32577
|
+
const r = spawnSync("git", [...args], {
|
|
32578
|
+
cwd,
|
|
32579
|
+
encoding: "utf8",
|
|
32580
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
32581
|
+
timeout: timeoutMs,
|
|
32582
|
+
windowsHide: true
|
|
32583
|
+
});
|
|
32584
|
+
const status = r.error === void 0 ? r.status ?? -1 : -1;
|
|
32585
|
+
return { status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
32586
|
+
}
|
|
32587
|
+
|
|
32588
|
+
// src/lessons/git-path-history.ts
|
|
32589
|
+
var GIT_SCAN_TIMEOUT_MS = 3e3;
|
|
32590
|
+
var cache = /* @__PURE__ */ new Map();
|
|
32591
|
+
function readGitPathHistory(projectRoot) {
|
|
32592
|
+
if (!cache.has(projectRoot)) cache.set(projectRoot, scanGitPathHistory(projectRoot));
|
|
32593
|
+
return cache.get(projectRoot) ?? null;
|
|
32594
|
+
}
|
|
32595
|
+
var LOG_ARGS = [
|
|
32596
|
+
"log",
|
|
32597
|
+
"HEAD",
|
|
32598
|
+
"--relative",
|
|
32599
|
+
"-M",
|
|
32600
|
+
"--diff-filter=DR",
|
|
32601
|
+
"--name-status",
|
|
32602
|
+
"-z",
|
|
32603
|
+
"--no-color",
|
|
32604
|
+
"--no-show-signature",
|
|
32605
|
+
"--pretty=format:"
|
|
32606
|
+
];
|
|
32607
|
+
function scanGitPathHistory(projectRoot, timeoutMs = GIT_SCAN_TIMEOUT_MS) {
|
|
32608
|
+
const tracked = runGit2(projectRoot, ["ls-files", "-z"], timeoutMs);
|
|
32609
|
+
if (tracked.status !== 0) return null;
|
|
32610
|
+
const log = runGit2(projectRoot, LOG_ARGS, timeoutMs);
|
|
32611
|
+
if (log.status !== 0) return null;
|
|
32612
|
+
return {
|
|
32613
|
+
tracked: new Set(tracked.stdout.split("\0").filter(Boolean)),
|
|
32614
|
+
...parseRemovals(log.stdout)
|
|
32615
|
+
};
|
|
32616
|
+
}
|
|
32617
|
+
function parseRemovals(out2) {
|
|
32618
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
32619
|
+
const renamedAway = /* @__PURE__ */ new Set();
|
|
32620
|
+
const tokens = out2.split("\0");
|
|
32621
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
32622
|
+
const status = tokens[i] ?? "";
|
|
32623
|
+
const path = tokens[i + 1] ?? "";
|
|
32624
|
+
if (status.startsWith("D")) {
|
|
32625
|
+
if (path !== "") deleted.add(path);
|
|
32626
|
+
i += 1;
|
|
32627
|
+
} else if (status.startsWith("R")) {
|
|
32628
|
+
if (path !== "") renamedAway.add(path);
|
|
32629
|
+
i += 2;
|
|
32630
|
+
}
|
|
32631
|
+
}
|
|
32632
|
+
return { deleted, renamedAway };
|
|
32633
|
+
}
|
|
32634
|
+
|
|
32635
|
+
// src/lessons/project-files.ts
|
|
32483
32636
|
var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
32484
32637
|
var MAX_FILES = 2e5;
|
|
32485
|
-
function
|
|
32638
|
+
function projectFilesOf(paths2, gitHistory) {
|
|
32639
|
+
return Object.assign(new Set(paths2), { gitHistory });
|
|
32640
|
+
}
|
|
32641
|
+
function gitHistoryOf(paths2) {
|
|
32642
|
+
return paths2.gitHistory?.() ?? null;
|
|
32643
|
+
}
|
|
32644
|
+
function listProjectFiles(projectRoot, maxFiles = MAX_FILES) {
|
|
32486
32645
|
const out2 = /* @__PURE__ */ new Set();
|
|
32487
32646
|
try {
|
|
32488
32647
|
const stack = [projectRoot];
|
|
@@ -32493,14 +32652,14 @@ function listProjectFiles(projectRoot) {
|
|
|
32493
32652
|
if (!SKIP_DIRS.has(entry.name)) stack.push(join(dir, entry.name));
|
|
32494
32653
|
} else if (entry.isFile()) {
|
|
32495
32654
|
out2.add(toRelPath(projectRoot, join(dir, entry.name)));
|
|
32496
|
-
if (out2.size >
|
|
32655
|
+
if (out2.size > maxFiles) return null;
|
|
32497
32656
|
}
|
|
32498
32657
|
}
|
|
32499
32658
|
}
|
|
32500
32659
|
} catch {
|
|
32501
32660
|
return null;
|
|
32502
32661
|
}
|
|
32503
|
-
return out2;
|
|
32662
|
+
return projectFilesOf(out2, () => readGitPathHistory(projectRoot));
|
|
32504
32663
|
}
|
|
32505
32664
|
|
|
32506
32665
|
// src/lessons/validate-checks.ts
|
|
@@ -32677,10 +32836,307 @@ function collectOrphans(graph, findings) {
|
|
|
32677
32836
|
}
|
|
32678
32837
|
}
|
|
32679
32838
|
}
|
|
32839
|
+
|
|
32840
|
+
// src/lessons/glob-expand.ts
|
|
32841
|
+
var MARK = "\0";
|
|
32842
|
+
var LED = "";
|
|
32843
|
+
var MAX_EXPANSIONS = 64;
|
|
32844
|
+
function fail(reason) {
|
|
32845
|
+
throw new Error(reason);
|
|
32846
|
+
}
|
|
32847
|
+
function skipClass(s, i) {
|
|
32848
|
+
const end = s.indexOf("]", i + 1);
|
|
32849
|
+
return end === -1 ? i + 1 : end + 1;
|
|
32850
|
+
}
|
|
32851
|
+
function markLedStars(body) {
|
|
32852
|
+
let out2 = "";
|
|
32853
|
+
let depth = 0;
|
|
32854
|
+
for (let i = 0; i < body.length; ) {
|
|
32855
|
+
const c2 = body[i];
|
|
32856
|
+
if (c2 === "[") {
|
|
32857
|
+
const end = skipClass(body, i);
|
|
32858
|
+
out2 += body.slice(i, end);
|
|
32859
|
+
i = end;
|
|
32860
|
+
continue;
|
|
32861
|
+
}
|
|
32862
|
+
if (c2 === "{") depth += 1;
|
|
32863
|
+
if (c2 === "}" && depth > 0) depth -= 1;
|
|
32864
|
+
const prev = body[i - 1];
|
|
32865
|
+
if (c2 === "*" && prev === "." && depth > 0) fail(".* inside {\u2026} is not supported");
|
|
32866
|
+
const segmentStart = i === 0 || prev === "/";
|
|
32867
|
+
const afterLeadingDot = prev === "." && (i === 1 || body[i - 2] === "/");
|
|
32868
|
+
const led = c2 === "*" && body[i + 1] !== "*" && prev !== "*" && (segmentStart || afterLeadingDot);
|
|
32869
|
+
out2 += led ? LED : c2;
|
|
32870
|
+
i += 1;
|
|
32871
|
+
}
|
|
32872
|
+
return out2;
|
|
32873
|
+
}
|
|
32874
|
+
function expandBraces(s) {
|
|
32875
|
+
let open2 = -1;
|
|
32876
|
+
for (let i = 0; i < s.length && open2 === -1; ) {
|
|
32877
|
+
if (s[i] === "[") i = skipClass(s, i);
|
|
32878
|
+
else if (s[i] === "}") fail("unbalanced }");
|
|
32879
|
+
else if (s[i] === "{") open2 = i;
|
|
32880
|
+
else i += 1;
|
|
32881
|
+
}
|
|
32882
|
+
if (open2 === -1) return [s];
|
|
32883
|
+
const options = [];
|
|
32884
|
+
let depth = 0;
|
|
32885
|
+
let start = open2 + 1;
|
|
32886
|
+
let close = -1;
|
|
32887
|
+
for (let i = open2 + 1; i < s.length && close === -1; ) {
|
|
32888
|
+
const c2 = s[i];
|
|
32889
|
+
if (c2 === "[") {
|
|
32890
|
+
i = skipClass(s, i);
|
|
32891
|
+
continue;
|
|
32892
|
+
}
|
|
32893
|
+
if (c2 === "{") depth += 1;
|
|
32894
|
+
else if (c2 === "}" && depth > 0) depth -= 1;
|
|
32895
|
+
else if (c2 === "}") close = i;
|
|
32896
|
+
else if (c2 === "," && depth === 0) {
|
|
32897
|
+
options.push(s.slice(start, i));
|
|
32898
|
+
start = i + 1;
|
|
32899
|
+
}
|
|
32900
|
+
i += 1;
|
|
32901
|
+
}
|
|
32902
|
+
if (close === -1) fail("unclosed {");
|
|
32903
|
+
if (options.length === 0)
|
|
32904
|
+
fail("brace groups need a comma, e.g. {a,b} (ranges are not supported)");
|
|
32905
|
+
options.push(s.slice(start, close));
|
|
32906
|
+
const suffixes = expandBraces(s.slice(close + 1));
|
|
32907
|
+
const out2 = [];
|
|
32908
|
+
for (const option of options) {
|
|
32909
|
+
for (const head of expandBraces(option)) {
|
|
32910
|
+
for (const tail of suffixes) {
|
|
32911
|
+
out2.push(s.slice(0, open2) + MARK + head + MARK + tail);
|
|
32912
|
+
if (out2.length > MAX_EXPANSIONS) fail(`more than ${MAX_EXPANSIONS} brace expansions`);
|
|
32913
|
+
}
|
|
32914
|
+
}
|
|
32915
|
+
}
|
|
32916
|
+
return out2;
|
|
32917
|
+
}
|
|
32918
|
+
|
|
32919
|
+
// src/lessons/glob-parse.ts
|
|
32920
|
+
var MAX_GLOB_LENGTH = 256;
|
|
32921
|
+
function parseGlob(pattern) {
|
|
32922
|
+
try {
|
|
32923
|
+
return parseOrThrow(pattern);
|
|
32924
|
+
} catch (err) {
|
|
32925
|
+
return err instanceof Error ? err.message : String(err);
|
|
32926
|
+
}
|
|
32927
|
+
}
|
|
32928
|
+
function parseOrThrow(pattern) {
|
|
32929
|
+
if (pattern.length > MAX_GLOB_LENGTH) fail(`longer than ${MAX_GLOB_LENGTH} characters`);
|
|
32930
|
+
if (pattern.includes("\\")) fail("backslash escapes are not supported (use / as separator)");
|
|
32931
|
+
if (/["\u0000-\u001f]/.test(pattern)) fail("quotes and control characters are not supported");
|
|
32932
|
+
if (/[()|]/.test(pattern.replace(/\[[^\]/]*\]/g, ""))) {
|
|
32933
|
+
fail("extglobs and (\u2026)/| groups are not supported (use {a,b})");
|
|
32934
|
+
}
|
|
32935
|
+
if (/[[\]{}]\+/.test(pattern)) fail("+ after a class or brace is a regex quantifier");
|
|
32936
|
+
const negated = pattern.startsWith("!");
|
|
32937
|
+
let body = negated ? pattern.slice(1) : pattern;
|
|
32938
|
+
if (body.startsWith("./")) body = body.slice(2);
|
|
32939
|
+
if (body.startsWith("!") || body.startsWith("./")) fail("use a single leading ! and ./");
|
|
32940
|
+
if (body === "") fail("empty pattern");
|
|
32941
|
+
const fastPath = !negated && (body === "*.*" || body === "**/*.*");
|
|
32942
|
+
if (fastPath) body = `${body.slice(0, -1)}?*`;
|
|
32943
|
+
return { negated, alternatives: expandBraces(markLedStars(body)).map(parseAlternative) };
|
|
32944
|
+
}
|
|
32945
|
+
function parseAlternative(alt) {
|
|
32946
|
+
const raw = alt.split("/");
|
|
32947
|
+
const out2 = [];
|
|
32948
|
+
raw.forEach((segment, i) => {
|
|
32949
|
+
if (segment.includes("**")) {
|
|
32950
|
+
if (segment !== "**") fail("** must be a whole segment, outside {\u2026} (use * in a segment)");
|
|
32951
|
+
if (out2.at(-1)?.k === "globstar") return;
|
|
32952
|
+
const before = raw[i - 1] ?? "";
|
|
32953
|
+
const trailing = raw.slice(i + 1).every((s) => s === "**");
|
|
32954
|
+
const min1 = trailing && (before.endsWith("*") || before.endsWith(LED));
|
|
32955
|
+
out2.push({ k: "globstar", min1 });
|
|
32956
|
+
return;
|
|
32957
|
+
}
|
|
32958
|
+
const tokens = tokenize(segment, alt);
|
|
32959
|
+
const guarded = segment.includes(LED);
|
|
32960
|
+
const literal = tokens.every((t) => t.k === "lit") ? tokens.map((t) => t.k === "lit" ? t.ch : "").join("") : null;
|
|
32961
|
+
const matchesEmpty = segment !== "" && !guarded && tokens.every((t) => t.k === "star");
|
|
32962
|
+
out2.push({ k: "segment", tokens, literal, guarded, matchesEmpty });
|
|
32963
|
+
});
|
|
32964
|
+
return out2;
|
|
32965
|
+
}
|
|
32966
|
+
function tokenize(segment, alt) {
|
|
32967
|
+
const tokens = [];
|
|
32968
|
+
for (let i = 0; i < segment.length; i += 1) {
|
|
32969
|
+
const c2 = segment[i];
|
|
32970
|
+
if (c2 === MARK) continue;
|
|
32971
|
+
if (c2 === "*" || c2 === LED) tokens.push({ k: "star" });
|
|
32972
|
+
else if (c2 === "?") tokens.push({ k: "one" });
|
|
32973
|
+
else if (c2 === "[") {
|
|
32974
|
+
const end = segment.indexOf("]", i + 1);
|
|
32975
|
+
if (end === -1) {
|
|
32976
|
+
if (alt.includes("]")) fail("a [...] class cannot span /");
|
|
32977
|
+
tokens.push({ k: "lit", ch: c2 });
|
|
32978
|
+
continue;
|
|
32979
|
+
}
|
|
32980
|
+
tokens.push(parseClass(segment.slice(i + 1, end)));
|
|
32981
|
+
i = end;
|
|
32982
|
+
} else tokens.push({ k: "lit", ch: c2 });
|
|
32983
|
+
}
|
|
32984
|
+
return tokens;
|
|
32985
|
+
}
|
|
32986
|
+
var CLASS_SPECIAL = /[-*+?.^${}(|)[\]]/;
|
|
32987
|
+
function parseClass(body) {
|
|
32988
|
+
if (body === "") fail("empty [] class");
|
|
32989
|
+
if (body.startsWith("!")) fail("[!...] is not a negation here; use [^...]");
|
|
32990
|
+
if (body.includes("[")) fail("POSIX [:classes:] and nested [ are not supported");
|
|
32991
|
+
const negated = body.startsWith("^");
|
|
32992
|
+
const members = negated ? body.slice(1) : body;
|
|
32993
|
+
if (members === "") fail("empty [^] class");
|
|
32994
|
+
const ranges = [];
|
|
32995
|
+
for (let i = 0; i < members.length; i += 1) {
|
|
32996
|
+
const lo = members[i];
|
|
32997
|
+
const hi = members[i + 2];
|
|
32998
|
+
if (members[i + 1] === "-" && hi !== void 0) {
|
|
32999
|
+
if (hi < lo) fail(`class range out of order: ${lo}-${hi}`);
|
|
33000
|
+
ranges.push([lo, hi]);
|
|
33001
|
+
i += 2;
|
|
33002
|
+
} else ranges.push([lo, lo]);
|
|
33003
|
+
}
|
|
33004
|
+
const inSet = (c2) => ranges.some(([lo, hi]) => c2 >= lo && c2 <= hi);
|
|
33005
|
+
const literal = CLASS_SPECIAL.test(body) ? null : `[${body}]`;
|
|
33006
|
+
return { k: "class", test: negated ? (c2) => c2 !== "/" && !inSet(c2) : inSet, literal };
|
|
33007
|
+
}
|
|
33008
|
+
|
|
33009
|
+
// src/lessons/add-helpers.ts
|
|
32680
33010
|
function normalizeRule(rule) {
|
|
32681
33011
|
return rule.trim().replace(/\s+/g, " ").toLowerCase();
|
|
32682
33012
|
}
|
|
32683
33013
|
|
|
33014
|
+
// src/lessons/glob-dp.ts
|
|
33015
|
+
var isDotSegment = (s) => s === "." || s === "..";
|
|
33016
|
+
function matchSegments(alt, segments, work) {
|
|
33017
|
+
const n = segments.length;
|
|
33018
|
+
let next = new Uint8Array(n + 1);
|
|
33019
|
+
next[n] = 1;
|
|
33020
|
+
for (let i = alt.length - 1; i >= 0; i -= 1) {
|
|
33021
|
+
const seg = alt[i];
|
|
33022
|
+
const cur = new Uint8Array(n + 1);
|
|
33023
|
+
for (let j = n; j >= 0; j -= 1) {
|
|
33024
|
+
if (--work.remaining <= 0) return false;
|
|
33025
|
+
if (seg.k === "globstar") {
|
|
33026
|
+
const eat = j < n && !isDotSegment(segments[j]) && (cur[j + 1] === 1 || next[j + 1] === 1);
|
|
33027
|
+
cur[j] = !seg.min1 && next[j] === 1 || eat ? 1 : 0;
|
|
33028
|
+
} else if (j < n && next[j + 1] === 1) {
|
|
33029
|
+
const text = segments[j];
|
|
33030
|
+
const ok = seg.literal !== null ? text === seg.literal : matchSegment(seg, text, j < n - 1, work);
|
|
33031
|
+
cur[j] = ok ? 1 : 0;
|
|
33032
|
+
}
|
|
33033
|
+
}
|
|
33034
|
+
if (seg.k === "globstar" && i >= 1 && tailMatchesNothing(alt, i + 1)) cur[n] = 1;
|
|
33035
|
+
next = cur;
|
|
33036
|
+
}
|
|
33037
|
+
return next[0] === 1;
|
|
33038
|
+
}
|
|
33039
|
+
function tailMatchesNothing(alt, from) {
|
|
33040
|
+
const empty = alt[from];
|
|
33041
|
+
const rest = alt[from + 1];
|
|
33042
|
+
if (empty?.k !== "segment" || !empty.matchesEmpty) return false;
|
|
33043
|
+
return rest === void 0 || rest.k === "globstar" && !rest.min1 && from + 2 === alt.length;
|
|
33044
|
+
}
|
|
33045
|
+
function matchSegment(seg, text, followedBySlash, work) {
|
|
33046
|
+
if (seg.guarded && (isDotSegment(text) || text === "" && !followedBySlash)) return false;
|
|
33047
|
+
const tokens = seg.tokens;
|
|
33048
|
+
const len = text.length;
|
|
33049
|
+
let next = new Uint8Array(len + 1);
|
|
33050
|
+
next[len] = 1;
|
|
33051
|
+
for (let k = tokens.length - 1; k >= 0; k -= 1) {
|
|
33052
|
+
const tok = tokens[k];
|
|
33053
|
+
const cur = new Uint8Array(len + 1);
|
|
33054
|
+
work.remaining -= len + 1;
|
|
33055
|
+
if (work.remaining <= 0) return false;
|
|
33056
|
+
for (let c2 = len; c2 >= 0; c2 -= 1) {
|
|
33057
|
+
cur[c2] = tokenMatches(tok, text, c2, next, cur) ? 1 : 0;
|
|
33058
|
+
}
|
|
33059
|
+
next = cur;
|
|
33060
|
+
}
|
|
33061
|
+
return next[0] === 1;
|
|
33062
|
+
}
|
|
33063
|
+
function tokenMatches(tok, text, c2, next, cur) {
|
|
33064
|
+
const ch = text[c2];
|
|
33065
|
+
switch (tok.k) {
|
|
33066
|
+
case "star":
|
|
33067
|
+
return next[c2] === 1 || ch !== void 0 && cur[c2 + 1] === 1;
|
|
33068
|
+
case "one":
|
|
33069
|
+
return ch !== void 0 && next[c2 + 1] === 1;
|
|
33070
|
+
case "lit":
|
|
33071
|
+
return ch === tok.ch && next[c2 + 1] === 1;
|
|
33072
|
+
case "class":
|
|
33073
|
+
return ch !== void 0 && tok.test(ch) && next[c2 + 1] === 1 || tok.literal !== null && text.startsWith(tok.literal, c2) && next[c2 + tok.literal.length] === 1;
|
|
33074
|
+
}
|
|
33075
|
+
}
|
|
33076
|
+
|
|
33077
|
+
// src/lessons/glob-safety.ts
|
|
33078
|
+
var MAX_GLOB_PATH_LENGTH = 4096;
|
|
33079
|
+
var MATCH_WORK_LIMIT = 2e5;
|
|
33080
|
+
var CACHE_LIMIT = 2e3;
|
|
33081
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
33082
|
+
function unsafeGlobFinding(triggerId, trigger) {
|
|
33083
|
+
if (trigger.kind !== "file_glob" || trigger.pattern.includes("\\")) return null;
|
|
33084
|
+
const reason = parseGlob(trigger.pattern);
|
|
33085
|
+
if (typeof reason !== "string") return null;
|
|
33086
|
+
return {
|
|
33087
|
+
level: "error",
|
|
33088
|
+
code: "UNSAFE_GLOB_PATTERN",
|
|
33089
|
+
message: `Trigger "${triggerId}" has a file_glob outside the safe glob subset (${trigger.pattern.slice(0, 120)}): ${reason}. Recall treats it as a non-match. Use only *, **, ?, [...] and {a,b}.`,
|
|
33090
|
+
triggerId
|
|
33091
|
+
};
|
|
33092
|
+
}
|
|
33093
|
+
function getGlobMatcher(pattern) {
|
|
33094
|
+
const hit = cache2.get(pattern);
|
|
33095
|
+
if (hit !== void 0) return hit;
|
|
33096
|
+
if (cache2.size >= CACHE_LIMIT) cache2.clear();
|
|
33097
|
+
const composed = pattern.normalize("NFC");
|
|
33098
|
+
const parsed = parseGlob(composed);
|
|
33099
|
+
const matcher = typeof parsed === "string" ? null : build(composed, parsed);
|
|
33100
|
+
cache2.set(pattern, matcher);
|
|
33101
|
+
return matcher;
|
|
33102
|
+
}
|
|
33103
|
+
function build(pattern, parsed) {
|
|
33104
|
+
const alts = parsed.alternatives.map(prepare);
|
|
33105
|
+
return {
|
|
33106
|
+
test(rawPath, budget) {
|
|
33107
|
+
const path = rawPath.normalize("NFC");
|
|
33108
|
+
if (path === pattern) return true;
|
|
33109
|
+
if (path === "" || path.length > MAX_GLOB_PATH_LENGTH) return false;
|
|
33110
|
+
const live = alts.filter((a) => mayMatch(a, path));
|
|
33111
|
+
if (live.length === 0) return parsed.negated;
|
|
33112
|
+
const limit = Math.min(MATCH_WORK_LIMIT, budget?.remaining ?? MATCH_WORK_LIMIT);
|
|
33113
|
+
const work = { remaining: limit };
|
|
33114
|
+
const segments = path.split("/");
|
|
33115
|
+
const hit = live.some((a) => matchSegments(a.alt, segments, work));
|
|
33116
|
+
if (budget !== void 0) budget.remaining -= limit - work.remaining;
|
|
33117
|
+
return work.remaining > 0 && hit !== parsed.negated;
|
|
33118
|
+
}
|
|
33119
|
+
};
|
|
33120
|
+
}
|
|
33121
|
+
function mayMatch({ head, tail }, path) {
|
|
33122
|
+
if (!path.endsWith(tail)) return false;
|
|
33123
|
+
if (head === null) return true;
|
|
33124
|
+
return path.startsWith(head) && (path.length === head.length || path[head.length] === "/");
|
|
33125
|
+
}
|
|
33126
|
+
function prepare(alt) {
|
|
33127
|
+
const first = alt[0];
|
|
33128
|
+
const last = alt[alt.length - 1];
|
|
33129
|
+
let tail = "";
|
|
33130
|
+
if (last?.k === "segment" && !last.matchesEmpty) {
|
|
33131
|
+
for (let k = last.tokens.length - 1; k >= 0; k -= 1) {
|
|
33132
|
+
const tok = last.tokens[k];
|
|
33133
|
+
if (tok.k !== "lit") break;
|
|
33134
|
+
tail = tok.ch + tail;
|
|
33135
|
+
}
|
|
33136
|
+
}
|
|
33137
|
+
return { alt, head: first?.k === "segment" ? first.literal : null, tail };
|
|
33138
|
+
}
|
|
33139
|
+
|
|
32684
33140
|
// src/lessons/regex-linear/nfa-compile.ts
|
|
32685
33141
|
var MAX_NFA_STATES = 2e3;
|
|
32686
33142
|
var Builder = class {
|
|
@@ -32872,6 +33328,9 @@ function escapeClass(c2) {
|
|
|
32872
33328
|
var HEX2 = /^[0-9a-fA-F]{2}$/;
|
|
32873
33329
|
var HEX4 = /^[0-9a-fA-F]{4}$/;
|
|
32874
33330
|
function readUnicodeEscape(src, i, c2) {
|
|
33331
|
+
if (c2 === "u" && src[i] === "{") {
|
|
33332
|
+
throw new UnsupportedRegexError("\\u{\u2026} code point escapes are not supported; use \\uHHHH");
|
|
33333
|
+
}
|
|
32875
33334
|
if (c2 === "x") {
|
|
32876
33335
|
const hex2 = src.slice(i, i + 2);
|
|
32877
33336
|
return HEX2.test(hex2) ? { ch: String.fromCharCode(parseInt(hex2, 16)), len: 2 } : { ch: "x", len: 0 };
|
|
@@ -32961,7 +33420,7 @@ function parseRegex(src) {
|
|
|
32961
33420
|
function parseAtom() {
|
|
32962
33421
|
const c2 = peek();
|
|
32963
33422
|
if (c2 === "(") return parseGroup2();
|
|
32964
|
-
if (c2 === "[") return
|
|
33423
|
+
if (c2 === "[") return parseClass2();
|
|
32965
33424
|
if (c2 === "\\") return parseEscape();
|
|
32966
33425
|
if (c2 === ".") {
|
|
32967
33426
|
i += 1;
|
|
@@ -33020,7 +33479,7 @@ function parseRegex(src) {
|
|
|
33020
33479
|
}
|
|
33021
33480
|
return { k: "char", ch: escapeLiteral(c2) };
|
|
33022
33481
|
}
|
|
33023
|
-
function
|
|
33482
|
+
function parseClass2() {
|
|
33024
33483
|
i += 1;
|
|
33025
33484
|
const negate = peek() === "^";
|
|
33026
33485
|
if (negate) i += 1;
|
|
@@ -33073,17 +33532,17 @@ function parseRegex(src) {
|
|
|
33073
33532
|
}
|
|
33074
33533
|
|
|
33075
33534
|
// src/lessons/regex-linear/index.ts
|
|
33076
|
-
var
|
|
33535
|
+
var cache3 = /* @__PURE__ */ new Map();
|
|
33077
33536
|
function compileLinearMatcher(pattern) {
|
|
33078
|
-
const hit =
|
|
33079
|
-
if (hit !== void 0 ||
|
|
33537
|
+
const hit = cache3.get(pattern);
|
|
33538
|
+
if (hit !== void 0 || cache3.has(pattern)) return hit ?? null;
|
|
33080
33539
|
let matcher;
|
|
33081
33540
|
try {
|
|
33082
33541
|
matcher = buildMatcher(parseRegex(pattern));
|
|
33083
33542
|
} catch {
|
|
33084
33543
|
matcher = null;
|
|
33085
33544
|
}
|
|
33086
|
-
|
|
33545
|
+
cache3.set(pattern, matcher);
|
|
33087
33546
|
return matcher;
|
|
33088
33547
|
}
|
|
33089
33548
|
|
|
@@ -33124,6 +33583,8 @@ function collectDuplicateRules(graph, findings) {
|
|
|
33124
33583
|
}
|
|
33125
33584
|
function collectInvalidTriggerPatterns(graph, findings) {
|
|
33126
33585
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33586
|
+
const globFinding = unsafeGlobFinding(triggerId, trigger);
|
|
33587
|
+
if (globFinding !== null) findings.push(globFinding);
|
|
33127
33588
|
if (trigger.kind !== "command_pattern") continue;
|
|
33128
33589
|
try {
|
|
33129
33590
|
new RegExp(trigger.pattern);
|
|
@@ -33131,7 +33592,7 @@ function collectInvalidTriggerPatterns(graph, findings) {
|
|
|
33131
33592
|
findings.push({
|
|
33132
33593
|
level: "error",
|
|
33133
33594
|
code: "INVALID_TRIGGER_PATTERN",
|
|
33134
|
-
message: `Trigger "${triggerId}" has an invalid command_pattern regex (${trigger.pattern}): ${
|
|
33595
|
+
message: `Trigger "${triggerId}" has an invalid command_pattern regex (${trigger.pattern}): ${regexSyntaxReason(err)}.`,
|
|
33135
33596
|
triggerId
|
|
33136
33597
|
});
|
|
33137
33598
|
continue;
|
|
@@ -33140,12 +33601,16 @@ function collectInvalidTriggerPatterns(graph, findings) {
|
|
|
33140
33601
|
findings.push({
|
|
33141
33602
|
level: "error",
|
|
33142
33603
|
code: "UNSAFE_TRIGGER_PATTERN",
|
|
33143
|
-
message: `Trigger "${triggerId}" has a command_pattern regex
|
|
33604
|
+
message: `Trigger "${triggerId}" has a command_pattern regex the linear matcher cannot run (${trigger.pattern}). It does not support backreferences (\\1, \\k<name>), lookarounds ((?=x), (?!x), (?<=x), (?<!x)), or patterns too large to run, such as (a{1000}){10}. Nested quantifiers such as (a+)+ are fine. Rewrite the pattern without the unsupported part.`,
|
|
33144
33605
|
triggerId
|
|
33145
33606
|
});
|
|
33146
33607
|
}
|
|
33147
33608
|
}
|
|
33148
33609
|
}
|
|
33610
|
+
function regexSyntaxReason(err) {
|
|
33611
|
+
const text = err instanceof Error ? err.message : String(err);
|
|
33612
|
+
return text.replace(/^Invalid regular expression: \/[\s\S]*\/[a-z]*: /, "");
|
|
33613
|
+
}
|
|
33149
33614
|
function collectBackslashGlobPatterns(graph, findings) {
|
|
33150
33615
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33151
33616
|
if (trigger.kind !== "file_glob") continue;
|
|
@@ -33226,7 +33691,11 @@ function collectTriggerSetCollisions(graph, findings) {
|
|
|
33226
33691
|
|
|
33227
33692
|
// src/lessons/glob-breadth.ts
|
|
33228
33693
|
var WILDCARD = /[*?[\]]/;
|
|
33694
|
+
function isNegatedGlob(pattern) {
|
|
33695
|
+
return pattern.startsWith("!");
|
|
33696
|
+
}
|
|
33229
33697
|
function globNarrowness(pattern) {
|
|
33698
|
+
if (isNegatedGlob(pattern)) return 0;
|
|
33230
33699
|
const segments = pattern.replaceAll("\\", "/").split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
33231
33700
|
if (segments.length === 0) return 0;
|
|
33232
33701
|
let literal = 0;
|
|
@@ -33277,6 +33746,15 @@ function isBroadCommandPattern(pattern) {
|
|
|
33277
33746
|
}
|
|
33278
33747
|
return hits > COMMAND_PROBE_CORPUS.length * BROAD_HIT_RATIO;
|
|
33279
33748
|
}
|
|
33749
|
+
function missingGlobState(pattern, history) {
|
|
33750
|
+
const matcher = getGlobMatcher(pattern);
|
|
33751
|
+
if (history === null || matcher === null) return "pending";
|
|
33752
|
+
const matchesAny = (paths2) => [...paths2].some((p) => matcher.test(p));
|
|
33753
|
+
if (matchesAny(history.tracked)) return "live";
|
|
33754
|
+
if (matchesAny(history.renamedAway)) return "dead";
|
|
33755
|
+
if (!picomatch.scan(pattern).isGlob && matchesAny(history.deleted)) return "dead";
|
|
33756
|
+
return "pending";
|
|
33757
|
+
}
|
|
33280
33758
|
|
|
33281
33759
|
// src/lessons/validate-liveness.ts
|
|
33282
33760
|
function activeTriggerIds(graph) {
|
|
@@ -33287,24 +33765,33 @@ function activeTriggerIds(graph) {
|
|
|
33287
33765
|
}
|
|
33288
33766
|
return ids;
|
|
33289
33767
|
}
|
|
33290
|
-
function
|
|
33291
|
-
const active = activeTriggerIds(graph);
|
|
33768
|
+
function fileGlobLiveness(graph, knownPaths, triggerIds) {
|
|
33769
|
+
const active = activeTriggerIds(graph) ;
|
|
33292
33770
|
const paths2 = [...knownPaths];
|
|
33293
|
-
const
|
|
33771
|
+
const missing = [];
|
|
33294
33772
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33295
|
-
if (trigger.kind !== "file_glob") continue;
|
|
33296
|
-
|
|
33297
|
-
|
|
33298
|
-
if (!paths2.some((p) =>
|
|
33773
|
+
if (trigger.kind !== "file_glob" || !active.has(triggerId)) continue;
|
|
33774
|
+
const matcher = getGlobMatcher(trigger.pattern);
|
|
33775
|
+
if (matcher === null) continue;
|
|
33776
|
+
if (!paths2.some((p) => matcher.test(p))) missing.push([triggerId, trigger.pattern]);
|
|
33777
|
+
}
|
|
33778
|
+
const dead = /* @__PURE__ */ new Set();
|
|
33779
|
+
const pending = /* @__PURE__ */ new Set();
|
|
33780
|
+
if (missing.length === 0) return { dead, pending };
|
|
33781
|
+
const history = gitHistoryOf(knownPaths);
|
|
33782
|
+
for (const [triggerId, pattern] of missing) {
|
|
33783
|
+
const state = missingGlobState(pattern, history);
|
|
33784
|
+
if (state === "dead") dead.add(triggerId);
|
|
33785
|
+
else if (state === "pending") pending.add(triggerId);
|
|
33299
33786
|
}
|
|
33300
|
-
return dead;
|
|
33787
|
+
return { dead, pending };
|
|
33301
33788
|
}
|
|
33302
33789
|
function collectDeadFileGlobs(graph, findings, knownPaths) {
|
|
33303
|
-
for (const triggerId of
|
|
33790
|
+
for (const triggerId of fileGlobLiveness(graph, knownPaths).dead) {
|
|
33304
33791
|
findings.push({
|
|
33305
33792
|
level: "warning",
|
|
33306
33793
|
code: "DEAD_FILE_GLOB",
|
|
33307
|
-
message: `file_glob trigger "${triggerId}" (${graph.triggers[triggerId]?.pattern ?? ""}) matches no file
|
|
33794
|
+
message: `file_glob trigger "${triggerId}" (${graph.triggers[triggerId]?.pattern ?? ""}) matches no file, and git history shows its path was renamed or deleted \u2014 the lesson is unreachable via this trigger. Re-point it at the current path, or detach it with \`lessons untrigger\`, or run \`lessons prune --apply\`.`,
|
|
33308
33795
|
triggerId
|
|
33309
33796
|
});
|
|
33310
33797
|
}
|
|
@@ -33376,14 +33863,14 @@ var STOP = /* @__PURE__ */ new Set([
|
|
|
33376
33863
|
"its",
|
|
33377
33864
|
"must"
|
|
33378
33865
|
]);
|
|
33379
|
-
function
|
|
33866
|
+
function tokenize2(text) {
|
|
33380
33867
|
return text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 2 && !STOP.has(t));
|
|
33381
33868
|
}
|
|
33382
33869
|
|
|
33383
33870
|
// src/lessons/keyword-signal.ts
|
|
33384
33871
|
var MAX_RECOMMENDED_KEYWORD_TOKENS = 5;
|
|
33385
33872
|
function isLowSignalKeyword(pattern) {
|
|
33386
|
-
return
|
|
33873
|
+
return tokenize2(pattern).length > MAX_RECOMMENDED_KEYWORD_TOKENS;
|
|
33387
33874
|
}
|
|
33388
33875
|
function splitRawTokens(pattern) {
|
|
33389
33876
|
return pattern.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 0);
|
|
@@ -33391,7 +33878,7 @@ function splitRawTokens(pattern) {
|
|
|
33391
33878
|
function keywordNeedleLosesTokens(pattern) {
|
|
33392
33879
|
const raw = splitRawTokens(pattern);
|
|
33393
33880
|
if (raw.length < 2) return false;
|
|
33394
|
-
return
|
|
33881
|
+
return tokenize2(pattern).length !== raw.length;
|
|
33395
33882
|
}
|
|
33396
33883
|
|
|
33397
33884
|
// src/lessons/validate-keywords.ts
|
|
@@ -33414,7 +33901,7 @@ function collectStopwordKeywords(graph, findings) {
|
|
|
33414
33901
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33415
33902
|
if (trigger.kind !== "keyword") continue;
|
|
33416
33903
|
if (!active.has(triggerId)) continue;
|
|
33417
|
-
if (
|
|
33904
|
+
if (tokenize2(trigger.pattern).length !== 0 && !keywordNeedleLosesTokens(trigger.pattern)) {
|
|
33418
33905
|
continue;
|
|
33419
33906
|
}
|
|
33420
33907
|
findings.push({
|
|
@@ -33462,7 +33949,6 @@ function validateLessonsGraph(graph, options = {}) {
|
|
|
33462
33949
|
|
|
33463
33950
|
// src/core/lint/shared/lessons.ts
|
|
33464
33951
|
var LESSONS_TARGET = "lessons";
|
|
33465
|
-
var GRAPH_REL = ".agentsmesh/lessons/lessons.json";
|
|
33466
33952
|
var ROOT_RULE_REL = ".agentsmesh/rules/_root.md";
|
|
33467
33953
|
var LESSONS_HEADING = /^## Lessons \(/m;
|
|
33468
33954
|
function lintLessonsSubsystem(projectRoot, scope) {
|
|
@@ -33477,7 +33963,7 @@ function lintLessonsSubsystem(projectRoot, scope) {
|
|
|
33477
33963
|
return [
|
|
33478
33964
|
diag(
|
|
33479
33965
|
"error",
|
|
33480
|
-
|
|
33966
|
+
LESSONS_GRAPH_PATH,
|
|
33481
33967
|
`lessons.json failed to load: ${err instanceof Error ? err.message : String(err)}`
|
|
33482
33968
|
)
|
|
33483
33969
|
];
|
|
@@ -33485,7 +33971,7 @@ function lintLessonsSubsystem(projectRoot, scope) {
|
|
|
33485
33971
|
const knownPaths = listProjectFiles(projectRoot) ?? void 0;
|
|
33486
33972
|
const report = validateLessonsGraph(graph, { knownPaths });
|
|
33487
33973
|
for (const finding of report.findings) {
|
|
33488
|
-
out2.push(diag(finding.level,
|
|
33974
|
+
out2.push(diag(finding.level, LESSONS_GRAPH_PATH, `[${finding.code}] ${finding.message}`));
|
|
33489
33975
|
}
|
|
33490
33976
|
const rootRuleAbs = join(projectRoot, ROOT_RULE_REL);
|
|
33491
33977
|
const rootRuleBody = existsSync(rootRuleAbs) ? readFileSync(rootRuleAbs, "utf8") : "";
|
|
@@ -33507,8 +33993,8 @@ function diag(level, file, message) {
|
|
|
33507
33993
|
// src/core/lint/linter.ts
|
|
33508
33994
|
var EXCLUDE_DIRS = ["node_modules", ".git", "dist", "coverage", ".agentsmesh"];
|
|
33509
33995
|
function isExcludedProjectPath(rel2) {
|
|
33510
|
-
const
|
|
33511
|
-
return EXCLUDE_DIRS.some((d) =>
|
|
33996
|
+
const posix9 = rel2.replaceAll("\\", "/");
|
|
33997
|
+
return EXCLUDE_DIRS.some((d) => posix9.includes(`/${d}/`) || posix9.startsWith(`${d}/`));
|
|
33512
33998
|
}
|
|
33513
33999
|
async function getProjectFiles(projectRoot) {
|
|
33514
34000
|
const all = await readDirRecursive(projectRoot);
|
|
@@ -33901,14 +34387,22 @@ async function findUntrackedManagedDirFiles(args) {
|
|
|
33901
34387
|
return [...found].sort();
|
|
33902
34388
|
}
|
|
33903
34389
|
|
|
34390
|
+
// src/lessons/conflict-markers.ts
|
|
34391
|
+
function hasConflictMarkers(text) {
|
|
34392
|
+
return /^(?:<{7}|>{7})(?: |\r?$)/m.test(text);
|
|
34393
|
+
}
|
|
34394
|
+
|
|
33904
34395
|
// src/core/check/lock-sync.ts
|
|
34396
|
+
init_fs();
|
|
33905
34397
|
async function checkLockSync(opts) {
|
|
33906
34398
|
const { config, configDir, canonicalDir, rootBase, scope = "project" } = opts;
|
|
33907
34399
|
const lock = await readLock(canonicalDir);
|
|
33908
34400
|
if (lock === null) {
|
|
34401
|
+
const text = await readFileSafe(join(canonicalDir, ".lock"));
|
|
33909
34402
|
return {
|
|
33910
34403
|
inSync: false,
|
|
33911
34404
|
hasLock: false,
|
|
34405
|
+
lockConflict: text !== null && hasConflictMarkers(text),
|
|
33912
34406
|
canonicalDrift: false,
|
|
33913
34407
|
outputDrift: false,
|
|
33914
34408
|
modified: [],
|
|
@@ -33978,6 +34472,7 @@ async function checkLockSync(opts) {
|
|
|
33978
34472
|
return {
|
|
33979
34473
|
inSync,
|
|
33980
34474
|
hasLock: true,
|
|
34475
|
+
lockConflict: false,
|
|
33981
34476
|
canonicalDrift,
|
|
33982
34477
|
outputDrift,
|
|
33983
34478
|
modified,
|