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/CHANGELOG.md +93 -0
- package/README.md +1 -1
- package/dist/canonical.js +303 -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 +775 -276
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1737 -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 +2105 -601
- 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 +269 -219
- package/dist/targets.js.map +1 -1
- package/package.json +4 -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
|
}
|
|
@@ -2867,6 +2886,9 @@ var init_link_token_context = __esm({
|
|
|
2867
2886
|
});
|
|
2868
2887
|
|
|
2869
2888
|
// src/core/reference/link-rebaser.ts
|
|
2889
|
+
function isSlashCommandToken(normalizedToken) {
|
|
2890
|
+
return /^\/[A-Za-z][A-Za-z0-9-]*$/.test(normalizedToken);
|
|
2891
|
+
}
|
|
2870
2892
|
function rewriteFileLinks(input) {
|
|
2871
2893
|
const missing = /* @__PURE__ */ new Set();
|
|
2872
2894
|
const protectedRefRanges = protectedRanges(input.content);
|
|
@@ -2917,6 +2939,7 @@ function rewriteFileLinks(input) {
|
|
|
2917
2939
|
if (targetIsDirectory && !normalizedCandidate.includes("/") && !normalizedCandidate.includes("\\")) {
|
|
2918
2940
|
return match;
|
|
2919
2941
|
}
|
|
2942
|
+
if (isSlashCommandToken(normalizedCandidate)) return match;
|
|
2920
2943
|
if (resolvedBeforeTranslate === null) {
|
|
2921
2944
|
let normTok = normalizeSeparators(punctStripped);
|
|
2922
2945
|
if (normTok.startsWith("agentsmesh/")) {
|
|
@@ -7041,10 +7064,6 @@ function generateAgents4(canonical) {
|
|
|
7041
7064
|
content: serializeAntigravityAgent(agent)
|
|
7042
7065
|
}));
|
|
7043
7066
|
}
|
|
7044
|
-
function generateIgnore3(canonical) {
|
|
7045
|
-
if (canonical.ignore.length === 0) return [];
|
|
7046
|
-
return [{ path: ANTIGRAVITY_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
7047
|
-
}
|
|
7048
7067
|
function renderAntigravityGlobalInstructions(canonical) {
|
|
7049
7068
|
const root = canonical.rules.find((rule) => rule.root);
|
|
7050
7069
|
const nonRootRules = canonical.rules.filter((rule) => {
|
|
@@ -7059,7 +7078,7 @@ function generateHooks2(canonical) {
|
|
|
7059
7078
|
if (Object.keys(hooks).length === 0) return [];
|
|
7060
7079
|
return [{ path: ANTIGRAVITY_HOOKS_FILE, content: JSON.stringify(hooks, null, 2) }];
|
|
7061
7080
|
}
|
|
7062
|
-
var generatePermissions3;
|
|
7081
|
+
var generateIgnore3, generatePermissions3;
|
|
7063
7082
|
var init_generator4 = __esm({
|
|
7064
7083
|
"src/targets/antigravity/generator.ts"() {
|
|
7065
7084
|
init_no_outputs();
|
|
@@ -7068,6 +7087,8 @@ var init_generator4 = __esm({
|
|
|
7068
7087
|
init_hooks_format2();
|
|
7069
7088
|
init_agents_format();
|
|
7070
7089
|
init_constants5();
|
|
7090
|
+
init_ignore_output();
|
|
7091
|
+
generateIgnore3 = ignoreOutput(ANTIGRAVITY_IGNORE_FILE);
|
|
7071
7092
|
generatePermissions3 = NO_OUTPUTS;
|
|
7072
7093
|
}
|
|
7073
7094
|
});
|
|
@@ -8661,16 +8682,14 @@ function generateHooks3(canonical) {
|
|
|
8661
8682
|
const content = JSON.stringify({ hooks: claudeHooks }, null, 2);
|
|
8662
8683
|
return [{ path: CLAUDE_SETTINGS, content }];
|
|
8663
8684
|
}
|
|
8664
|
-
|
|
8665
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
8666
|
-
const content = canonical.ignore.join("\n");
|
|
8667
|
-
return [{ path: CLAUDE_IGNORE, content }];
|
|
8668
|
-
}
|
|
8685
|
+
var generateIgnore5;
|
|
8669
8686
|
var init_generator6 = __esm({
|
|
8670
8687
|
"src/targets/claude-code/generator.ts"() {
|
|
8671
8688
|
init_markdown();
|
|
8672
8689
|
init_constants7();
|
|
8673
8690
|
init_hooks_format2();
|
|
8691
|
+
init_ignore_output();
|
|
8692
|
+
generateIgnore5 = ignoreOutput(CLAUDE_IGNORE);
|
|
8674
8693
|
}
|
|
8675
8694
|
});
|
|
8676
8695
|
function ruleSectionTitle(rule) {
|
|
@@ -10489,11 +10508,7 @@ function generateMcp5(canonical) {
|
|
|
10489
10508
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
10490
10509
|
return [{ path: CODEBUFF_MCP_FILE, content: serializeCodebuffMcp(canonical.mcp) }];
|
|
10491
10510
|
}
|
|
10492
|
-
|
|
10493
|
-
if (canonical.ignore.length === 0) return [];
|
|
10494
|
-
return [{ path: CODEBUFF_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
10495
|
-
}
|
|
10496
|
-
var generateAgents8, generateHooks5, generatePermissions6;
|
|
10511
|
+
var generateIgnore7, generateAgents8, generateHooks5, generatePermissions6;
|
|
10497
10512
|
var init_generator8 = __esm({
|
|
10498
10513
|
"src/targets/codebuff/generator.ts"() {
|
|
10499
10514
|
init_no_outputs();
|
|
@@ -10503,6 +10518,8 @@ var init_generator8 = __esm({
|
|
|
10503
10518
|
init_nested_rules();
|
|
10504
10519
|
init_mcp_format2();
|
|
10505
10520
|
init_constants9();
|
|
10521
|
+
init_ignore_output();
|
|
10522
|
+
generateIgnore7 = ignoreOutput(CODEBUFF_IGNORE_FILE);
|
|
10506
10523
|
generateAgents8 = NO_OUTPUTS;
|
|
10507
10524
|
generateHooks5 = NO_OUTPUTS;
|
|
10508
10525
|
generatePermissions6 = NO_OUTPUTS;
|
|
@@ -13015,53 +13032,37 @@ var init_mcp_generator = __esm({
|
|
|
13015
13032
|
}
|
|
13016
13033
|
});
|
|
13017
13034
|
|
|
13018
|
-
// src/targets/copilot/hook-entry.ts
|
|
13019
|
-
function hasHookCommand2(entry) {
|
|
13020
|
-
return hasHookCommand(entry);
|
|
13021
|
-
}
|
|
13022
|
-
var init_hook_entry = __esm({
|
|
13023
|
-
"src/targets/copilot/hook-entry.ts"() {
|
|
13024
|
-
init_hook_command();
|
|
13025
|
-
}
|
|
13026
|
-
});
|
|
13027
|
-
|
|
13028
13035
|
// src/targets/copilot/hook-format.ts
|
|
13029
|
-
function
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
}
|
|
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`;
|
|
13042
13048
|
}
|
|
13043
13049
|
function buildCopilotHooksObject(hooks) {
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
(entry) => typeof entry === "object" && entry !== null && hasHookCommand2(entry)
|
|
13051
|
-
).map((entry, index) => {
|
|
13052
|
-
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) => {
|
|
13053
13056
|
const hook = {
|
|
13054
13057
|
type: "command",
|
|
13055
|
-
bash: `./scripts/${
|
|
13058
|
+
bash: `./scripts/${wrapperScriptName(event, index)}`
|
|
13056
13059
|
};
|
|
13057
13060
|
if (entry.matcher && entry.matcher !== "*") hook.matcher = entry.matcher;
|
|
13058
13061
|
if (entry.timeout !== void 0) hook.timeoutSec = Math.ceil(entry.timeout / 1e3);
|
|
13059
13062
|
return hook;
|
|
13060
|
-
})
|
|
13061
|
-
|
|
13062
|
-
})
|
|
13063
|
+
})
|
|
13064
|
+
])
|
|
13063
13065
|
);
|
|
13064
|
-
return Object.keys(result2).length > 0 ? result2 : null;
|
|
13065
13066
|
}
|
|
13066
13067
|
function generateHooks8(canonical) {
|
|
13067
13068
|
const hooks = buildCopilotHooksObject(canonical.hooks);
|
|
@@ -13073,10 +13074,24 @@ function generateHooks8(canonical) {
|
|
|
13073
13074
|
}
|
|
13074
13075
|
];
|
|
13075
13076
|
}
|
|
13077
|
+
var COPILOT_HOOK_CONTEXT_EVENTS, CANONICAL_TO_COPILOT;
|
|
13076
13078
|
var init_hook_format = __esm({
|
|
13077
13079
|
"src/targets/copilot/hook-format.ts"() {
|
|
13078
13080
|
init_constants32();
|
|
13079
|
-
|
|
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
|
+
]);
|
|
13080
13095
|
}
|
|
13081
13096
|
});
|
|
13082
13097
|
function ruleSlug2(source) {
|
|
@@ -13182,18 +13197,7 @@ var init_generator12 = __esm({
|
|
|
13182
13197
|
}
|
|
13183
13198
|
});
|
|
13184
13199
|
function mapCopilotHookEvent(event) {
|
|
13185
|
-
|
|
13186
|
-
case "preToolUse":
|
|
13187
|
-
return "PreToolUse";
|
|
13188
|
-
case "postToolUse":
|
|
13189
|
-
return "PostToolUse";
|
|
13190
|
-
case "notification":
|
|
13191
|
-
return "Notification";
|
|
13192
|
-
case "userPromptSubmitted":
|
|
13193
|
-
return "UserPromptSubmit";
|
|
13194
|
-
default:
|
|
13195
|
-
return null;
|
|
13196
|
-
}
|
|
13200
|
+
return COPILOT_TO_CANONICAL.get(event) ?? null;
|
|
13197
13201
|
}
|
|
13198
13202
|
function extractMatcher(comment) {
|
|
13199
13203
|
if (typeof comment !== "string") return "*";
|
|
@@ -13281,11 +13285,16 @@ async function importHooks(projectRoot, results, options = {}) {
|
|
|
13281
13285
|
feature: "hooks"
|
|
13282
13286
|
});
|
|
13283
13287
|
}
|
|
13288
|
+
var COPILOT_TO_CANONICAL;
|
|
13284
13289
|
var init_hook_parser = __esm({
|
|
13285
13290
|
"src/targets/copilot/hook-parser.ts"() {
|
|
13286
13291
|
init_canonical_paths();
|
|
13287
13292
|
init_fs();
|
|
13288
13293
|
init_constants32();
|
|
13294
|
+
init_hook_format();
|
|
13295
|
+
COPILOT_TO_CANONICAL = new Map(
|
|
13296
|
+
[...CANONICAL_TO_COPILOT].map(([canonical, copilot]) => [copilot, canonical])
|
|
13297
|
+
);
|
|
13289
13298
|
}
|
|
13290
13299
|
});
|
|
13291
13300
|
async function importSkills2(projectRoot, results, normalize, skillsDirRel = COPILOT_SKILLS_DIR) {
|
|
@@ -13522,7 +13531,7 @@ function lintCommands4(canonical) {
|
|
|
13522
13531
|
}
|
|
13523
13532
|
function lintHooks9(canonical) {
|
|
13524
13533
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
13525
|
-
const supported = [
|
|
13534
|
+
const supported = [...CANONICAL_TO_COPILOT.keys()];
|
|
13526
13535
|
const diagnostics = unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
13527
13536
|
(event) => createUnsupportedHookWarning(event, "copilot", supported, {
|
|
13528
13537
|
unsupportedBy: "Copilot hooks"
|
|
@@ -13545,11 +13554,9 @@ function lintHooks9(canonical) {
|
|
|
13545
13554
|
var init_lint10 = __esm({
|
|
13546
13555
|
"src/targets/copilot/lint.ts"() {
|
|
13547
13556
|
init_helpers();
|
|
13557
|
+
init_hook_format();
|
|
13548
13558
|
}
|
|
13549
13559
|
});
|
|
13550
|
-
function safePhaseName(phase) {
|
|
13551
|
-
return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
13552
|
-
}
|
|
13553
13560
|
function toRepoRelative(projectRoot, sourcePath) {
|
|
13554
13561
|
const repoRelative = relative(projectRoot, sourcePath).replace(/\\/g, "/");
|
|
13555
13562
|
if (!repoRelative || repoRelative.startsWith("../")) return null;
|
|
@@ -13577,9 +13584,6 @@ async function buildAssetOutput(projectRoot, command, hooksDirRel) {
|
|
|
13577
13584
|
rewrittenCommand: rewriteWrapperCommand(command, repoRelative)
|
|
13578
13585
|
};
|
|
13579
13586
|
}
|
|
13580
|
-
function wrapperPath(event, index, hooksDirRel) {
|
|
13581
|
-
return `${hooksDirRel}/scripts/${safePhaseName(event)}-${index}.sh`;
|
|
13582
|
-
}
|
|
13583
13587
|
function safeShellLine2(value) {
|
|
13584
13588
|
return value.replace(/[\r\n]+/g, " ");
|
|
13585
13589
|
}
|
|
@@ -13594,15 +13598,13 @@ function buildWrapper(command, matcher) {
|
|
|
13594
13598
|
].join("\n");
|
|
13595
13599
|
}
|
|
13596
13600
|
async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel = COPILOT_HOOKS_DIR) {
|
|
13597
|
-
|
|
13601
|
+
const groups = copilotHookGroups(canonical.hooks);
|
|
13602
|
+
if (groups.length === 0) return outputs;
|
|
13598
13603
|
const wrapperOutputs = [];
|
|
13599
13604
|
const assetOutputs = /* @__PURE__ */ new Map();
|
|
13600
|
-
for (const
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
for (const entry of entries) {
|
|
13604
|
-
if (!hasHookCommand2(entry)) continue;
|
|
13605
|
-
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)}`;
|
|
13606
13608
|
let command = entry.command;
|
|
13607
13609
|
const asset = await buildAssetOutput(projectRoot, entry.command, hooksDirRel);
|
|
13608
13610
|
if (asset) {
|
|
@@ -13616,7 +13618,6 @@ async function addHookScriptAssets(projectRoot, canonical, outputs, hooksDirRel
|
|
|
13616
13618
|
'set -eu\nHOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n'
|
|
13617
13619
|
);
|
|
13618
13620
|
wrapperOutputs.push({ path: scriptPath, content: wrapper });
|
|
13619
|
-
index++;
|
|
13620
13621
|
}
|
|
13621
13622
|
}
|
|
13622
13623
|
return [...outputs, ...wrapperOutputs, ...assetOutputs.values()];
|
|
@@ -13626,7 +13627,7 @@ var init_hook_assets = __esm({
|
|
|
13626
13627
|
"src/targets/copilot/hook-assets.ts"() {
|
|
13627
13628
|
init_fs();
|
|
13628
13629
|
init_constants32();
|
|
13629
|
-
|
|
13630
|
+
init_hook_format();
|
|
13630
13631
|
SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
|
|
13631
13632
|
}
|
|
13632
13633
|
});
|
|
@@ -13944,6 +13945,7 @@ var init_copilot2 = __esm({
|
|
|
13944
13945
|
init_command_prompt();
|
|
13945
13946
|
init_lint10();
|
|
13946
13947
|
init_hook_assets();
|
|
13948
|
+
init_hook_format();
|
|
13947
13949
|
init_scope_extras2();
|
|
13948
13950
|
init_importer_spec2();
|
|
13949
13951
|
init_capabilities6();
|
|
@@ -14074,6 +14076,7 @@ var init_copilot2 = __esm({
|
|
|
14074
14076
|
permissions: lintPermissions7
|
|
14075
14077
|
},
|
|
14076
14078
|
postProcessHookOutputs: async (projectRoot, canonical, outputs) => addHookScriptAssets(projectRoot, canonical, [...outputs]),
|
|
14079
|
+
hookContextEvents: COPILOT_HOOK_CONTEXT_EVENTS,
|
|
14077
14080
|
mergeGeneratedOutputContent: mergeCopilotMcpJson,
|
|
14078
14081
|
project: project7,
|
|
14079
14082
|
globalSupport: {
|
|
@@ -14161,11 +14164,6 @@ function generatePermissions8(canonical) {
|
|
|
14161
14164
|
});
|
|
14162
14165
|
return [{ path: CRUSH_CONFIG_FILE, content: JSON.stringify(crushConfig, null, 2) }];
|
|
14163
14166
|
}
|
|
14164
|
-
function generateIgnore9(canonical) {
|
|
14165
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
14166
|
-
const content = canonical.ignore.join("\n");
|
|
14167
|
-
return [{ path: CRUSH_IGNORE, content }];
|
|
14168
|
-
}
|
|
14169
14167
|
function buildCrushHooksFromCanonical(canonical) {
|
|
14170
14168
|
if (!canonical.hooks) return {};
|
|
14171
14169
|
const result2 = {};
|
|
@@ -14183,7 +14181,7 @@ function buildCrushHooksFromCanonical(canonical) {
|
|
|
14183
14181
|
}
|
|
14184
14182
|
return result2;
|
|
14185
14183
|
}
|
|
14186
|
-
var generateRules12;
|
|
14184
|
+
var generateRules12, generateIgnore9;
|
|
14187
14185
|
var init_generator13 = __esm({
|
|
14188
14186
|
"src/targets/crush/generator.ts"() {
|
|
14189
14187
|
init_managed_blocks();
|
|
@@ -14192,7 +14190,9 @@ var init_generator13 = __esm({
|
|
|
14192
14190
|
init_command_skill();
|
|
14193
14191
|
init_constants12();
|
|
14194
14192
|
init_config_format();
|
|
14193
|
+
init_ignore_output();
|
|
14195
14194
|
generateRules12 = (canonical) => embeddedRootRule(canonical, CRUSH_TARGET, CRUSH_ROOT_FILE);
|
|
14195
|
+
generateIgnore9 = ignoreOutput(CRUSH_IGNORE);
|
|
14196
14196
|
}
|
|
14197
14197
|
});
|
|
14198
14198
|
async function importFromCrush(projectRoot, options = {}) {
|
|
@@ -14728,7 +14728,7 @@ function cursorHooksToCanonical(hooks) {
|
|
|
14728
14728
|
}
|
|
14729
14729
|
return result2;
|
|
14730
14730
|
}
|
|
14731
|
-
var CANONICAL_TO_CURSOR, CURSOR_TO_CANONICAL;
|
|
14731
|
+
var CANONICAL_TO_CURSOR, CURSOR_HOOK_CONTEXT_EVENTS, CURSOR_TO_CANONICAL;
|
|
14732
14732
|
var init_hook_format2 = __esm({
|
|
14733
14733
|
"src/targets/cursor/hook-format.ts"() {
|
|
14734
14734
|
init_hook_types();
|
|
@@ -14736,6 +14736,7 @@ var init_hook_format2 = __esm({
|
|
|
14736
14736
|
CANONICAL_TO_CURSOR = {
|
|
14737
14737
|
PreToolUse: "preToolUse",
|
|
14738
14738
|
PostToolUse: "postToolUse",
|
|
14739
|
+
PostToolUseFailure: "postToolUseFailure",
|
|
14739
14740
|
UserPromptSubmit: "beforeSubmitPrompt",
|
|
14740
14741
|
SubagentStart: "subagentStart",
|
|
14741
14742
|
SubagentStop: "subagentStop",
|
|
@@ -14744,6 +14745,11 @@ var init_hook_format2 = __esm({
|
|
|
14744
14745
|
SessionEnd: "sessionEnd",
|
|
14745
14746
|
PreCompact: "preCompact"
|
|
14746
14747
|
};
|
|
14748
|
+
CURSOR_HOOK_CONTEXT_EVENTS = [
|
|
14749
|
+
"SessionStart",
|
|
14750
|
+
"PostToolUse",
|
|
14751
|
+
"PostToolUseFailure"
|
|
14752
|
+
];
|
|
14747
14753
|
CURSOR_TO_CANONICAL = new Map(
|
|
14748
14754
|
Object.entries(CANONICAL_TO_CURSOR).map(([canonical, cursor]) => [cursor, canonical])
|
|
14749
14755
|
);
|
|
@@ -14752,7 +14758,7 @@ var init_hook_format2 = __esm({
|
|
|
14752
14758
|
|
|
14753
14759
|
// src/targets/cursor/generator/hooks.ts
|
|
14754
14760
|
function generateHooks10(canonical) {
|
|
14755
|
-
if (!canonical.hooks
|
|
14761
|
+
if (!canonical.hooks) return [];
|
|
14756
14762
|
const cursorHooks = toCursorHooks(canonical.hooks);
|
|
14757
14763
|
if (Object.keys(cursorHooks).length === 0) return [];
|
|
14758
14764
|
const content = JSON.stringify({ version: 1, hooks: cursorHooks }, null, 2);
|
|
@@ -14766,14 +14772,12 @@ var init_hooks3 = __esm({
|
|
|
14766
14772
|
});
|
|
14767
14773
|
|
|
14768
14774
|
// src/targets/cursor/generator/ignore.ts
|
|
14769
|
-
|
|
14770
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
14771
|
-
const content = canonical.ignore.join("\n");
|
|
14772
|
-
return [{ path: CURSOR_IGNORE, content }];
|
|
14773
|
-
}
|
|
14775
|
+
var generateIgnore10;
|
|
14774
14776
|
var init_ignore = __esm({
|
|
14775
14777
|
"src/targets/cursor/generator/ignore.ts"() {
|
|
14776
14778
|
init_constants13();
|
|
14779
|
+
init_ignore_output();
|
|
14780
|
+
generateIgnore10 = ignoreOutput(CURSOR_IGNORE);
|
|
14777
14781
|
}
|
|
14778
14782
|
});
|
|
14779
14783
|
|
|
@@ -15469,6 +15473,7 @@ var init_cursor2 = __esm({
|
|
|
15469
15473
|
init_linter13();
|
|
15470
15474
|
init_import_map_builders();
|
|
15471
15475
|
init_lint12();
|
|
15476
|
+
init_hook_format2();
|
|
15472
15477
|
target13 = {
|
|
15473
15478
|
name: "cursor",
|
|
15474
15479
|
primaryRootInstructionPath: CURSOR_GENERAL_RULE,
|
|
@@ -15590,6 +15595,7 @@ var init_cursor2 = __esm({
|
|
|
15590
15595
|
permissions: "native"
|
|
15591
15596
|
},
|
|
15592
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,
|
|
15593
15599
|
lintRules: lintRules13,
|
|
15594
15600
|
lint: {
|
|
15595
15601
|
commands: lintCommands6,
|
|
@@ -16851,25 +16857,127 @@ var init_skills3 = __esm({
|
|
|
16851
16857
|
}
|
|
16852
16858
|
});
|
|
16853
16859
|
|
|
16854
|
-
// src/targets/gemini-cli/
|
|
16855
|
-
function
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
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
|
+
}
|
|
16871
16970
|
}
|
|
16971
|
+
return Object.keys(result2).length > 0 ? result2 : null;
|
|
16872
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
|
|
16873
16981
|
function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
16874
16982
|
const settings = {};
|
|
16875
16983
|
let hasAnyNativeSettings = false;
|
|
@@ -16881,29 +16989,10 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
|
16881
16989
|
settings.experimental = { enableAgents: true };
|
|
16882
16990
|
hasAnyNativeSettings = true;
|
|
16883
16991
|
}
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
const mappedEntries = entries.filter(
|
|
16889
|
-
(entry) => typeof entry === "object" && entry !== null && hasHookCommand(entry)
|
|
16890
|
-
).map((entry, index) => ({
|
|
16891
|
-
matcher: entry.matcher,
|
|
16892
|
-
hooks: [
|
|
16893
|
-
{
|
|
16894
|
-
name: `${mappedEvent}-${index + 1}`,
|
|
16895
|
-
type: "command",
|
|
16896
|
-
command: getHookCommand(entry),
|
|
16897
|
-
timeout: entry.timeout
|
|
16898
|
-
}
|
|
16899
|
-
]
|
|
16900
|
-
}));
|
|
16901
|
-
return mappedEntries.length > 0 ? [[mappedEvent, mappedEntries]] : [];
|
|
16902
|
-
});
|
|
16903
|
-
if (hookEntries.length > 0) {
|
|
16904
|
-
settings.hooks = Object.fromEntries(hookEntries);
|
|
16905
|
-
hasAnyNativeSettings = true;
|
|
16906
|
-
}
|
|
16992
|
+
const hooks = enabledFeatures.has("hooks") ? buildGeminiHooks(canonical.hooks) : null;
|
|
16993
|
+
if (hooks) {
|
|
16994
|
+
settings.hooks = hooks;
|
|
16995
|
+
hasAnyNativeSettings = true;
|
|
16907
16996
|
}
|
|
16908
16997
|
if (hasAnyNativeSettings) {
|
|
16909
16998
|
settings.context = { fileName: [GEMINI_ROOT, GEMINI_COMPAT_AGENTS] };
|
|
@@ -16913,19 +17002,18 @@ function generateGeminiSettingsFiles(canonical, enabledFeatures) {
|
|
|
16913
17002
|
}
|
|
16914
17003
|
var init_settings2 = __esm({
|
|
16915
17004
|
"src/targets/gemini-cli/generator/settings.ts"() {
|
|
16916
|
-
init_hook_command();
|
|
16917
17005
|
init_constants33();
|
|
17006
|
+
init_hooks4();
|
|
16918
17007
|
}
|
|
16919
17008
|
});
|
|
16920
17009
|
|
|
16921
17010
|
// src/targets/gemini-cli/generator/ignore.ts
|
|
16922
|
-
|
|
16923
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
16924
|
-
return [{ path: GEMINI_IGNORE, content: canonical.ignore.join("\n") }];
|
|
16925
|
-
}
|
|
17011
|
+
var generateIgnore13;
|
|
16926
17012
|
var init_ignore2 = __esm({
|
|
16927
17013
|
"src/targets/gemini-cli/generator/ignore.ts"() {
|
|
16928
17014
|
init_constants33();
|
|
17015
|
+
init_ignore_output();
|
|
17016
|
+
generateIgnore13 = ignoreOutput(GEMINI_IGNORE);
|
|
16929
17017
|
}
|
|
16930
17018
|
});
|
|
16931
17019
|
|
|
@@ -17204,27 +17292,6 @@ var init_layout6 = __esm({
|
|
|
17204
17292
|
};
|
|
17205
17293
|
}
|
|
17206
17294
|
});
|
|
17207
|
-
function mapGeminiHookEvent(event) {
|
|
17208
|
-
switch (event) {
|
|
17209
|
-
case "BeforeTool":
|
|
17210
|
-
case "preToolUse":
|
|
17211
|
-
return "PreToolUse";
|
|
17212
|
-
case "AfterTool":
|
|
17213
|
-
case "postToolUse":
|
|
17214
|
-
return "PostToolUse";
|
|
17215
|
-
case "Notification":
|
|
17216
|
-
case "notification":
|
|
17217
|
-
return "Notification";
|
|
17218
|
-
case "BeforeAgent":
|
|
17219
|
-
return "SubagentStart";
|
|
17220
|
-
case "AfterAgent":
|
|
17221
|
-
return "SubagentStop";
|
|
17222
|
-
case "SessionStart":
|
|
17223
|
-
return "SessionStart";
|
|
17224
|
-
default:
|
|
17225
|
-
return null;
|
|
17226
|
-
}
|
|
17227
|
-
}
|
|
17228
17295
|
function parseFlexibleFrontmatter(content) {
|
|
17229
17296
|
const yamlOpen = content.indexOf("---");
|
|
17230
17297
|
const tomlOpen = content.indexOf("+++");
|
|
@@ -17298,7 +17365,7 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
17298
17365
|
(entry) => entry.hooks.filter(
|
|
17299
17366
|
(hook) => hook !== null && typeof hook === "object" && hasHookCommand(hook)
|
|
17300
17367
|
).map((hook) => ({
|
|
17301
|
-
matcher: entry.matcher,
|
|
17368
|
+
matcher: fromGeminiMatcher(event, entry.matcher),
|
|
17302
17369
|
command: getHookCommand(hook),
|
|
17303
17370
|
type: "command",
|
|
17304
17371
|
timeout: typeof hook.timeout === "number" ? hook.timeout : void 0
|
|
@@ -17308,7 +17375,7 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
17308
17375
|
const legacyMapped = value.filter(
|
|
17309
17376
|
(entry) => entry !== null && typeof entry === "object" && typeof entry.matcher === "string" && hasHookCommand(entry)
|
|
17310
17377
|
).map((entry) => ({
|
|
17311
|
-
matcher: entry.matcher,
|
|
17378
|
+
matcher: fromGeminiMatcher(event, entry.matcher),
|
|
17312
17379
|
command: getHookCommand(entry),
|
|
17313
17380
|
type: "command"
|
|
17314
17381
|
}));
|
|
@@ -17337,7 +17404,7 @@ var init_format_helpers_settings = __esm({
|
|
|
17337
17404
|
init_hook_command();
|
|
17338
17405
|
init_fs();
|
|
17339
17406
|
init_constants33();
|
|
17340
|
-
|
|
17407
|
+
init_hook_map();
|
|
17341
17408
|
}
|
|
17342
17409
|
});
|
|
17343
17410
|
async function importGeminiIgnore(projectRoot, results) {
|
|
@@ -17833,14 +17900,7 @@ function lintPermissions10(canonical, options) {
|
|
|
17833
17900
|
}
|
|
17834
17901
|
function lintHooks12(canonical) {
|
|
17835
17902
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
17836
|
-
const supported = [
|
|
17837
|
-
"PreToolUse",
|
|
17838
|
-
"PostToolUse",
|
|
17839
|
-
"Notification",
|
|
17840
|
-
"SubagentStart",
|
|
17841
|
-
"SubagentStop",
|
|
17842
|
-
"SessionStart"
|
|
17843
|
-
];
|
|
17903
|
+
const supported = [...CANONICAL_TO_GEMINI.keys()];
|
|
17844
17904
|
return unsupportedHookEventNames(canonical.hooks, supported).map(
|
|
17845
17905
|
(event) => createUnsupportedHookWarning(event, "gemini-cli", supported)
|
|
17846
17906
|
);
|
|
@@ -17848,6 +17908,7 @@ function lintHooks12(canonical) {
|
|
|
17848
17908
|
var init_lint15 = __esm({
|
|
17849
17909
|
"src/targets/gemini-cli/lint.ts"() {
|
|
17850
17910
|
init_helpers();
|
|
17911
|
+
init_hook_map();
|
|
17851
17912
|
}
|
|
17852
17913
|
});
|
|
17853
17914
|
|
|
@@ -17884,6 +17945,7 @@ var init_gemini_cli2 = __esm({
|
|
|
17884
17945
|
init_import_map_builders();
|
|
17885
17946
|
init_lint15();
|
|
17886
17947
|
init_scoped_settings_emit();
|
|
17948
|
+
init_hook_map();
|
|
17887
17949
|
init_settings();
|
|
17888
17950
|
target16 = {
|
|
17889
17951
|
name: "gemini-cli",
|
|
@@ -17934,6 +17996,7 @@ var init_gemini_cli2 = __esm({
|
|
|
17934
17996
|
permissions: lintPermissions10
|
|
17935
17997
|
},
|
|
17936
17998
|
emitScopedSettings: emitScopedGeminiSettings,
|
|
17999
|
+
hookContextEvents: GEMINI_HOOK_CONTEXT_EVENTS,
|
|
17937
18000
|
mergeGeneratedOutputContent(existing, pending, newContent, resolvedPath) {
|
|
17938
18001
|
const base = pending?.content ?? existing;
|
|
17939
18002
|
if (base !== null && resolvedPath === GEMINI_SETTINGS) {
|
|
@@ -18026,14 +18089,10 @@ function generateAgents17(canonical) {
|
|
|
18026
18089
|
content: serializeProjectedAgentSkill(agent)
|
|
18027
18090
|
}));
|
|
18028
18091
|
}
|
|
18029
|
-
function generateIgnore14(canonical) {
|
|
18030
|
-
if (canonical.ignore.length === 0) return [];
|
|
18031
|
-
return [{ path: GOOSE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
18032
|
-
}
|
|
18033
18092
|
function generateHooks12(canonical) {
|
|
18034
18093
|
return buildWrappedCommandHooks(canonical, GOOSE_HOOKS_FILE);
|
|
18035
18094
|
}
|
|
18036
|
-
var generateRules17, generatePermissions12;
|
|
18095
|
+
var generateRules17, generateIgnore14, generatePermissions12;
|
|
18037
18096
|
var init_generator20 = __esm({
|
|
18038
18097
|
"src/targets/goose/generator.ts"() {
|
|
18039
18098
|
init_managed_blocks();
|
|
@@ -18043,7 +18102,9 @@ var init_generator20 = __esm({
|
|
|
18043
18102
|
init_command_skill();
|
|
18044
18103
|
init_wrapped_command_hooks();
|
|
18045
18104
|
init_constants16();
|
|
18105
|
+
init_ignore_output();
|
|
18046
18106
|
generateRules17 = (canonical) => embeddedRootRule(canonical, GOOSE_TARGET, GOOSE_ROOT_FILE);
|
|
18107
|
+
generateIgnore14 = ignoreOutput(GOOSE_IGNORE);
|
|
18047
18108
|
generatePermissions12 = NO_OUTPUTS;
|
|
18048
18109
|
}
|
|
18049
18110
|
});
|
|
@@ -18948,10 +19009,6 @@ function generateAgents18(canonical) {
|
|
|
18948
19009
|
};
|
|
18949
19010
|
});
|
|
18950
19011
|
}
|
|
18951
|
-
function generateIgnore16(canonical) {
|
|
18952
|
-
if (canonical.ignore.length === 0) return [];
|
|
18953
|
-
return [{ path: JUNIE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
18954
|
-
}
|
|
18955
19012
|
function generateSkills17(canonical) {
|
|
18956
19013
|
return generateEmbeddedSkills(canonical, JUNIE_SKILLS_DIR);
|
|
18957
19014
|
}
|
|
@@ -18963,6 +19020,7 @@ function renderJunieGlobalInstructions(canonical) {
|
|
|
18963
19020
|
});
|
|
18964
19021
|
return appendEmbeddedRulesBlock(root?.body.trim() ?? "", nonRootRules);
|
|
18965
19022
|
}
|
|
19023
|
+
var generateIgnore16;
|
|
18966
19024
|
var init_generator22 = __esm({
|
|
18967
19025
|
"src/targets/junie/generator.ts"() {
|
|
18968
19026
|
init_mcp_servers();
|
|
@@ -18970,7 +19028,9 @@ var init_generator22 = __esm({
|
|
|
18970
19028
|
init_managed_blocks();
|
|
18971
19029
|
init_markdown();
|
|
18972
19030
|
init_constants18();
|
|
19031
|
+
init_ignore_output();
|
|
18973
19032
|
init_global_config2();
|
|
19033
|
+
generateIgnore16 = ignoreOutput(JUNIE_IGNORE);
|
|
18974
19034
|
}
|
|
18975
19035
|
});
|
|
18976
19036
|
|
|
@@ -19386,10 +19446,6 @@ function generateMcp15(canonical) {
|
|
|
19386
19446
|
}
|
|
19387
19447
|
];
|
|
19388
19448
|
}
|
|
19389
|
-
function generateIgnore17(canonical) {
|
|
19390
|
-
if (canonical.ignore.length === 0) return [];
|
|
19391
|
-
return [{ path: KILO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
19392
|
-
}
|
|
19393
19449
|
function generatePermissions15(canonical) {
|
|
19394
19450
|
if (!canonical.permissions) return [];
|
|
19395
19451
|
const { allow, deny } = canonical.permissions;
|
|
@@ -19404,11 +19460,14 @@ function generatePermissions15(canonical) {
|
|
|
19404
19460
|
function generateSkills18(canonical) {
|
|
19405
19461
|
return generateEmbeddedSkills(canonical, KILO_CODE_SKILLS_DIR);
|
|
19406
19462
|
}
|
|
19463
|
+
var generateIgnore17;
|
|
19407
19464
|
var init_generator23 = __esm({
|
|
19408
19465
|
"src/targets/kilo-code/generator.ts"() {
|
|
19409
19466
|
init_embedded_skill();
|
|
19410
19467
|
init_markdown();
|
|
19411
19468
|
init_constants19();
|
|
19469
|
+
init_ignore_output();
|
|
19470
|
+
generateIgnore17 = ignoreOutput(KILO_CODE_IGNORE);
|
|
19412
19471
|
}
|
|
19413
19472
|
});
|
|
19414
19473
|
var kiloNonRootRuleMapper, kiloCommandMapper, kiloAgentMapper;
|
|
@@ -21153,11 +21212,7 @@ function buildKiroAgentOutputs(canonical, rules = []) {
|
|
|
21153
21212
|
function generateAgents21(canonical) {
|
|
21154
21213
|
return buildKiroAgentOutputs(canonical);
|
|
21155
21214
|
}
|
|
21156
|
-
|
|
21157
|
-
if (canonical.ignore.length === 0) return [];
|
|
21158
|
-
return [{ path: KIRO_IGNORE, content: canonical.ignore.join("\n") }];
|
|
21159
|
-
}
|
|
21160
|
-
var generatePermissions17;
|
|
21215
|
+
var generateIgnore18, generatePermissions17;
|
|
21161
21216
|
var init_generator25 = __esm({
|
|
21162
21217
|
"src/targets/kiro/generator.ts"() {
|
|
21163
21218
|
init_no_outputs();
|
|
@@ -21166,6 +21221,8 @@ var init_generator25 = __esm({
|
|
|
21166
21221
|
init_markdown();
|
|
21167
21222
|
init_hook_format3();
|
|
21168
21223
|
init_constants21();
|
|
21224
|
+
init_ignore_output();
|
|
21225
|
+
generateIgnore18 = ignoreOutput(KIRO_IGNORE);
|
|
21169
21226
|
generatePermissions17 = NO_OUTPUTS;
|
|
21170
21227
|
}
|
|
21171
21228
|
});
|
|
@@ -23808,10 +23865,6 @@ function generateMcp19(canonical) {
|
|
|
23808
23865
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
23809
23866
|
return [{ path: QWEN_SETTINGS, content }];
|
|
23810
23867
|
}
|
|
23811
|
-
function generateIgnore21(canonical) {
|
|
23812
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
23813
|
-
return [{ path: QWEN_IGNORE, content: canonical.ignore.join("\n") }];
|
|
23814
|
-
}
|
|
23815
23868
|
function generateHooks18(canonical) {
|
|
23816
23869
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
23817
23870
|
const hooks = buildClaudeHooksObjectFromCanonical(canonical);
|
|
@@ -23829,11 +23882,14 @@ function generatePermissions21(canonical) {
|
|
|
23829
23882
|
if (ask.length > 0) permissions.ask = ask;
|
|
23830
23883
|
return [{ path: QWEN_SETTINGS, content: JSON.stringify({ permissions }, null, 2) }];
|
|
23831
23884
|
}
|
|
23885
|
+
var generateIgnore21;
|
|
23832
23886
|
var init_generator29 = __esm({
|
|
23833
23887
|
"src/targets/qwen-code/generator.ts"() {
|
|
23834
23888
|
init_markdown();
|
|
23835
23889
|
init_hooks_format2();
|
|
23836
23890
|
init_constants25();
|
|
23891
|
+
init_ignore_output();
|
|
23892
|
+
generateIgnore21 = ignoreOutput(QWEN_IGNORE);
|
|
23837
23893
|
}
|
|
23838
23894
|
});
|
|
23839
23895
|
|
|
@@ -25531,10 +25587,6 @@ function generateMcp23(canonical) {
|
|
|
25531
25587
|
}
|
|
25532
25588
|
];
|
|
25533
25589
|
}
|
|
25534
|
-
function generateIgnore24(canonical) {
|
|
25535
|
-
if (canonical.ignore.length === 0) return [];
|
|
25536
|
-
return [{ path: TRAE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
25537
|
-
}
|
|
25538
25590
|
function generateHooks20(canonical) {
|
|
25539
25591
|
if (!canonical.hooks) return [];
|
|
25540
25592
|
const hooks = {};
|
|
@@ -25555,12 +25607,15 @@ function generateHooks20(canonical) {
|
|
|
25555
25607
|
if (Object.keys(hooks).length === 0) return [];
|
|
25556
25608
|
return [{ path: TRAE_HOOKS_FILE, content: JSON.stringify({ version: 1, hooks }, null, 2) }];
|
|
25557
25609
|
}
|
|
25610
|
+
var generateIgnore24;
|
|
25558
25611
|
var init_generator33 = __esm({
|
|
25559
25612
|
"src/targets/trae/generator.ts"() {
|
|
25560
25613
|
init_embedded_skill();
|
|
25561
25614
|
init_markdown();
|
|
25562
25615
|
init_hook_command();
|
|
25563
25616
|
init_constants29();
|
|
25617
|
+
init_ignore_output();
|
|
25618
|
+
generateIgnore24 = ignoreOutput(TRAE_IGNORE);
|
|
25564
25619
|
}
|
|
25565
25620
|
});
|
|
25566
25621
|
|
|
@@ -26267,11 +26322,7 @@ function generateMcp24(canonical, ctx) {
|
|
|
26267
26322
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
26268
26323
|
return [{ path, content }];
|
|
26269
26324
|
}
|
|
26270
|
-
|
|
26271
|
-
if (canonical.ignore.length === 0) return [];
|
|
26272
|
-
return [{ path: WARP_IGNORE_FILE, content: canonical.ignore.join("\n") }];
|
|
26273
|
-
}
|
|
26274
|
-
var generateRules31, generatePermissions24, generateHooks21;
|
|
26325
|
+
var generateRules31, generatePermissions24, generateHooks21, generateIgnore25;
|
|
26275
26326
|
var init_generator34 = __esm({
|
|
26276
26327
|
"src/targets/warp/generator.ts"() {
|
|
26277
26328
|
init_managed_blocks();
|
|
@@ -26280,9 +26331,11 @@ var init_generator34 = __esm({
|
|
|
26280
26331
|
init_projected_agent_skill();
|
|
26281
26332
|
init_command_skill();
|
|
26282
26333
|
init_constants30();
|
|
26334
|
+
init_ignore_output();
|
|
26283
26335
|
generateRules31 = (canonical) => embeddedRootRule(canonical, WARP_TARGET, WARP_ROOT_FILE);
|
|
26284
26336
|
generatePermissions24 = NO_OUTPUTS;
|
|
26285
26337
|
generateHooks21 = NO_OUTPUTS;
|
|
26338
|
+
generateIgnore25 = ignoreOutput(WARP_IGNORE_FILE);
|
|
26286
26339
|
}
|
|
26287
26340
|
});
|
|
26288
26341
|
|
|
@@ -26907,13 +26960,12 @@ var init_rules4 = __esm({
|
|
|
26907
26960
|
});
|
|
26908
26961
|
|
|
26909
26962
|
// src/targets/windsurf/generator/ignore.ts
|
|
26910
|
-
|
|
26911
|
-
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
26912
|
-
return [{ path: CODEIUM_IGNORE, content: canonical.ignore.join("\n") }];
|
|
26913
|
-
}
|
|
26963
|
+
var generateIgnore26;
|
|
26914
26964
|
var init_ignore3 = __esm({
|
|
26915
26965
|
"src/targets/windsurf/generator/ignore.ts"() {
|
|
26916
26966
|
init_constants34();
|
|
26967
|
+
init_ignore_output();
|
|
26968
|
+
generateIgnore26 = ignoreOutput(CODEIUM_IGNORE);
|
|
26917
26969
|
}
|
|
26918
26970
|
});
|
|
26919
26971
|
|
|
@@ -26979,7 +27031,7 @@ function canonicalHookEventName(event) {
|
|
|
26979
27031
|
if (KNOWN_CANONICAL_HOOK_EVENTS.includes(event)) return event;
|
|
26980
27032
|
return WINDSURF_TO_CANONICAL.get(event) ?? null;
|
|
26981
27033
|
}
|
|
26982
|
-
var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_TO_CANONICAL;
|
|
27034
|
+
var KNOWN_CANONICAL_HOOK_EVENTS, WINDSURF_HOOK_CONTEXT_EVENTS, WINDSURF_TO_CANONICAL;
|
|
26983
27035
|
var init_hook_events = __esm({
|
|
26984
27036
|
"src/targets/windsurf/hook-events.ts"() {
|
|
26985
27037
|
init_hook_types();
|
|
@@ -26992,6 +27044,7 @@ var init_hook_events = __esm({
|
|
|
26992
27044
|
"SubagentStop",
|
|
26993
27045
|
...BEST_EFFORT_HOOK_EVENTS
|
|
26994
27046
|
];
|
|
27047
|
+
WINDSURF_HOOK_CONTEXT_EVENTS = [];
|
|
26995
27048
|
WINDSURF_TO_CANONICAL = new Map(
|
|
26996
27049
|
KNOWN_CANONICAL_HOOK_EVENTS.map((event) => [windsurfEventName(event), event])
|
|
26997
27050
|
);
|
|
@@ -27017,12 +27070,12 @@ function toWindsurfHooks(hooks) {
|
|
|
27017
27070
|
return result2;
|
|
27018
27071
|
}
|
|
27019
27072
|
function generateHooks22(canonical) {
|
|
27020
|
-
if (!canonical.hooks
|
|
27073
|
+
if (!canonical.hooks) return [];
|
|
27021
27074
|
const hooks = toWindsurfHooks(canonical.hooks);
|
|
27022
27075
|
if (Object.keys(hooks).length === 0) return [];
|
|
27023
27076
|
return [{ path: WINDSURF_HOOKS_FILE, content: JSON.stringify({ hooks }, null, 2) }];
|
|
27024
27077
|
}
|
|
27025
|
-
var
|
|
27078
|
+
var init_hooks5 = __esm({
|
|
27026
27079
|
"src/targets/windsurf/generator/hooks.ts"() {
|
|
27027
27080
|
init_hook_command();
|
|
27028
27081
|
init_constants34();
|
|
@@ -27074,7 +27127,7 @@ var init_generator35 = __esm({
|
|
|
27074
27127
|
init_workflows();
|
|
27075
27128
|
init_agents4();
|
|
27076
27129
|
init_mcp4();
|
|
27077
|
-
|
|
27130
|
+
init_hooks5();
|
|
27078
27131
|
init_skills4();
|
|
27079
27132
|
init_permissions6();
|
|
27080
27133
|
}
|
|
@@ -27193,7 +27246,7 @@ async function parseHooks(hooksPath, onParseError) {
|
|
|
27193
27246
|
return result2;
|
|
27194
27247
|
}
|
|
27195
27248
|
var VALID_TYPES;
|
|
27196
|
-
var
|
|
27249
|
+
var init_hooks6 = __esm({
|
|
27197
27250
|
"src/canonical/features/hooks.ts"() {
|
|
27198
27251
|
init_syntax_error();
|
|
27199
27252
|
init_fs();
|
|
@@ -27274,7 +27327,7 @@ var WILDCARD_MATCHER;
|
|
|
27274
27327
|
var init_importer_hooks2 = __esm({
|
|
27275
27328
|
"src/targets/windsurf/importer-hooks.ts"() {
|
|
27276
27329
|
init_canonical_paths();
|
|
27277
|
-
|
|
27330
|
+
init_hooks6();
|
|
27278
27331
|
init_fs();
|
|
27279
27332
|
init_constants34();
|
|
27280
27333
|
init_hook_events();
|
|
@@ -27575,6 +27628,7 @@ var init_windsurf2 = __esm({
|
|
|
27575
27628
|
init_merge14();
|
|
27576
27629
|
init_linter32();
|
|
27577
27630
|
init_lint31();
|
|
27631
|
+
init_hook_events();
|
|
27578
27632
|
init_import_map_builders();
|
|
27579
27633
|
init_conversions();
|
|
27580
27634
|
init_projected_agent_skill();
|
|
@@ -27706,6 +27760,7 @@ var init_windsurf2 = __esm({
|
|
|
27706
27760
|
},
|
|
27707
27761
|
emptyImportMessage: "No Windsurf config found (.windsurfrules, .windsurf/rules, .windsurfignore, or .codeiumignore).",
|
|
27708
27762
|
supportsConversion: { agents: true },
|
|
27763
|
+
hookContextEvents: WINDSURF_HOOK_CONTEXT_EVENTS,
|
|
27709
27764
|
lintRules: lintRules32,
|
|
27710
27765
|
lint: {
|
|
27711
27766
|
commands: lintCommands10,
|
|
@@ -28850,6 +28905,23 @@ var init_builtin_targets = __esm({
|
|
|
28850
28905
|
}
|
|
28851
28906
|
});
|
|
28852
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
|
+
|
|
28853
28925
|
// src/core/generate/engine.ts
|
|
28854
28926
|
init_builtin_targets();
|
|
28855
28927
|
init_registry();
|
|
@@ -29752,11 +29824,12 @@ async function generateHooksFeature(results, targets, canonical, projectRoot, sc
|
|
|
29752
29824
|
const gen = resolveTargetFeatureGenerator(target34, "hooks", config, scope) ?? getDescriptor(target34)?.generators.generateHooks;
|
|
29753
29825
|
if (!gen) continue;
|
|
29754
29826
|
const ctx = featureContext(target34, "hooks", scope);
|
|
29755
|
-
|
|
29827
|
+
const projected = withTargetRecallHooks(canonical, target34);
|
|
29828
|
+
let outputs = [...gen(projected, ctx)];
|
|
29756
29829
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29757
29830
|
const post = descriptor34?.postProcessHookOutputs;
|
|
29758
29831
|
if (post) {
|
|
29759
|
-
outputs = [...await post(projectRoot,
|
|
29832
|
+
outputs = [...await post(projectRoot, projected, outputs)];
|
|
29760
29833
|
}
|
|
29761
29834
|
const options = outputMergeOptions(target34);
|
|
29762
29835
|
for (const out2 of outputs) {
|
|
@@ -29769,7 +29842,7 @@ async function generateScopedSettingsFeature(results, targets, canonical, projec
|
|
|
29769
29842
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29770
29843
|
const emit = descriptor34?.emitScopedSettings;
|
|
29771
29844
|
if (!emit) continue;
|
|
29772
|
-
const outputs = emit(canonical, scope, enabledFeatures);
|
|
29845
|
+
const outputs = emit(withTargetRecallHooks(canonical, target34), scope, enabledFeatures);
|
|
29773
29846
|
if (outputs.length === 0) continue;
|
|
29774
29847
|
const options = outputMergeOptions(target34);
|
|
29775
29848
|
for (const out2 of outputs) {
|
|
@@ -29812,7 +29885,12 @@ async function generate(ctx) {
|
|
|
29812
29885
|
const descriptor34 = getBuiltinTargetDefinition(target34) ?? getDescriptor(target34);
|
|
29813
29886
|
const scopeExtras = descriptor34?.globalSupport?.scopeExtras;
|
|
29814
29887
|
if (scopeExtras) {
|
|
29815
|
-
const extras = await scopeExtras(
|
|
29888
|
+
const extras = await scopeExtras(
|
|
29889
|
+
withTargetRecallHooks(canonical, target34),
|
|
29890
|
+
projectRoot,
|
|
29891
|
+
scope,
|
|
29892
|
+
enabledFeatures
|
|
29893
|
+
);
|
|
29816
29894
|
await emitScopeExtras(results, target34, extras, projectRoot);
|
|
29817
29895
|
}
|
|
29818
29896
|
}
|
|
@@ -31119,7 +31197,7 @@ async function parsePermissions(permissionsPath, onParseError) {
|
|
|
31119
31197
|
}
|
|
31120
31198
|
|
|
31121
31199
|
// src/canonical/load/loader.ts
|
|
31122
|
-
|
|
31200
|
+
init_hooks6();
|
|
31123
31201
|
|
|
31124
31202
|
// src/canonical/features/ignore.ts
|
|
31125
31203
|
init_fs();
|
|
@@ -31168,10 +31246,10 @@ function ruleSlug4(r) {
|
|
|
31168
31246
|
function mergeByKey(base, overlay, key) {
|
|
31169
31247
|
return [...new Map([...base, ...overlay].map((item) => [key(item), item])).values()];
|
|
31170
31248
|
}
|
|
31171
|
-
function mergeCanonicalFiles(base, overlay) {
|
|
31249
|
+
function mergeCanonicalFiles(base, overlay, options = {}) {
|
|
31172
31250
|
const mcp = mergeMcp7(base.mcp, overlay.mcp);
|
|
31173
31251
|
const permissions = mergePermissions2(base.permissions, overlay.permissions);
|
|
31174
|
-
const hooks =
|
|
31252
|
+
const hooks = options.hooks === "combine" ? combineHooks(base.hooks, overlay.hooks) : overrideHooks(base.hooks, overlay.hooks);
|
|
31175
31253
|
const ignore = mergeUniqueStrings(base.ignore, overlay.ignore);
|
|
31176
31254
|
return {
|
|
31177
31255
|
rules: mergeByKey(base.rules, overlay.rules, ruleSlug4),
|
|
@@ -31210,17 +31288,31 @@ function mergeUniqueStrings(base, overlay) {
|
|
|
31210
31288
|
}
|
|
31211
31289
|
return merged;
|
|
31212
31290
|
}
|
|
31213
|
-
function
|
|
31291
|
+
function overrideHooks(base, overlay) {
|
|
31214
31292
|
if (!base && !overlay) return null;
|
|
31215
31293
|
const result2 = {};
|
|
31216
|
-
const
|
|
31217
|
-
for (const k of keys) {
|
|
31294
|
+
for (const k of hookEvents(base, overlay)) {
|
|
31218
31295
|
const o = overlay?.[k];
|
|
31219
|
-
|
|
31220
|
-
|
|
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)))];
|
|
31221
31307
|
}
|
|
31222
31308
|
return result2;
|
|
31223
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
|
+
}
|
|
31224
31316
|
|
|
31225
31317
|
// src/config/resolve/native-format-detector.ts
|
|
31226
31318
|
init_fs();
|
|
@@ -31991,7 +32083,7 @@ function gateExtendElevatedArtifacts(canonical, ext) {
|
|
|
31991
32083
|
});
|
|
31992
32084
|
}
|
|
31993
32085
|
init_mcp();
|
|
31994
|
-
|
|
32086
|
+
init_hooks6();
|
|
31995
32087
|
|
|
31996
32088
|
// src/install/pack/pack-reader.ts
|
|
31997
32089
|
init_fs();
|
|
@@ -32078,7 +32170,7 @@ async function loadPacksCanonical(abDir) {
|
|
|
32078
32170
|
const canonical = await loadPackCanonical(packDir);
|
|
32079
32171
|
const filtered = filterCanonicalByFeatures(canonical, meta.features);
|
|
32080
32172
|
const picked = applyExtendPick(filtered, meta.features, meta.pick, meta.name);
|
|
32081
|
-
merged = mergeCanonicalFiles(merged, picked);
|
|
32173
|
+
merged = mergeCanonicalFiles(merged, picked, { hooks: "combine" });
|
|
32082
32174
|
}
|
|
32083
32175
|
return merged;
|
|
32084
32176
|
}
|
|
@@ -32129,9 +32221,10 @@ async function loadCanonicalWithExtends(config, configDir, options = {}, canonic
|
|
|
32129
32221
|
merged = mergeCanonicalFiles(merged, picked);
|
|
32130
32222
|
}
|
|
32131
32223
|
const packsCanonical = await loadPacksCanonical(canonicalDir);
|
|
32132
|
-
merged = mergeCanonicalFiles(merged, packsCanonical);
|
|
32224
|
+
merged = mergeCanonicalFiles(merged, packsCanonical, { hooks: "combine" });
|
|
32133
32225
|
const localCanonical = await loadCanonicalFiles(canonicalDir);
|
|
32134
32226
|
merged = mergeCanonicalFiles(merged, localCanonical);
|
|
32227
|
+
merged = { ...merged, hooks: combineHooks(merged.hooks, packsCanonical.hooks) };
|
|
32135
32228
|
return { canonical: merged, resolvedExtends };
|
|
32136
32229
|
}
|
|
32137
32230
|
|
|
@@ -32410,6 +32503,9 @@ function lintRuleScopeInversion(input) {
|
|
|
32410
32503
|
}
|
|
32411
32504
|
return out2;
|
|
32412
32505
|
}
|
|
32506
|
+
|
|
32507
|
+
// src/lessons/graph-store.ts
|
|
32508
|
+
init_fs_text_encoding();
|
|
32413
32509
|
var VersionSchema = z.union([z.literal(1), z.literal(2)]);
|
|
32414
32510
|
var IdSchema = z.string().regex(/^[a-z0-9-]+$/, "id must be kebab-case");
|
|
32415
32511
|
var DateSchema = z.string().regex(
|
|
@@ -32453,13 +32549,13 @@ function parseGraph(raw) {
|
|
|
32453
32549
|
}
|
|
32454
32550
|
|
|
32455
32551
|
// src/lessons/graph-store.ts
|
|
32456
|
-
var
|
|
32552
|
+
var LESSONS_GRAPH_PATH = ".agentsmesh/lessons/lessons.json";
|
|
32457
32553
|
function graphFilePath(projectRoot) {
|
|
32458
|
-
return resolve(projectRoot,
|
|
32554
|
+
return resolve(projectRoot, LESSONS_GRAPH_PATH);
|
|
32459
32555
|
}
|
|
32460
32556
|
function loadLessonsGraph(projectRoot) {
|
|
32461
32557
|
const raw = readFileSync(graphFilePath(projectRoot), "utf8");
|
|
32462
|
-
return parseGraph(JSON.parse(raw));
|
|
32558
|
+
return parseGraph(JSON.parse(stripBom(raw)));
|
|
32463
32559
|
}
|
|
32464
32560
|
var BASE_REL = ".agentsmesh/lessons";
|
|
32465
32561
|
function lessonsPaths(projectRoot) {
|
|
@@ -32476,9 +32572,76 @@ function lessonsPaths(projectRoot) {
|
|
|
32476
32572
|
function toRelPath(projectRoot, absolute) {
|
|
32477
32573
|
return relative(projectRoot, absolute).split(sep).join("/");
|
|
32478
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
|
|
32479
32636
|
var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
32480
32637
|
var MAX_FILES = 2e5;
|
|
32481
|
-
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) {
|
|
32482
32645
|
const out2 = /* @__PURE__ */ new Set();
|
|
32483
32646
|
try {
|
|
32484
32647
|
const stack = [projectRoot];
|
|
@@ -32489,14 +32652,14 @@ function listProjectFiles(projectRoot) {
|
|
|
32489
32652
|
if (!SKIP_DIRS.has(entry.name)) stack.push(join(dir, entry.name));
|
|
32490
32653
|
} else if (entry.isFile()) {
|
|
32491
32654
|
out2.add(toRelPath(projectRoot, join(dir, entry.name)));
|
|
32492
|
-
if (out2.size >
|
|
32655
|
+
if (out2.size > maxFiles) return null;
|
|
32493
32656
|
}
|
|
32494
32657
|
}
|
|
32495
32658
|
}
|
|
32496
32659
|
} catch {
|
|
32497
32660
|
return null;
|
|
32498
32661
|
}
|
|
32499
|
-
return out2;
|
|
32662
|
+
return projectFilesOf(out2, () => readGitPathHistory(projectRoot));
|
|
32500
32663
|
}
|
|
32501
32664
|
|
|
32502
32665
|
// src/lessons/validate-checks.ts
|
|
@@ -32673,10 +32836,307 @@ function collectOrphans(graph, findings) {
|
|
|
32673
32836
|
}
|
|
32674
32837
|
}
|
|
32675
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
|
|
32676
33010
|
function normalizeRule(rule) {
|
|
32677
33011
|
return rule.trim().replace(/\s+/g, " ").toLowerCase();
|
|
32678
33012
|
}
|
|
32679
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
|
+
|
|
32680
33140
|
// src/lessons/regex-linear/nfa-compile.ts
|
|
32681
33141
|
var MAX_NFA_STATES = 2e3;
|
|
32682
33142
|
var Builder = class {
|
|
@@ -32868,6 +33328,9 @@ function escapeClass(c2) {
|
|
|
32868
33328
|
var HEX2 = /^[0-9a-fA-F]{2}$/;
|
|
32869
33329
|
var HEX4 = /^[0-9a-fA-F]{4}$/;
|
|
32870
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
|
+
}
|
|
32871
33334
|
if (c2 === "x") {
|
|
32872
33335
|
const hex2 = src.slice(i, i + 2);
|
|
32873
33336
|
return HEX2.test(hex2) ? { ch: String.fromCharCode(parseInt(hex2, 16)), len: 2 } : { ch: "x", len: 0 };
|
|
@@ -32957,7 +33420,7 @@ function parseRegex(src) {
|
|
|
32957
33420
|
function parseAtom() {
|
|
32958
33421
|
const c2 = peek();
|
|
32959
33422
|
if (c2 === "(") return parseGroup2();
|
|
32960
|
-
if (c2 === "[") return
|
|
33423
|
+
if (c2 === "[") return parseClass2();
|
|
32961
33424
|
if (c2 === "\\") return parseEscape();
|
|
32962
33425
|
if (c2 === ".") {
|
|
32963
33426
|
i += 1;
|
|
@@ -33016,7 +33479,7 @@ function parseRegex(src) {
|
|
|
33016
33479
|
}
|
|
33017
33480
|
return { k: "char", ch: escapeLiteral(c2) };
|
|
33018
33481
|
}
|
|
33019
|
-
function
|
|
33482
|
+
function parseClass2() {
|
|
33020
33483
|
i += 1;
|
|
33021
33484
|
const negate = peek() === "^";
|
|
33022
33485
|
if (negate) i += 1;
|
|
@@ -33069,17 +33532,17 @@ function parseRegex(src) {
|
|
|
33069
33532
|
}
|
|
33070
33533
|
|
|
33071
33534
|
// src/lessons/regex-linear/index.ts
|
|
33072
|
-
var
|
|
33535
|
+
var cache3 = /* @__PURE__ */ new Map();
|
|
33073
33536
|
function compileLinearMatcher(pattern) {
|
|
33074
|
-
const hit =
|
|
33075
|
-
if (hit !== void 0 ||
|
|
33537
|
+
const hit = cache3.get(pattern);
|
|
33538
|
+
if (hit !== void 0 || cache3.has(pattern)) return hit ?? null;
|
|
33076
33539
|
let matcher;
|
|
33077
33540
|
try {
|
|
33078
33541
|
matcher = buildMatcher(parseRegex(pattern));
|
|
33079
33542
|
} catch {
|
|
33080
33543
|
matcher = null;
|
|
33081
33544
|
}
|
|
33082
|
-
|
|
33545
|
+
cache3.set(pattern, matcher);
|
|
33083
33546
|
return matcher;
|
|
33084
33547
|
}
|
|
33085
33548
|
|
|
@@ -33120,6 +33583,8 @@ function collectDuplicateRules(graph, findings) {
|
|
|
33120
33583
|
}
|
|
33121
33584
|
function collectInvalidTriggerPatterns(graph, findings) {
|
|
33122
33585
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33586
|
+
const globFinding = unsafeGlobFinding(triggerId, trigger);
|
|
33587
|
+
if (globFinding !== null) findings.push(globFinding);
|
|
33123
33588
|
if (trigger.kind !== "command_pattern") continue;
|
|
33124
33589
|
try {
|
|
33125
33590
|
new RegExp(trigger.pattern);
|
|
@@ -33127,7 +33592,7 @@ function collectInvalidTriggerPatterns(graph, findings) {
|
|
|
33127
33592
|
findings.push({
|
|
33128
33593
|
level: "error",
|
|
33129
33594
|
code: "INVALID_TRIGGER_PATTERN",
|
|
33130
|
-
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)}.`,
|
|
33131
33596
|
triggerId
|
|
33132
33597
|
});
|
|
33133
33598
|
continue;
|
|
@@ -33136,12 +33601,16 @@ function collectInvalidTriggerPatterns(graph, findings) {
|
|
|
33136
33601
|
findings.push({
|
|
33137
33602
|
level: "error",
|
|
33138
33603
|
code: "UNSAFE_TRIGGER_PATTERN",
|
|
33139
|
-
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.`,
|
|
33140
33605
|
triggerId
|
|
33141
33606
|
});
|
|
33142
33607
|
}
|
|
33143
33608
|
}
|
|
33144
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
|
+
}
|
|
33145
33614
|
function collectBackslashGlobPatterns(graph, findings) {
|
|
33146
33615
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33147
33616
|
if (trigger.kind !== "file_glob") continue;
|
|
@@ -33222,7 +33691,11 @@ function collectTriggerSetCollisions(graph, findings) {
|
|
|
33222
33691
|
|
|
33223
33692
|
// src/lessons/glob-breadth.ts
|
|
33224
33693
|
var WILDCARD = /[*?[\]]/;
|
|
33694
|
+
function isNegatedGlob(pattern) {
|
|
33695
|
+
return pattern.startsWith("!");
|
|
33696
|
+
}
|
|
33225
33697
|
function globNarrowness(pattern) {
|
|
33698
|
+
if (isNegatedGlob(pattern)) return 0;
|
|
33226
33699
|
const segments = pattern.replaceAll("\\", "/").split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
33227
33700
|
if (segments.length === 0) return 0;
|
|
33228
33701
|
let literal = 0;
|
|
@@ -33273,6 +33746,15 @@ function isBroadCommandPattern(pattern) {
|
|
|
33273
33746
|
}
|
|
33274
33747
|
return hits > COMMAND_PROBE_CORPUS.length * BROAD_HIT_RATIO;
|
|
33275
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
|
+
}
|
|
33276
33758
|
|
|
33277
33759
|
// src/lessons/validate-liveness.ts
|
|
33278
33760
|
function activeTriggerIds(graph) {
|
|
@@ -33283,24 +33765,33 @@ function activeTriggerIds(graph) {
|
|
|
33283
33765
|
}
|
|
33284
33766
|
return ids;
|
|
33285
33767
|
}
|
|
33286
|
-
function
|
|
33287
|
-
const active = activeTriggerIds(graph);
|
|
33768
|
+
function fileGlobLiveness(graph, knownPaths, triggerIds) {
|
|
33769
|
+
const active = activeTriggerIds(graph) ;
|
|
33288
33770
|
const paths2 = [...knownPaths];
|
|
33289
|
-
const
|
|
33771
|
+
const missing = [];
|
|
33290
33772
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33291
|
-
if (trigger.kind !== "file_glob") continue;
|
|
33292
|
-
|
|
33293
|
-
|
|
33294
|
-
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);
|
|
33295
33786
|
}
|
|
33296
|
-
return dead;
|
|
33787
|
+
return { dead, pending };
|
|
33297
33788
|
}
|
|
33298
33789
|
function collectDeadFileGlobs(graph, findings, knownPaths) {
|
|
33299
|
-
for (const triggerId of
|
|
33790
|
+
for (const triggerId of fileGlobLiveness(graph, knownPaths).dead) {
|
|
33300
33791
|
findings.push({
|
|
33301
33792
|
level: "warning",
|
|
33302
33793
|
code: "DEAD_FILE_GLOB",
|
|
33303
|
-
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\`.`,
|
|
33304
33795
|
triggerId
|
|
33305
33796
|
});
|
|
33306
33797
|
}
|
|
@@ -33372,14 +33863,14 @@ var STOP = /* @__PURE__ */ new Set([
|
|
|
33372
33863
|
"its",
|
|
33373
33864
|
"must"
|
|
33374
33865
|
]);
|
|
33375
|
-
function
|
|
33866
|
+
function tokenize2(text) {
|
|
33376
33867
|
return text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 2 && !STOP.has(t));
|
|
33377
33868
|
}
|
|
33378
33869
|
|
|
33379
33870
|
// src/lessons/keyword-signal.ts
|
|
33380
33871
|
var MAX_RECOMMENDED_KEYWORD_TOKENS = 5;
|
|
33381
33872
|
function isLowSignalKeyword(pattern) {
|
|
33382
|
-
return
|
|
33873
|
+
return tokenize2(pattern).length > MAX_RECOMMENDED_KEYWORD_TOKENS;
|
|
33383
33874
|
}
|
|
33384
33875
|
function splitRawTokens(pattern) {
|
|
33385
33876
|
return pattern.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 0);
|
|
@@ -33387,7 +33878,7 @@ function splitRawTokens(pattern) {
|
|
|
33387
33878
|
function keywordNeedleLosesTokens(pattern) {
|
|
33388
33879
|
const raw = splitRawTokens(pattern);
|
|
33389
33880
|
if (raw.length < 2) return false;
|
|
33390
|
-
return
|
|
33881
|
+
return tokenize2(pattern).length !== raw.length;
|
|
33391
33882
|
}
|
|
33392
33883
|
|
|
33393
33884
|
// src/lessons/validate-keywords.ts
|
|
@@ -33410,7 +33901,7 @@ function collectStopwordKeywords(graph, findings) {
|
|
|
33410
33901
|
for (const [triggerId, trigger] of Object.entries(graph.triggers)) {
|
|
33411
33902
|
if (trigger.kind !== "keyword") continue;
|
|
33412
33903
|
if (!active.has(triggerId)) continue;
|
|
33413
|
-
if (
|
|
33904
|
+
if (tokenize2(trigger.pattern).length !== 0 && !keywordNeedleLosesTokens(trigger.pattern)) {
|
|
33414
33905
|
continue;
|
|
33415
33906
|
}
|
|
33416
33907
|
findings.push({
|
|
@@ -33458,7 +33949,6 @@ function validateLessonsGraph(graph, options = {}) {
|
|
|
33458
33949
|
|
|
33459
33950
|
// src/core/lint/shared/lessons.ts
|
|
33460
33951
|
var LESSONS_TARGET = "lessons";
|
|
33461
|
-
var GRAPH_REL = ".agentsmesh/lessons/lessons.json";
|
|
33462
33952
|
var ROOT_RULE_REL = ".agentsmesh/rules/_root.md";
|
|
33463
33953
|
var LESSONS_HEADING = /^## Lessons \(/m;
|
|
33464
33954
|
function lintLessonsSubsystem(projectRoot, scope) {
|
|
@@ -33473,7 +33963,7 @@ function lintLessonsSubsystem(projectRoot, scope) {
|
|
|
33473
33963
|
return [
|
|
33474
33964
|
diag(
|
|
33475
33965
|
"error",
|
|
33476
|
-
|
|
33966
|
+
LESSONS_GRAPH_PATH,
|
|
33477
33967
|
`lessons.json failed to load: ${err instanceof Error ? err.message : String(err)}`
|
|
33478
33968
|
)
|
|
33479
33969
|
];
|
|
@@ -33481,7 +33971,7 @@ function lintLessonsSubsystem(projectRoot, scope) {
|
|
|
33481
33971
|
const knownPaths = listProjectFiles(projectRoot) ?? void 0;
|
|
33482
33972
|
const report = validateLessonsGraph(graph, { knownPaths });
|
|
33483
33973
|
for (const finding of report.findings) {
|
|
33484
|
-
out2.push(diag(finding.level,
|
|
33974
|
+
out2.push(diag(finding.level, LESSONS_GRAPH_PATH, `[${finding.code}] ${finding.message}`));
|
|
33485
33975
|
}
|
|
33486
33976
|
const rootRuleAbs = join(projectRoot, ROOT_RULE_REL);
|
|
33487
33977
|
const rootRuleBody = existsSync(rootRuleAbs) ? readFileSync(rootRuleAbs, "utf8") : "";
|
|
@@ -33503,8 +33993,8 @@ function diag(level, file, message) {
|
|
|
33503
33993
|
// src/core/lint/linter.ts
|
|
33504
33994
|
var EXCLUDE_DIRS = ["node_modules", ".git", "dist", "coverage", ".agentsmesh"];
|
|
33505
33995
|
function isExcludedProjectPath(rel2) {
|
|
33506
|
-
const
|
|
33507
|
-
return EXCLUDE_DIRS.some((d) =>
|
|
33996
|
+
const posix9 = rel2.replaceAll("\\", "/");
|
|
33997
|
+
return EXCLUDE_DIRS.some((d) => posix9.includes(`/${d}/`) || posix9.startsWith(`${d}/`));
|
|
33508
33998
|
}
|
|
33509
33999
|
async function getProjectFiles(projectRoot) {
|
|
33510
34000
|
const all = await readDirRecursive(projectRoot);
|
|
@@ -33897,14 +34387,22 @@ async function findUntrackedManagedDirFiles(args) {
|
|
|
33897
34387
|
return [...found].sort();
|
|
33898
34388
|
}
|
|
33899
34389
|
|
|
34390
|
+
// src/lessons/conflict-markers.ts
|
|
34391
|
+
function hasConflictMarkers(text) {
|
|
34392
|
+
return /^(?:<{7}|>{7})(?: |\r?$)/m.test(text);
|
|
34393
|
+
}
|
|
34394
|
+
|
|
33900
34395
|
// src/core/check/lock-sync.ts
|
|
34396
|
+
init_fs();
|
|
33901
34397
|
async function checkLockSync(opts) {
|
|
33902
34398
|
const { config, configDir, canonicalDir, rootBase, scope = "project" } = opts;
|
|
33903
34399
|
const lock = await readLock(canonicalDir);
|
|
33904
34400
|
if (lock === null) {
|
|
34401
|
+
const text = await readFileSafe(join(canonicalDir, ".lock"));
|
|
33905
34402
|
return {
|
|
33906
34403
|
inSync: false,
|
|
33907
34404
|
hasLock: false,
|
|
34405
|
+
lockConflict: text !== null && hasConflictMarkers(text),
|
|
33908
34406
|
canonicalDrift: false,
|
|
33909
34407
|
outputDrift: false,
|
|
33910
34408
|
modified: [],
|
|
@@ -33974,6 +34472,7 @@ async function checkLockSync(opts) {
|
|
|
33974
34472
|
return {
|
|
33975
34473
|
inSync,
|
|
33976
34474
|
hasLock: true,
|
|
34475
|
+
lockConflict: false,
|
|
33977
34476
|
canonicalDrift,
|
|
33978
34477
|
outputDrift,
|
|
33979
34478
|
modified,
|