@lousy-agents/mcp 5.13.6 → 5.14.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.
@@ -3333,7 +3333,7 @@ class Ajv {
3333
3333
  constructor(opts = {}) {
3334
3334
  this.schemas = {};
3335
3335
  this.refs = {};
3336
- this.formats = {};
3336
+ this.formats = Object.create(null);
3337
3337
  this._compilations = new Set();
3338
3338
  this._loading = {};
3339
3339
  this._cache = new Map();
@@ -6559,7 +6559,7 @@ function escapeJsonPtr(str) {
6559
6559
 
6560
6560
 
6561
6561
  },
6562
- 832(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
6562
+ 8050(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
6563
6563
  // NAMESPACE OBJECT: ../../node_modules/micromark/lib/constructs.js
6564
6564
  var constructs_namespaceObject = {};
6565
6565
  __webpack_require__.r(constructs_namespaceObject);
@@ -26562,7 +26562,7 @@ function isPathWithinRoot(rootPath, candidatePath) {
26562
26562
  }
26563
26563
  /**
26564
26564
  * Ensures existing path segments under targetDir are not symbolic links.
26565
- */ async function assertPathHasNoSymbolicLinks(targetDir, absolutePath) {
26565
+ */ async function file_system_utils_assertPathHasNoSymbolicLinks(targetDir, absolutePath) {
26566
26566
  const rootPath = await (0,promises_.realpath)(targetDir);
26567
26567
  if (!isPathWithinRoot(rootPath, absolutePath)) {
26568
26568
  throw new Error(`Resolved path is outside target directory: ${absolutePath}`);
@@ -26592,7 +26592,7 @@ function isPathWithinRoot(rootPath, candidatePath) {
26592
26592
  * Resolves a relative path under targetDir and validates it does not pass through symlinks.
26593
26593
  */ async function file_system_utils_resolveSafePath(targetDir, relativePath) {
26594
26594
  const resolvedPath = await resolvePathWithinRoot(targetDir, relativePath);
26595
- await assertPathHasNoSymbolicLinks(targetDir, resolvedPath);
26595
+ await file_system_utils_assertPathHasNoSymbolicLinks(targetDir, resolvedPath);
26596
26596
  return resolvedPath;
26597
26597
  }
26598
26598
  /**
@@ -26778,14 +26778,14 @@ const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
26778
26778
  const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
26779
26779
  const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
26780
26780
  const _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
26781
- const sep = "/";
26781
+ const pathe_M_eThtNZ_sep = "/";
26782
26782
  const normalize = function(path) {
26783
26783
  if (path.length === 0) {
26784
26784
  return ".";
26785
26785
  }
26786
26786
  path = normalizeWindowsPath(path);
26787
26787
  const isUNCPath = path.match(_UNC_REGEX);
26788
- const isPathAbsolute = isAbsolute(path);
26788
+ const isPathAbsolute = pathe_M_eThtNZ_isAbsolute(path);
26789
26789
  const trailingSeparator = path[path.length - 1] === "/";
26790
26790
  path = normalizeString(path, !isPathAbsolute);
26791
26791
  if (path.length === 0) {
@@ -26806,7 +26806,7 @@ const normalize = function(path) {
26806
26806
  }
26807
26807
  return `//${path}`;
26808
26808
  }
26809
- return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
26809
+ return isPathAbsolute && !pathe_M_eThtNZ_isAbsolute(path) ? `/${path}` : path;
26810
26810
  };
26811
26811
  const pathe_M_eThtNZ_join = function(...segments) {
26812
26812
  let path = "";
@@ -26845,10 +26845,10 @@ const pathe_M_eThtNZ_resolve = function(...arguments_) {
26845
26845
  continue;
26846
26846
  }
26847
26847
  resolvedPath = `${path}/${resolvedPath}`;
26848
- resolvedAbsolute = isAbsolute(path);
26848
+ resolvedAbsolute = pathe_M_eThtNZ_isAbsolute(path);
26849
26849
  }
26850
26850
  resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
26851
- if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
26851
+ if (resolvedAbsolute && !pathe_M_eThtNZ_isAbsolute(resolvedPath)) {
26852
26852
  return `/${resolvedPath}`;
26853
26853
  }
26854
26854
  return resolvedPath.length > 0 ? resolvedPath : ".";
@@ -26912,7 +26912,7 @@ function normalizeString(path, allowAboveRoot) {
26912
26912
  }
26913
26913
  return res;
26914
26914
  }
26915
- const isAbsolute = function(p) {
26915
+ const pathe_M_eThtNZ_isAbsolute = function(p) {
26916
26916
  return _IS_ABSOLUTE_RE.test(p);
26917
26917
  };
26918
26918
  const toNamespacedPath = function(p) {
@@ -26923,7 +26923,7 @@ const pathe_M_eThtNZ_extname = function(p) {
26923
26923
  const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
26924
26924
  return match && match[1] || "";
26925
26925
  };
26926
- const relative = function(from, to) {
26926
+ const pathe_M_eThtNZ_relative = function(from, to) {
26927
26927
  const _from = pathe_M_eThtNZ_resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
26928
26928
  const _to = pathe_M_eThtNZ_resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
26929
26929
  if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) {
@@ -26944,7 +26944,7 @@ const pathe_M_eThtNZ_dirname = function(p) {
26944
26944
  if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
26945
26945
  segments[0] += "/";
26946
26946
  }
26947
- return segments.join("/") || (isAbsolute(p) ? "/" : ".");
26947
+ return segments.join("/") || (pathe_M_eThtNZ_isAbsolute(p) ? "/" : ".");
26948
26948
  };
26949
26949
  const pathe_M_eThtNZ_format = function(p) {
26950
26950
  const ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "";
@@ -26989,15 +26989,15 @@ const pathe_M_eThtNZ_path = (/* unused pure expression or super */ null && ({
26989
26989
  dirname: pathe_M_eThtNZ_dirname,
26990
26990
  extname: pathe_M_eThtNZ_extname,
26991
26991
  format: pathe_M_eThtNZ_format,
26992
- isAbsolute: isAbsolute,
26992
+ isAbsolute: pathe_M_eThtNZ_isAbsolute,
26993
26993
  join: pathe_M_eThtNZ_join,
26994
26994
  matchesGlob: matchesGlob,
26995
26995
  normalize: normalize,
26996
26996
  normalizeString: normalizeString,
26997
26997
  parse: pathe_M_eThtNZ_parse,
26998
- relative: relative,
26998
+ relative: pathe_M_eThtNZ_relative,
26999
26999
  resolve: pathe_M_eThtNZ_resolve,
27000
- sep: sep,
27000
+ sep: pathe_M_eThtNZ_sep,
27001
27001
  toNamespacedPath: toNamespacedPath
27002
27002
  }));
27003
27003
 
@@ -28502,371 +28502,317 @@ var jsonc = __webpack_require__(5975);
28502
28502
 
28503
28503
 
28504
28504
 
28505
-
28506
28505
  const defaultFindOptions = {
28507
- startingFrom: ".",
28508
- rootPattern: /^node_modules$/,
28509
- reverse: false,
28510
- test: (filePath) => {
28511
- try {
28512
- if ((0,external_node_fs_.statSync)(filePath).isFile()) {
28513
- return true;
28514
- }
28515
- } catch {
28516
- }
28517
- }
28506
+ startingFrom: ".",
28507
+ rootPattern: /^node_modules$/,
28508
+ reverse: false,
28509
+ test: (filePath) => {
28510
+ try {
28511
+ if ((0,external_node_fs_.statSync)(filePath).isFile()) return true;
28512
+ } catch {}
28513
+ }
28518
28514
  };
28519
28515
  async function findFile(filename, _options = {}) {
28520
- const filenames = Array.isArray(filename) ? filename : [filename];
28521
- const options = { ...defaultFindOptions, ..._options };
28522
- const basePath = pathe_M_eThtNZ_resolve(options.startingFrom);
28523
- const leadingSlash = basePath[0] === "/";
28524
- const segments = basePath.split("/").filter(Boolean);
28525
- if (filenames.includes(segments.at(-1)) && await options.test(basePath)) {
28526
- return basePath;
28527
- }
28528
- if (leadingSlash) {
28529
- segments[0] = "/" + segments[0];
28530
- }
28531
- let root = segments.findIndex((r) => r.match(options.rootPattern));
28532
- if (root === -1) {
28533
- root = 0;
28534
- }
28535
- if (options.reverse) {
28536
- for (let index = root + 1; index <= segments.length; index++) {
28537
- for (const filename2 of filenames) {
28538
- const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename2);
28539
- if (await options.test(filePath)) {
28540
- return filePath;
28541
- }
28542
- }
28543
- }
28544
- } else {
28545
- for (let index = segments.length; index > root; index--) {
28546
- for (const filename2 of filenames) {
28547
- const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename2);
28548
- if (await options.test(filePath)) {
28549
- return filePath;
28550
- }
28551
- }
28552
- }
28553
- }
28554
- throw new Error(
28555
- `Cannot find matching ${filename} in ${options.startingFrom} or parent directories`
28556
- );
28516
+ const filenames = Array.isArray(filename) ? filename : [filename];
28517
+ const options = {
28518
+ ...defaultFindOptions,
28519
+ ..._options
28520
+ };
28521
+ const basePath = pathe_M_eThtNZ_resolve(options.startingFrom);
28522
+ const leadingSlash = basePath[0] === "/";
28523
+ const segments = basePath.split("/").filter(Boolean);
28524
+ if (filenames.includes(segments.at(-1)) && await options.test(basePath)) return basePath;
28525
+ if (leadingSlash) segments[0] = "/" + segments[0];
28526
+ let root = segments.findIndex((r) => r.match(options.rootPattern));
28527
+ if (root === -1) root = 0;
28528
+ if (options.reverse) for (let index = root + 1; index <= segments.length; index++) for (const filename of filenames) {
28529
+ const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename);
28530
+ if (await options.test(filePath)) return filePath;
28531
+ }
28532
+ else for (let index = segments.length; index > root; index--) for (const filename of filenames) {
28533
+ const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename);
28534
+ if (await options.test(filePath)) return filePath;
28535
+ }
28536
+ throw new Error(`Cannot find matching ${filename} in ${options.startingFrom} or parent directories`);
28557
28537
  }
28558
28538
  function findNearestFile(filename, options = {}) {
28559
- return findFile(filename, options);
28539
+ return findFile(filename, options);
28560
28540
  }
28561
28541
  function findFarthestFile(filename, options = {}) {
28562
- return findFile(filename, { ...options, reverse: true });
28542
+ return findFile(filename, {
28543
+ ...options,
28544
+ reverse: true
28545
+ });
28563
28546
  }
28564
-
28565
28547
  function _resolvePath(id, opts = {}) {
28566
- if (id instanceof URL || id.startsWith("file://")) {
28567
- return normalize((0,external_node_url_.fileURLToPath)(id));
28568
- }
28569
- if (isAbsolute(id)) {
28570
- return normalize(id);
28571
- }
28572
- return resolveModulePath(id, {
28573
- ...opts,
28574
- from: opts.from || opts.parent || opts.url
28575
- });
28548
+ if (id instanceof URL || id.startsWith("file://")) return normalize((0,external_node_url_.fileURLToPath)(id));
28549
+ if (pathe_M_eThtNZ_isAbsolute(id)) return normalize(id);
28550
+ return resolveModulePath(id, {
28551
+ ...opts,
28552
+ from: opts.from || opts.parent || opts.url
28553
+ });
28576
28554
  }
28577
-
28578
28555
  const FileCache$1 = /* @__PURE__ */ (/* unused pure expression or super */ null && (new Map()));
28579
28556
  function defineTSConfig(tsconfig) {
28580
- return tsconfig;
28557
+ return tsconfig;
28581
28558
  }
28582
28559
  async function readTSConfig(id, options = {}) {
28583
- const resolvedPath = await resolveTSConfig(id, options);
28584
- const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache$1;
28585
- if (options.cache && cache.has(resolvedPath)) {
28586
- return cache.get(resolvedPath);
28587
- }
28588
- const text = await promises.readFile(resolvedPath, "utf8");
28589
- const parsed = parseJSONC(text);
28590
- cache.set(resolvedPath, parsed);
28591
- return parsed;
28560
+ const resolvedPath = await resolveTSConfig(id, options);
28561
+ const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache$1;
28562
+ if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
28563
+ const parsed = parseJSONC(await promises.readFile(resolvedPath, "utf8"));
28564
+ cache.set(resolvedPath, parsed);
28565
+ return parsed;
28592
28566
  }
28593
28567
  async function writeTSConfig(path, tsconfig) {
28594
- await promises.writeFile(path, stringifyJSONC(tsconfig));
28568
+ await promises.writeFile(path, stringifyJSONC(tsconfig));
28595
28569
  }
28596
28570
  async function resolveTSConfig(id = process.cwd(), options = {}) {
28597
- return findNearestFile("tsconfig.json", {
28598
- ...options,
28599
- startingFrom: _resolvePath(id, options)
28600
- });
28571
+ return findNearestFile("tsconfig.json", {
28572
+ ...options,
28573
+ startingFrom: _resolvePath(id, options)
28574
+ });
28601
28575
  }
28602
-
28603
28576
  const lockFiles = [
28604
- "yarn.lock",
28605
- "package-lock.json",
28606
- "pnpm-lock.yaml",
28607
- "npm-shrinkwrap.json",
28608
- "bun.lockb",
28609
- "bun.lock",
28610
- "deno.lock"
28577
+ "yarn.lock",
28578
+ "package-lock.json",
28579
+ "pnpm-lock.yaml",
28580
+ "npm-shrinkwrap.json",
28581
+ "bun.lockb",
28582
+ "bun.lock",
28583
+ "deno.lock"
28584
+ ];
28585
+ const packageFiles = [
28586
+ "package.json",
28587
+ "package.json5",
28588
+ "package.yaml"
28611
28589
  ];
28612
- const packageFiles = ["package.json", "package.json5", "package.yaml"];
28613
28590
  const workspaceFiles = [
28614
- "pnpm-workspace.yaml",
28615
- "lerna.json",
28616
- "turbo.json",
28617
- "rush.json",
28618
- "deno.json",
28619
- "deno.jsonc"
28591
+ "pnpm-workspace.yaml",
28592
+ "lerna.json",
28593
+ "turbo.json",
28594
+ "rush.json",
28595
+ "deno.json",
28596
+ "deno.jsonc"
28620
28597
  ];
28621
28598
  const FileCache = /* @__PURE__ */ new Map();
28622
28599
  function definePackageJSON(pkg) {
28623
- return pkg;
28600
+ return pkg;
28624
28601
  }
28625
28602
  async function findPackage(id = process.cwd(), options = {}) {
28626
- return findNearestFile(packageFiles, {
28627
- ...options,
28628
- startingFrom: _resolvePath(id, options)
28629
- });
28603
+ return findNearestFile(packageFiles, {
28604
+ ...options,
28605
+ startingFrom: _resolvePath(id, options)
28606
+ });
28630
28607
  }
28631
28608
  async function readPackage(id, options = {}) {
28632
- const resolvedPath = await findPackage(id, options);
28633
- const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
28634
- if (options.cache && cache.has(resolvedPath)) {
28635
- return cache.get(resolvedPath);
28636
- }
28637
- const blob = await promises.readFile(resolvedPath, "utf8");
28638
- let parsed;
28639
- if (resolvedPath.endsWith(".json5")) {
28640
- parsed = parseJSON5(blob);
28641
- } else if (resolvedPath.endsWith(".yaml")) {
28642
- parsed = parseYAML(blob);
28643
- } else {
28644
- try {
28645
- parsed = parseJSON(blob);
28646
- } catch {
28647
- parsed = parseJSONC(blob);
28648
- }
28649
- }
28650
- cache.set(resolvedPath, parsed);
28651
- return parsed;
28609
+ const resolvedPath = await findPackage(id, options);
28610
+ const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
28611
+ if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
28612
+ const blob = await promises.readFile(resolvedPath, "utf8");
28613
+ let parsed;
28614
+ if (resolvedPath.endsWith(".json5")) parsed = parseJSON5(blob);
28615
+ else if (resolvedPath.endsWith(".yaml")) parsed = parseYAML(blob);
28616
+ else try {
28617
+ parsed = parseJSON(blob);
28618
+ } catch {
28619
+ parsed = parseJSONC(blob);
28620
+ }
28621
+ cache.set(resolvedPath, parsed);
28622
+ return parsed;
28652
28623
  }
28653
28624
  async function writePackage(path, pkg) {
28654
- let content;
28655
- if (path.endsWith(".json5")) {
28656
- content = stringifyJSON5(pkg);
28657
- } else if (path.endsWith(".yaml")) {
28658
- content = stringifyYAML(pkg);
28659
- } else {
28660
- content = stringifyJSON(pkg);
28661
- }
28662
- await promises.writeFile(path, content);
28625
+ let content;
28626
+ if (path.endsWith(".json5")) content = stringifyJSON5(pkg);
28627
+ else if (path.endsWith(".yaml")) content = stringifyYAML(pkg);
28628
+ else content = stringifyJSON(pkg);
28629
+ await promises.writeFile(path, content);
28663
28630
  }
28664
28631
  async function readPackageJSON(id, options = {}) {
28665
- const resolvedPath = await resolvePackageJSON(id, options);
28666
- const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
28667
- if (options.cache && cache.has(resolvedPath)) {
28668
- return cache.get(resolvedPath);
28669
- }
28670
- const blob = await external_node_fs_.promises.readFile(resolvedPath, "utf8");
28671
- let parsed;
28672
- try {
28673
- parsed = json_n(blob);
28674
- } catch {
28675
- parsed = (0,jsonc.parseJSONC)(blob);
28676
- }
28677
- cache.set(resolvedPath, parsed);
28678
- return parsed;
28632
+ const resolvedPath = await resolvePackageJSON(id, options);
28633
+ const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
28634
+ if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
28635
+ const blob = await external_node_fs_.promises.readFile(resolvedPath, "utf8");
28636
+ let parsed;
28637
+ try {
28638
+ parsed = json_n(blob);
28639
+ } catch {
28640
+ parsed = (0,jsonc.parseJSONC)(blob);
28641
+ }
28642
+ cache.set(resolvedPath, parsed);
28643
+ return parsed;
28679
28644
  }
28680
28645
  async function writePackageJSON(path, pkg) {
28681
- await promises.writeFile(path, stringifyJSON(pkg));
28646
+ await promises.writeFile(path, stringifyJSON(pkg));
28682
28647
  }
28683
28648
  async function resolvePackageJSON(id = process.cwd(), options = {}) {
28684
- return findNearestFile("package.json", {
28685
- ...options,
28686
- startingFrom: _resolvePath(id, options)
28687
- });
28649
+ return findNearestFile("package.json", {
28650
+ ...options,
28651
+ startingFrom: _resolvePath(id, options)
28652
+ });
28688
28653
  }
28689
28654
  async function resolveLockfile(id = process.cwd(), options = {}) {
28690
- return findNearestFile(lockFiles, {
28691
- ...options,
28692
- startingFrom: _resolvePath(id, options)
28693
- });
28655
+ return findNearestFile(lockFiles, {
28656
+ ...options,
28657
+ startingFrom: _resolvePath(id, options)
28658
+ });
28694
28659
  }
28695
28660
  const workspaceTests = {
28696
- workspaceFile: (opts) => findFile(workspaceFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
28697
- gitConfig: (opts) => findFile(".git/config", opts).then((r) => pathe_M_eThtNZ_resolve(r, "../..")),
28698
- lockFile: (opts) => findFile(lockFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
28699
- packageJson: (opts) => findFile(packageFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r))
28661
+ workspaceFile: (opts) => findFile(workspaceFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
28662
+ gitConfig: (opts) => findFile(".git/config", opts).then((r) => pathe_M_eThtNZ_resolve(r, "../..")),
28663
+ lockFile: (opts) => findFile(lockFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
28664
+ packageJson: (opts) => findFile(packageFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r))
28700
28665
  };
28701
28666
  async function findWorkspaceDir(id = process.cwd(), options = {}) {
28702
- const startingFrom = _resolvePath(id, options);
28703
- const tests = options.tests || ["workspaceFile", "gitConfig", "lockFile", "packageJson"];
28704
- for (const testName of tests) {
28705
- const test = workspaceTests[testName];
28706
- if (options[testName] === false || !test) {
28707
- continue;
28708
- }
28709
- const direction = options[testName] || (testName === "gitConfig" ? "closest" : "furthest");
28710
- const detected = await test({
28711
- ...options,
28712
- startingFrom,
28713
- reverse: direction === "furthest"
28714
- }).catch(() => {
28715
- });
28716
- if (detected) {
28717
- return detected;
28718
- }
28719
- }
28720
- throw new Error(`Cannot detect workspace root from ${id}`);
28667
+ const startingFrom = _resolvePath(id, options);
28668
+ const tests = options.tests || [
28669
+ "workspaceFile",
28670
+ "gitConfig",
28671
+ "lockFile",
28672
+ "packageJson"
28673
+ ];
28674
+ for (const testName of tests) {
28675
+ const test = workspaceTests[testName];
28676
+ if (options[testName] === false || !test) continue;
28677
+ const direction = options[testName] || (testName === "gitConfig" ? "closest" : "furthest");
28678
+ const detected = await test({
28679
+ ...options,
28680
+ startingFrom,
28681
+ reverse: direction === "furthest"
28682
+ }).catch(() => {});
28683
+ if (detected) return detected;
28684
+ }
28685
+ throw new Error(`Cannot detect workspace root from ${id}`);
28721
28686
  }
28722
28687
  async function updatePackage(id, callback, options = {}) {
28723
- const resolvedPath = await findPackage(id, options);
28724
- const pkg = await readPackage(id, options);
28725
- const proxy = new Proxy(pkg, {
28726
- get(target, prop) {
28727
- if (typeof prop === "string" && objectKeys.has(prop) && !Object.hasOwn(target, prop)) {
28728
- target[prop] = {};
28729
- }
28730
- return Reflect.get(target, prop);
28731
- }
28732
- });
28733
- const updated = await callback(proxy) || pkg;
28734
- await writePackage(resolvedPath, updated);
28688
+ const resolvedPath = await findPackage(id, options);
28689
+ const pkg = await readPackage(id, options);
28690
+ await writePackage(resolvedPath, await callback(new Proxy(pkg, { get(target, prop) {
28691
+ if (typeof prop === "string" && objectKeys.has(prop) && !Object.hasOwn(target, prop)) target[prop] = {};
28692
+ return Reflect.get(target, prop);
28693
+ } })) || pkg);
28735
28694
  }
28736
28695
  function sortPackage(pkg) {
28737
- const sorted = {};
28738
- const originalKeys = Object.keys(pkg);
28739
- const knownKeysPresent = defaultFieldOrder.filter(
28740
- (key) => Object.hasOwn(pkg, key)
28741
- );
28742
- for (const key of originalKeys) {
28743
- const currentIndex = knownKeysPresent.indexOf(key);
28744
- if (currentIndex === -1) {
28745
- sorted[key] = pkg[key];
28746
- continue;
28747
- }
28748
- for (let i = 0; i <= currentIndex; i++) {
28749
- const knownKey = knownKeysPresent[i];
28750
- if (!Object.hasOwn(sorted, knownKey)) {
28751
- sorted[knownKey] = pkg[knownKey];
28752
- }
28753
- }
28754
- }
28755
- for (const key of [...dependencyKeys, "scripts"]) {
28756
- const value = sorted[key];
28757
- if (dist_isObject(value)) {
28758
- sorted[key] = sortObject(value);
28759
- }
28760
- }
28761
- return sorted;
28696
+ const sorted = {};
28697
+ const originalKeys = Object.keys(pkg);
28698
+ const knownKeysPresent = defaultFieldOrder.filter((key) => Object.hasOwn(pkg, key));
28699
+ for (const key of originalKeys) {
28700
+ const currentIndex = knownKeysPresent.indexOf(key);
28701
+ if (currentIndex === -1) {
28702
+ sorted[key] = pkg[key];
28703
+ continue;
28704
+ }
28705
+ for (let i = 0; i <= currentIndex; i++) {
28706
+ const knownKey = knownKeysPresent[i];
28707
+ if (!Object.hasOwn(sorted, knownKey)) sorted[knownKey] = pkg[knownKey];
28708
+ }
28709
+ }
28710
+ for (const key of [...dependencyKeys, "scripts"]) {
28711
+ const value = sorted[key];
28712
+ if (dist_isObject(value)) sorted[key] = sortObject(value);
28713
+ }
28714
+ return sorted;
28762
28715
  }
28763
28716
  function normalizePackage(pkg) {
28764
- const normalized = sortPackage(pkg);
28765
- for (const key of dependencyKeys) {
28766
- if (!Object.hasOwn(normalized, key)) {
28767
- continue;
28768
- }
28769
- const value = normalized[key];
28770
- if (!dist_isObject(value)) {
28771
- delete normalized[key];
28772
- }
28773
- }
28774
- return normalized;
28717
+ const normalized = sortPackage(pkg);
28718
+ for (const key of dependencyKeys) {
28719
+ if (!Object.hasOwn(normalized, key)) continue;
28720
+ const value = normalized[key];
28721
+ if (!dist_isObject(value)) delete normalized[key];
28722
+ }
28723
+ return normalized;
28775
28724
  }
28776
28725
  function dist_isObject(value) {
28777
- return typeof value === "object" && value !== null && !Array.isArray(value);
28726
+ return typeof value === "object" && value !== null && !Array.isArray(value);
28778
28727
  }
28779
28728
  function sortObject(obj) {
28780
- return Object.fromEntries(
28781
- Object.entries(obj).sort(([a], [b]) => a.localeCompare(b))
28782
- );
28729
+ return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)));
28783
28730
  }
28784
28731
  const dependencyKeys = (/* unused pure expression or super */ null && ([
28785
- "dependencies",
28786
- "devDependencies",
28787
- "optionalDependencies",
28788
- "peerDependencies"
28732
+ "dependencies",
28733
+ "devDependencies",
28734
+ "optionalDependencies",
28735
+ "peerDependencies"
28789
28736
  ]));
28790
- const objectKeys = /* @__PURE__ */ (/* unused pure expression or super */ null && (new Set([
28791
- "typesVersions",
28792
- "scripts",
28793
- "resolutions",
28794
- "overrides",
28795
- "dependencies",
28796
- "devDependencies",
28797
- "dependenciesMeta",
28798
- "peerDependencies",
28799
- "peerDependenciesMeta",
28800
- "optionalDependencies",
28801
- "engines",
28802
- "publishConfig"
28803
- ])));
28737
+ const objectKeys = new Set([
28738
+ "typesVersions",
28739
+ "scripts",
28740
+ "resolutions",
28741
+ "overrides",
28742
+ "dependencies",
28743
+ "devDependencies",
28744
+ "dependenciesMeta",
28745
+ "peerDependencies",
28746
+ "peerDependenciesMeta",
28747
+ "optionalDependencies",
28748
+ "engines",
28749
+ "publishConfig"
28750
+ ]);
28804
28751
  const defaultFieldOrder = (/* unused pure expression or super */ null && ([
28805
- "$schema",
28806
- "name",
28807
- "version",
28808
- "private",
28809
- "description",
28810
- "keywords",
28811
- "homepage",
28812
- "bugs",
28813
- "repository",
28814
- "funding",
28815
- "license",
28816
- "author",
28817
- "sideEffects",
28818
- "type",
28819
- "imports",
28820
- "exports",
28821
- "main",
28822
- "module",
28823
- "browser",
28824
- "types",
28825
- "typesVersions",
28826
- "typings",
28827
- "bin",
28828
- "man",
28829
- "files",
28830
- "workspaces",
28831
- "scripts",
28832
- "resolutions",
28833
- "overrides",
28834
- "dependencies",
28835
- "devDependencies",
28836
- "dependenciesMeta",
28837
- "peerDependencies",
28838
- "peerDependenciesMeta",
28839
- "optionalDependencies",
28840
- "bundledDependencies",
28841
- "bundleDependencies",
28842
- "packageManager",
28843
- "engines",
28844
- "publishConfig"
28752
+ "$schema",
28753
+ "name",
28754
+ "version",
28755
+ "private",
28756
+ "description",
28757
+ "keywords",
28758
+ "homepage",
28759
+ "bugs",
28760
+ "repository",
28761
+ "funding",
28762
+ "license",
28763
+ "author",
28764
+ "sideEffects",
28765
+ "type",
28766
+ "imports",
28767
+ "exports",
28768
+ "main",
28769
+ "module",
28770
+ "browser",
28771
+ "types",
28772
+ "typesVersions",
28773
+ "typings",
28774
+ "bin",
28775
+ "man",
28776
+ "files",
28777
+ "workspaces",
28778
+ "scripts",
28779
+ "resolutions",
28780
+ "overrides",
28781
+ "dependencies",
28782
+ "devDependencies",
28783
+ "dependenciesMeta",
28784
+ "peerDependencies",
28785
+ "peerDependenciesMeta",
28786
+ "optionalDependencies",
28787
+ "bundledDependencies",
28788
+ "bundleDependencies",
28789
+ "packageManager",
28790
+ "engines",
28791
+ "publishConfig"
28845
28792
  ]));
28846
-
28847
28793
  function defineGitConfig(config) {
28848
- return config;
28794
+ return config;
28849
28795
  }
28850
28796
  async function resolveGitConfig(dir, opts) {
28851
- return findNearestFile(".git/config", { ...opts, startingFrom: dir });
28797
+ return findNearestFile(".git/config", {
28798
+ ...opts,
28799
+ startingFrom: dir
28800
+ });
28852
28801
  }
28853
28802
  async function readGitConfig(dir, opts) {
28854
- const path = await resolveGitConfig(dir, opts);
28855
- const ini = await readFile(path, "utf8");
28856
- return parseGitConfig(ini);
28803
+ return parseGitConfig(await readFile(await resolveGitConfig(dir, opts), "utf8"));
28857
28804
  }
28858
28805
  async function writeGitConfig(path, config) {
28859
- await writeFile(path, stringifyGitConfig(config));
28806
+ await writeFile(path, stringifyGitConfig(config));
28860
28807
  }
28861
28808
  function parseGitConfig(ini) {
28862
- return parseINI(ini.replaceAll(/^\[(\w+) "(.+)"\]$/gm, "[$1.$2]"));
28809
+ return parseINI(ini.replaceAll(/^\[(\w+) "(.+)"\]$/gm, "[$1.$2]"));
28863
28810
  }
28864
28811
  function stringifyGitConfig(config) {
28865
- return stringifyINI(config).replaceAll(/^\[(\w+)\.(\w+)\]$/gm, '[$1 "$2"]');
28812
+ return stringifyINI(config).replaceAll(/^\[(\w+)\.(\w+)\]$/gm, "[$1 \"$2\"]");
28866
28813
  }
28867
28814
 
28868
28815
 
28869
-
28870
28816
  ;// CONCATENATED MODULE: ../../node_modules/c12/dist/index.mjs
28871
28817
 
28872
28818
 
@@ -29237,7 +29183,7 @@ async function watchConfig(options) {
29237
29183
  options.rcFile && resolve(l.cwd, typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`),
29238
29184
  options.packageJson && resolve(l.cwd, "package.json")
29239
29185
  ]).filter(Boolean))];
29240
- const watch = await __webpack_require__.e(/* import() */ 27).then(__webpack_require__.bind(__webpack_require__, 9774)).then((r) => r.watch || r.default || r);
29186
+ const watch = await __webpack_require__.e(/* import() */ 475).then(__webpack_require__.bind(__webpack_require__, 4710)).then((r) => r.watch || r.default || r);
29241
29187
  const { diff } = await __webpack_require__.e(/* import() */ 164).then(__webpack_require__.bind(__webpack_require__, 263));
29242
29188
  const _fswatcher = watch(watchingFiles, {
29243
29189
  ignoreInitial: true,
@@ -29990,6 +29936,240 @@ function defaultExec(command, args, options) {
29990
29936
  return new OctokitRulesetGateway(octokit);
29991
29937
  }
29992
29938
 
29939
+ // EXTERNAL MODULE: external "node:crypto"
29940
+ var external_node_crypto_ = __webpack_require__(7598);
29941
+ ;// CONCATENATED MODULE: ../core/src/gateways/init-hooks-config-gateway.ts
29942
+
29943
+
29944
+
29945
+
29946
+
29947
+ const CLAUDE_SETTINGS_PATH = (0,external_node_path_.join)(".claude", "settings.json");
29948
+ /**
29949
+ * PreToolUse hooks for Edit and Write tools only.
29950
+ * File paths are NOT passed as shell arguments — Claude Code pipes the hook
29951
+ * JSON (including tool_input.file_path) to the command via stdin.
29952
+ */ const PRE_TOOL_USE_HOOKS = [
29953
+ {
29954
+ matcher: "Edit",
29955
+ hooks: [
29956
+ {
29957
+ type: "command",
29958
+ command: "lousy-agents context"
29959
+ }
29960
+ ]
29961
+ },
29962
+ {
29963
+ matcher: "Write",
29964
+ hooks: [
29965
+ {
29966
+ type: "command",
29967
+ command: "lousy-agents context"
29968
+ }
29969
+ ]
29970
+ }
29971
+ ];
29972
+ const SESSION_START_HOOKS = [
29973
+ {
29974
+ hooks: [
29975
+ {
29976
+ type: "command",
29977
+ command: "lousy-agents context"
29978
+ }
29979
+ ]
29980
+ }
29981
+ ];
29982
+ const STOP_HOOKS = [
29983
+ {
29984
+ hooks: [
29985
+ {
29986
+ type: "command",
29987
+ command: "lousy-agents capture"
29988
+ }
29989
+ ]
29990
+ }
29991
+ ];
29992
+ const SUBAGENT_STOP_HOOKS = [
29993
+ {
29994
+ hooks: [
29995
+ {
29996
+ type: "command",
29997
+ command: "lousy-agents capture"
29998
+ }
29999
+ ]
30000
+ }
30001
+ ];
30002
+ const DANGEROUS_KEYS = new Set([
30003
+ "__proto__",
30004
+ "constructor",
30005
+ "prototype"
30006
+ ]);
30007
+ function hasPrototypePollutionKey(obj, depth = 0) {
30008
+ if (depth > 20) return false;
30009
+ if (obj === null || typeof obj !== "object") return false;
30010
+ for (const key of Object.keys(obj)){
30011
+ if (DANGEROUS_KEYS.has(key)) return true;
30012
+ if (hasPrototypePollutionKey(obj[key], depth + 1)) return true;
30013
+ }
30014
+ return false;
30015
+ }
30016
+ function safeJoin(rootDir, relativePath) {
30017
+ const resolved = resolve(rootDir, relativePath);
30018
+ const root = resolve(rootDir);
30019
+ if (resolved !== root) {
30020
+ const rel = relative(root, resolved);
30021
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
30022
+ throw new Error(`Resolved path is outside target directory: ${relativePath}`);
30023
+ }
30024
+ }
30025
+ return resolved;
30026
+ }
30027
+ function getExistingMatchers(hooks, event) {
30028
+ const entries = hooks[event];
30029
+ if (!Array.isArray(entries)) return new Set();
30030
+ return new Set(entries.filter((e)=>e !== null && typeof e === "object").map((e)=>e.matcher).filter((m)=>typeof m === "string"));
30031
+ }
30032
+ class InitHooksConfigGateway {
30033
+ async initHooks(rootDir, config) {
30034
+ const written = [];
30035
+ const skipped = [];
30036
+ const realRootDir = await realpath(rootDir);
30037
+ const settingsPath = safeJoin(realRootDir, CLAUDE_SETTINGS_PATH);
30038
+ const claudeDir = join(realRootDir, ".claude");
30039
+ // Reject symlinks on .claude/settings.json and all ancestor segments
30040
+ await assertPathHasNoSymbolicLinks(realRootDir, settingsPath);
30041
+ let existing = {};
30042
+ try {
30043
+ const raw = await readFileNoFollow(settingsPath, 1_048_576);
30044
+ const parsed = JSON.parse(raw);
30045
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
30046
+ if (hasPrototypePollutionKey(parsed)) {
30047
+ throw new Error("Settings file contains dangerous prototype keys");
30048
+ }
30049
+ existing = parsed;
30050
+ }
30051
+ } catch (error) {
30052
+ if (error instanceof Error && "code" in error) {
30053
+ const code = error.code;
30054
+ if (code === "ENOENT" || code === "ENOTDIR") {
30055
+ existing = {};
30056
+ } else {
30057
+ throw error;
30058
+ }
30059
+ } else if (error instanceof SyntaxError || error instanceof Error && error.message === "Settings file contains dangerous prototype keys") {
30060
+ throw error;
30061
+ } else if (error instanceof Error) {
30062
+ throw error;
30063
+ }
30064
+ }
30065
+ const rawHooks = existing.hooks;
30066
+ const existingHooks = rawHooks !== null && typeof rawHooks === "object" && !Array.isArray(rawHooks) ? rawHooks : {};
30067
+ const existingPreToolUseMatchers = getExistingMatchers(existingHooks, "PreToolUse");
30068
+ const alreadyHasEditHook = existingPreToolUseMatchers.has("Edit") && !config.force;
30069
+ const alreadyHasWriteHook = existingPreToolUseMatchers.has("Write") && !config.force;
30070
+ const alreadyHasStop = Array.isArray(existingHooks.Stop) && !config.force;
30071
+ const alreadyHasSubagentStop = Array.isArray(existingHooks.SubagentStop) && !config.force;
30072
+ const alreadyHasSessionStart = config.addSessionStart && Array.isArray(existingHooks.SessionStart) && !config.force;
30073
+ const allAlreadyPresent = alreadyHasEditHook && alreadyHasWriteHook && alreadyHasStop && alreadyHasSubagentStop && (!config.addSessionStart || alreadyHasSessionStart);
30074
+ if (allAlreadyPresent) {
30075
+ skipped.push(settingsPath);
30076
+ return {
30077
+ written,
30078
+ skipped
30079
+ };
30080
+ }
30081
+ const updatedHooks = {
30082
+ ...existingHooks
30083
+ };
30084
+ const missingPreToolUseHooks = PRE_TOOL_USE_HOOKS.filter((h)=>!(h.matcher === "Edit" && alreadyHasEditHook) && !(h.matcher === "Write" && alreadyHasWriteHook));
30085
+ if (missingPreToolUseHooks.length > 0) {
30086
+ // In --force mode, remove any existing Edit/Write matchers before
30087
+ // appending the new ones so we never produce duplicate entries.
30088
+ const existing_ = Array.isArray(existingHooks.PreToolUse) ? config.force ? existingHooks.PreToolUse.filter((e)=>{
30089
+ if (e === null || typeof e !== "object" || Array.isArray(e)) {
30090
+ return true;
30091
+ }
30092
+ const m = e.matcher;
30093
+ return m !== "Edit" && m !== "Write";
30094
+ }) : existingHooks.PreToolUse : [];
30095
+ updatedHooks.PreToolUse = [
30096
+ ...existing_,
30097
+ ...missingPreToolUseHooks
30098
+ ];
30099
+ }
30100
+ // Stop/SubagentStop: written if not already configured with a valid
30101
+ // array. Use --force to replace them.
30102
+ if (!alreadyHasStop) {
30103
+ updatedHooks.Stop = STOP_HOOKS;
30104
+ }
30105
+ if (!alreadyHasSubagentStop) {
30106
+ updatedHooks.SubagentStop = SUBAGENT_STOP_HOOKS;
30107
+ }
30108
+ if (config.addSessionStart && !alreadyHasSessionStart) {
30109
+ updatedHooks.SessionStart = SESSION_START_HOOKS;
30110
+ }
30111
+ const updatedSettings = {
30112
+ ...existing,
30113
+ hooks: updatedHooks
30114
+ };
30115
+ const content = `${JSON.stringify(updatedSettings, null, 2)}\n`;
30116
+ await mkdir(claudeDir, {
30117
+ recursive: true
30118
+ });
30119
+ // Re-check after mkdir: a race between the initial check and directory
30120
+ // creation could allow an attacker to replace .claude/ with a symlink.
30121
+ // By the time mkdir returns, the directory exists; if .claude (or any
30122
+ // ancestor) is now a symlink the walk will reach it and throw.
30123
+ await assertPathHasNoSymbolicLinks(realRootDir, settingsPath);
30124
+ // Use a random suffix so the temp path is unpredictable, combined with
30125
+ // O_EXCL so the open fails rather than truncating a pre-existing file.
30126
+ // Together these defeat hardlink pre-creation attacks: an attacker cannot
30127
+ // predict the path to hardlink, and even if they did O_EXCL would reject it.
30128
+ const tmpPath = `${settingsPath}.${randomBytes(8).toString("hex")}.tmp`;
30129
+ // O_NOFOLLOW prevents following a symlink that races between open and write.
30130
+ // O_EXCL guarantees the file is newly created (no truncate of an existing target).
30131
+ const hasNoFollow = typeof constants.O_NOFOLLOW === "number" && constants.O_NOFOLLOW !== 0;
30132
+ const openFlags = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (hasNoFollow ? constants.O_NOFOLLOW : 0);
30133
+ let tmpFileHandle;
30134
+ try {
30135
+ tmpFileHandle = await open(tmpPath, openFlags);
30136
+ } catch (error) {
30137
+ if (error instanceof Error && "code" in error) {
30138
+ if (error.code === "ELOOP") {
30139
+ throw new Error(`Symlinks are not allowed for temp path: ${JSON.stringify(tmpPath)}`);
30140
+ }
30141
+ if (error.code === "EEXIST") {
30142
+ // With 8 random bytes (2^64 possibilities) this is astronomically
30143
+ // rare; if it happens it likely indicates a targeted attack.
30144
+ throw new Error(`Temp file already exists (possible collision or attack): ${JSON.stringify(tmpPath)}`);
30145
+ }
30146
+ }
30147
+ throw error;
30148
+ }
30149
+ try {
30150
+ await tmpFileHandle.writeFile(content, "utf8");
30151
+ } finally{
30152
+ await tmpFileHandle.close();
30153
+ }
30154
+ try {
30155
+ await rename(tmpPath, settingsPath);
30156
+ } catch (error) {
30157
+ // Best-effort cleanup: remove the random temp file so it does not
30158
+ // accumulate on repeated failures (e.g. settingsPath unwritable).
30159
+ await unlink(tmpPath).catch(()=>{});
30160
+ throw error;
30161
+ }
30162
+ written.push(settingsPath);
30163
+ return {
30164
+ written,
30165
+ skipped
30166
+ };
30167
+ }
30168
+ }
30169
+ function createInitHooksConfigGateway() {
30170
+ return new InitHooksConfigGateway();
30171
+ }
30172
+
29993
30173
  ;// CONCATENATED MODULE: ../core/src/gateways/instruction-analysis-gateway.ts
29994
30174
  /**
29995
30175
  * Gateway for analyzing repository instructions for feedback loop coverage
@@ -30094,6 +30274,258 @@ function defaultExec(command, args, options) {
30094
30274
  return new FileSystemInstructionAnalysisGateway();
30095
30275
  }
30096
30276
 
30277
+ // EXTERNAL MODULE: ../../node_modules/yaml/dist/index.js
30278
+ var yaml_dist = __webpack_require__(3519);
30279
+ ;// CONCATENATED MODULE: ../core/src/lib/frontmatter.ts
30280
+ /**
30281
+ * Shared YAML frontmatter parser for markdown files.
30282
+ * Extracts YAML data between leading `---` delimiters.
30283
+ */
30284
+ /**
30285
+ * Parses YAML frontmatter and returns a tagged result:
30286
+ * - `{ ok: true, data }` on success
30287
+ * - `{ ok: false, reason: 'missing' }` when no frontmatter delimiters found
30288
+ * - `{ ok: false, reason: 'invalid', detail }` when YAML is malformed (with error detail)
30289
+ */ function frontmatter_parseFrontmatterWithError(content) {
30290
+ const lines = content.split("\n");
30291
+ if (lines[0]?.trim() !== "---") {
30292
+ return {
30293
+ ok: false,
30294
+ reason: "missing"
30295
+ };
30296
+ }
30297
+ let endIndex = -1;
30298
+ for(let i = 1; i < lines.length; i++){
30299
+ if (lines[i]?.trim() === "---") {
30300
+ endIndex = i;
30301
+ break;
30302
+ }
30303
+ }
30304
+ if (endIndex === -1) {
30305
+ return {
30306
+ ok: false,
30307
+ reason: "missing"
30308
+ };
30309
+ }
30310
+ const yamlContent = lines.slice(1, endIndex).join("\n");
30311
+ let data;
30312
+ try {
30313
+ const parsed = parseYaml(yamlContent, {
30314
+ maxAliasCount: 0
30315
+ });
30316
+ data = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
30317
+ } catch (error) {
30318
+ const detail = error instanceof Error ? error.message : "Unknown YAML parse error";
30319
+ return {
30320
+ ok: false,
30321
+ reason: "invalid",
30322
+ detail
30323
+ };
30324
+ }
30325
+ const fieldLines = new Map();
30326
+ for(let i = 1; i < endIndex; i++){
30327
+ const match = lines[i]?.match(/^([^\s:][^:]*?):(?:\s|$)/);
30328
+ if (match?.[1]) {
30329
+ fieldLines.set(match[1], i + 1);
30330
+ }
30331
+ }
30332
+ return {
30333
+ ok: true,
30334
+ data: {
30335
+ data: data ?? {},
30336
+ fieldLines,
30337
+ frontmatterStartLine: 1
30338
+ }
30339
+ };
30340
+ }
30341
+ /**
30342
+ * Parses YAML frontmatter from markdown content.
30343
+ *
30344
+ * Returns `null` when the content has no opening `---`, no closing `---`,
30345
+ * or contains invalid YAML.
30346
+ */ function frontmatter_parseFrontmatter(content) {
30347
+ const result = frontmatter_parseFrontmatterWithError(content);
30348
+ return result.ok ? result.data : null;
30349
+ }
30350
+
30351
+ ;// CONCATENATED MODULE: ../core/src/use-cases/lesson-schema.ts
30352
+
30353
+ const SAFE_SLUG = /^[a-z0-9-]+$/;
30354
+ const MAX_TITLE_LENGTH = 200;
30355
+ const MAX_PATTERN_LENGTH = 200;
30356
+ const MAX_PATTERNS = 50;
30357
+ const MAX_TRIGGER_VALUES = 100;
30358
+ const MAX_TRIGGER_VALUE_LENGTH = 200;
30359
+ const lesson_schema_LessonFrontmatterSchema = schemas_object({
30360
+ slug: schemas_string().regex(SAFE_SLUG, "slug must match ^[a-z0-9-]+$"),
30361
+ title: schemas_string().min(1).max(MAX_TITLE_LENGTH),
30362
+ type: schemas_enum([
30363
+ "invariant",
30364
+ "pattern"
30365
+ ]),
30366
+ created: schemas_string().regex(/^\d{4}-\d{2}-\d{2}$/, "created must be YYYY-MM-DD"),
30367
+ revised: schemas_string().regex(/^\d{4}-\d{2}-\d{2}$/, "revised must be YYYY-MM-DD"),
30368
+ provenance: schemas_array(schemas_object({
30369
+ pr: schemas_number().int(),
30370
+ // biome-ignore lint/style/useNamingConvention: YAML frontmatter key uses snake_case
30371
+ finding_id: schemas_string(),
30372
+ facet: schemas_string()
30373
+ }).strict()),
30374
+ triggers: schemas_object({
30375
+ paths: schemas_array(schemas_string().min(1).max(MAX_TRIGGER_VALUE_LENGTH)).max(MAX_TRIGGER_VALUES),
30376
+ tags: schemas_array(schemas_string().min(1).max(MAX_TRIGGER_VALUE_LENGTH)).max(MAX_TRIGGER_VALUES),
30377
+ patterns: schemas_array(schemas_string().min(1).max(MAX_PATTERN_LENGTH)).max(MAX_PATTERNS)
30378
+ }).strict()
30379
+ }).strict().refine((data)=>data.revised >= data.created, {
30380
+ message: "revised must be on or after created (lexicographic ISO date compare)",
30381
+ path: [
30382
+ "revised"
30383
+ ]
30384
+ });
30385
+
30386
+ ;// CONCATENATED MODULE: ../core/src/gateways/lesson-file-gateway.ts
30387
+ /**
30388
+ * Gateway for reading lesson files from .lousy-agents/lessons/.
30389
+ */
30390
+
30391
+
30392
+
30393
+
30394
+ const MAX_LESSON_FILE_BYTES = 1_048_576; // 1 MB
30395
+ const MAX_LESSON_FILES = 500;
30396
+ const MAX_AGGREGATE_BYTES = (/* unused pure expression or super */ null && (20 * 1024 * 1024)); // 20 MB
30397
+ const LESSONS_RELATIVE_PATH = (0,external_node_path_.join)(".lousy-agents", "lessons");
30398
+ /**
30399
+ * Extracts the markdown body from lesson file content (text after second `---`).
30400
+ */ function extractBody(content) {
30401
+ const lines = content.split("\n");
30402
+ if (lines[0]?.trim() !== "---") {
30403
+ return content;
30404
+ }
30405
+ let endIndex = -1;
30406
+ for(let i = 1; i < lines.length; i++){
30407
+ if (lines[i]?.trim() === "---") {
30408
+ endIndex = i;
30409
+ break;
30410
+ }
30411
+ }
30412
+ if (endIndex === -1) {
30413
+ return "";
30414
+ }
30415
+ const bodyLines = lines.slice(endIndex + 1);
30416
+ if (bodyLines[0] === "") {
30417
+ return bodyLines.slice(1).join("\n");
30418
+ }
30419
+ return bodyLines.join("\n");
30420
+ }
30421
+ class LessonFileGateway {
30422
+ async readLessons(rootDir) {
30423
+ const realRootDir = await realpath(rootDir);
30424
+ const lessonsDir = join(realRootDir, LESSONS_RELATIVE_PATH);
30425
+ await assertPathHasNoSymbolicLinks(realRootDir, lessonsDir);
30426
+ let dirStat;
30427
+ try {
30428
+ dirStat = await lstat(lessonsDir);
30429
+ } catch (error) {
30430
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
30431
+ return {
30432
+ lessons: [],
30433
+ errors: []
30434
+ };
30435
+ }
30436
+ throw error;
30437
+ }
30438
+ if (!dirStat.isDirectory()) {
30439
+ throw new Error(`Lessons path exists but is not a directory: ${lessonsDir}`);
30440
+ }
30441
+ let entries;
30442
+ try {
30443
+ entries = await readdir(lessonsDir, {
30444
+ withFileTypes: true
30445
+ });
30446
+ } catch (error) {
30447
+ const reason = error instanceof Error ? error.message : String(error);
30448
+ const wrapped = new Error(`Cannot read lessons directory ${lessonsDir}: ${reason}`);
30449
+ // Preserve the OS error code so callers can distinguish EACCES
30450
+ // (permission denied) from other failures without parsing the message.
30451
+ if (error instanceof Error && "code" in error) {
30452
+ wrapped.code = error.code;
30453
+ }
30454
+ throw wrapped;
30455
+ }
30456
+ const mdFiles = entries.filter((e)=>e.isFile() && e.name.endsWith(".md")).map((e)=>join(lessonsDir, e.name)).sort();
30457
+ if (mdFiles.length > MAX_LESSON_FILES) {
30458
+ throw new Error(`Lesson file count exceeds limit: ${mdFiles.length} files found (max ${MAX_LESSON_FILES})`);
30459
+ }
30460
+ const lessons = [];
30461
+ const errors = [];
30462
+ let aggregateBytes = 0;
30463
+ for (const filePath of mdFiles){
30464
+ let content;
30465
+ try {
30466
+ content = await readFileNoFollow(filePath, MAX_LESSON_FILE_BYTES);
30467
+ } catch (error) {
30468
+ const reason = error instanceof Error ? error.message : String(error);
30469
+ errors.push({
30470
+ filePath,
30471
+ reason
30472
+ });
30473
+ continue;
30474
+ }
30475
+ const byteLength = Buffer.byteLength(content, "utf-8");
30476
+ aggregateBytes += byteLength;
30477
+ if (aggregateBytes > MAX_AGGREGATE_BYTES) {
30478
+ throw new Error(`Aggregate lesson bytes exceed limit: ${aggregateBytes} bytes > ${MAX_AGGREGATE_BYTES} bytes`);
30479
+ }
30480
+ const parseResult = parseFrontmatterWithError(content);
30481
+ if (!parseResult.ok) {
30482
+ const reason = parseResult.reason === "invalid" ? `Invalid YAML frontmatter: ${parseResult.detail}` : "Missing YAML frontmatter";
30483
+ errors.push({
30484
+ filePath,
30485
+ reason
30486
+ });
30487
+ continue;
30488
+ }
30489
+ const schemaResult = LessonFrontmatterSchema.safeParse(parseResult.data.data);
30490
+ if (!schemaResult.success) {
30491
+ const reason = schemaResult.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ");
30492
+ errors.push({
30493
+ filePath,
30494
+ reason
30495
+ });
30496
+ continue;
30497
+ }
30498
+ const fm = schemaResult.data;
30499
+ const body = extractBody(content);
30500
+ const lesson = {
30501
+ slug: fm.slug,
30502
+ title: fm.title,
30503
+ type: fm.type,
30504
+ created: fm.created,
30505
+ revised: fm.revised,
30506
+ provenance: fm.provenance,
30507
+ triggers: {
30508
+ paths: fm.triggers.paths,
30509
+ tags: fm.triggers.tags,
30510
+ patterns: fm.triggers.patterns
30511
+ },
30512
+ body
30513
+ };
30514
+ lessons.push({
30515
+ lesson,
30516
+ filePath
30517
+ });
30518
+ }
30519
+ return {
30520
+ lessons,
30521
+ errors
30522
+ };
30523
+ }
30524
+ }
30525
+ function createLessonFileGateway() {
30526
+ return new LessonFileGateway();
30527
+ }
30528
+
30097
30529
  ;// CONCATENATED MODULE: ../../node_modules/consola/dist/core.mjs
30098
30530
  const LogLevels = {
30099
30531
  silent: Number.NEGATIVE_INFINITY,
@@ -31902,58 +32334,6 @@ const PackageJsonSchema = schemas_object({
31902
32334
  return new FileSystemSkillFileGateway();
31903
32335
  }
31904
32336
 
31905
- // EXTERNAL MODULE: ../../node_modules/yaml/dist/index.js
31906
- var yaml_dist = __webpack_require__(3519);
31907
- ;// CONCATENATED MODULE: ../core/src/lib/frontmatter.ts
31908
- /**
31909
- * Shared YAML frontmatter parser for markdown files.
31910
- * Extracts YAML data between leading `---` delimiters.
31911
- */
31912
- /**
31913
- * Parses YAML frontmatter from markdown content.
31914
- *
31915
- * Returns `null` when the content has no opening `---`, no closing `---`,
31916
- * or contains invalid YAML.
31917
- */ function frontmatter_parseFrontmatter(content) {
31918
- const lines = content.split("\n");
31919
- if (lines[0]?.trim() !== "---") {
31920
- return null;
31921
- }
31922
- let endIndex = -1;
31923
- for(let i = 1; i < lines.length; i++){
31924
- if (lines[i]?.trim() === "---") {
31925
- endIndex = i;
31926
- break;
31927
- }
31928
- }
31929
- if (endIndex === -1) {
31930
- return null;
31931
- }
31932
- const yamlContent = lines.slice(1, endIndex).join("\n");
31933
- let data;
31934
- try {
31935
- const parsed = parseYaml(yamlContent, {
31936
- maxAliasCount: 0
31937
- });
31938
- data = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
31939
- } catch {
31940
- return null;
31941
- }
31942
- const fieldLines = new Map();
31943
- for(let i = 1; i < endIndex; i++){
31944
- // Match YAML top-level field names: non-whitespace start, any chars except colon, then colon followed by whitespace or end-of-line
31945
- const match = lines[i]?.match(/^([^\s:][^:]*?):(?:\s|$)/);
31946
- if (match?.[1]) {
31947
- fieldLines.set(match[1], i + 1);
31948
- }
31949
- }
31950
- return {
31951
- data: data ?? {},
31952
- fieldLines,
31953
- frontmatterStartLine: 1
31954
- };
31955
- }
31956
-
31957
32337
  ;// CONCATENATED MODULE: ../core/src/gateways/skill-lint-gateway.ts
31958
32338
  /**
31959
32339
  * Gateway for skill lint file system operations.
@@ -32483,6 +32863,8 @@ function createWorkflowGateway(cwd) {
32483
32863
 
32484
32864
 
32485
32865
 
32866
+
32867
+
32486
32868
  ;// CONCATENATED MODULE: ./src/tools/types.ts
32487
32869
  /**
32488
32870
  * Shared types and utilities for MCP tool handlers.
@@ -48922,7 +49304,7 @@ function default_ok() {}
48922
49304
 
48923
49305
  function unreachable() {}
48924
49306
 
48925
- ;// CONCATENATED MODULE: ../../node_modules/unified/node_modules/is-plain-obj/index.js
49307
+ ;// CONCATENATED MODULE: ../../node_modules/is-plain-obj/index.js
48926
49308
  function is_plain_obj_isPlainObject(value) {
48927
49309
  if (typeof value !== 'object' || value === null) {
48928
49310
  return false;
@@ -51684,7 +52066,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
51684
52066
 
51685
52067
  /** Maximum number of raw heading pattern entries accepted before deduplication. */ const MAX_RAW_HEADING_PATTERNS = 1000;
51686
52068
  /** Maximum number of heading patterns accepted in a single execute() call. */ const MAX_HEADING_PATTERNS = 50;
51687
- /** Maximum character length for a single heading pattern. */ const MAX_PATTERN_LENGTH = 200;
52069
+ /** Maximum character length for a single heading pattern. */ const analyze_instruction_quality_MAX_PATTERN_LENGTH = 200;
51688
52070
  /**
51689
52071
  * Lowercase-keyed lookup built once from HEADING_PATTERN_DESCRIPTIONS.
51690
52072
  * Enables description lookup regardless of the casing callers supply for patterns.
@@ -51696,7 +52078,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
51696
52078
  * Input for the analyze instruction quality use case.
51697
52079
  */ const AnalyzeInstructionQualityInputSchema = schemas_object({
51698
52080
  targetDir: schemas_string().min(1, "Target directory is required"),
51699
- headingPatterns: schemas_array(schemas_string().max(MAX_PATTERN_LENGTH * 2)).max(MAX_RAW_HEADING_PATTERNS).optional(),
52081
+ headingPatterns: schemas_array(schemas_string().max(analyze_instruction_quality_MAX_PATTERN_LENGTH * 2)).max(MAX_RAW_HEADING_PATTERNS).optional(),
51700
52082
  proximityWindow: schemas_number().int().positive().optional()
51701
52083
  });
51702
52084
  /**
@@ -51796,8 +52178,8 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
51796
52178
  if (trimmed.length === 0) {
51797
52179
  throw new Error("headingPatterns must not contain empty or whitespace-only entries");
51798
52180
  }
51799
- if (trimmed.length > MAX_PATTERN_LENGTH) {
51800
- throw new Error(`headingPatterns entries must not exceed ${MAX_PATTERN_LENGTH} characters`);
52181
+ if (trimmed.length > analyze_instruction_quality_MAX_PATTERN_LENGTH) {
52182
+ throw new Error(`headingPatterns entries must not exceed ${analyze_instruction_quality_MAX_PATTERN_LENGTH} characters`);
51801
52183
  }
51802
52184
  const lower = trimmed.toLowerCase();
51803
52185
  if (!seenLower.has(lower)) {
@@ -63814,4 +64196,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
63814
64196
  // module factories are used so entry inlining is disabled
63815
64197
  // startup
63816
64198
  // Load entry module and return exports
63817
- var __webpack_exports__ = __webpack_require__(832);
64199
+ var __webpack_exports__ = __webpack_require__(8050);