codeql-development-mcp-server 2.24.3-rc1 → 2.24.3-rc2

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.
@@ -2991,7 +2991,7 @@ var require_compile = __commonJS({
2991
2991
  const schOrFunc = root.refs[ref];
2992
2992
  if (schOrFunc)
2993
2993
  return schOrFunc;
2994
- let _sch = resolve13.call(this, root, ref);
2994
+ let _sch = resolve14.call(this, root, ref);
2995
2995
  if (_sch === void 0) {
2996
2996
  const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
2997
2997
  const { schemaId } = this.opts;
@@ -3018,7 +3018,7 @@ var require_compile = __commonJS({
3018
3018
  function sameSchemaEnv(s1, s2) {
3019
3019
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3020
3020
  }
3021
- function resolve13(root, ref) {
3021
+ function resolve14(root, ref) {
3022
3022
  let sch;
3023
3023
  while (typeof (sch = this.refs[ref]) == "string")
3024
3024
  ref = sch;
@@ -3593,7 +3593,7 @@ var require_fast_uri = __commonJS({
3593
3593
  }
3594
3594
  return uri;
3595
3595
  }
3596
- function resolve13(baseURI, relativeURI, options) {
3596
+ function resolve14(baseURI, relativeURI, options) {
3597
3597
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3598
3598
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
3599
3599
  schemelessOptions.skipEscape = true;
@@ -3820,7 +3820,7 @@ var require_fast_uri = __commonJS({
3820
3820
  var fastUri = {
3821
3821
  SCHEMES,
3822
3822
  normalize,
3823
- resolve: resolve13,
3823
+ resolve: resolve14,
3824
3824
  resolveComponent,
3825
3825
  equal,
3826
3826
  serialize,
@@ -9611,7 +9611,7 @@ var require_compile2 = __commonJS({
9611
9611
  const schOrFunc = root.refs[ref];
9612
9612
  if (schOrFunc)
9613
9613
  return schOrFunc;
9614
- let _sch = resolve13.call(this, root, ref);
9614
+ let _sch = resolve14.call(this, root, ref);
9615
9615
  if (_sch === void 0) {
9616
9616
  const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
9617
9617
  const { schemaId } = this.opts;
@@ -9638,7 +9638,7 @@ var require_compile2 = __commonJS({
9638
9638
  function sameSchemaEnv(s1, s2) {
9639
9639
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
9640
9640
  }
9641
- function resolve13(root, ref) {
9641
+ function resolve14(root, ref) {
9642
9642
  let sch;
9643
9643
  while (typeof (sch = this.refs[ref]) == "string")
9644
9644
  ref = sch;
@@ -12713,8 +12713,8 @@ var require_common = __commonJS({
12713
12713
  }
12714
12714
  return debug;
12715
12715
  }
12716
- function extend4(namespace, delimiter5) {
12717
- const newDebug = createDebug(this.namespace + (typeof delimiter5 === "undefined" ? ":" : delimiter5) + namespace);
12716
+ function extend4(namespace, delimiter6) {
12717
+ const newDebug = createDebug(this.namespace + (typeof delimiter6 === "undefined" ? ":" : delimiter6) + namespace);
12718
12718
  newDebug.log = this.log;
12719
12719
  return newDebug;
12720
12720
  }
@@ -17919,10 +17919,10 @@ var require_raw_body = __commonJS({
17919
17919
  if (done) {
17920
17920
  return readStream(stream, encoding, length, limit, wrap(done));
17921
17921
  }
17922
- return new Promise(function executor(resolve13, reject) {
17922
+ return new Promise(function executor(resolve14, reject) {
17923
17923
  readStream(stream, encoding, length, limit, function onRead(err, buf) {
17924
17924
  if (err) return reject(err);
17925
- resolve13(buf);
17925
+ resolve14(buf);
17926
17926
  });
17927
17927
  });
17928
17928
  }
@@ -27724,7 +27724,7 @@ var require_mime_types = __commonJS({
27724
27724
  "../node_modules/mime-types/index.js"(exports) {
27725
27725
  "use strict";
27726
27726
  var db = require_mime_db();
27727
- var extname2 = __require("path").extname;
27727
+ var extname3 = __require("path").extname;
27728
27728
  var mimeScore = require_mimeScore();
27729
27729
  var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
27730
27730
  var TEXT_TYPE_REGEXP = /^text\//i;
@@ -27780,7 +27780,7 @@ var require_mime_types = __commonJS({
27780
27780
  if (!path4 || typeof path4 !== "string") {
27781
27781
  return false;
27782
27782
  }
27783
- var extension2 = extname2("x." + path4).toLowerCase().slice(1);
27783
+ var extension2 = extname3("x." + path4).toLowerCase().slice(1);
27784
27784
  if (!extension2) {
27785
27785
  return false;
27786
27786
  }
@@ -31255,15 +31255,15 @@ var require_view = __commonJS({
31255
31255
  var path4 = __require("node:path");
31256
31256
  var fs3 = __require("node:fs");
31257
31257
  var dirname8 = path4.dirname;
31258
- var basename7 = path4.basename;
31259
- var extname2 = path4.extname;
31260
- var join18 = path4.join;
31261
- var resolve13 = path4.resolve;
31258
+ var basename8 = path4.basename;
31259
+ var extname3 = path4.extname;
31260
+ var join19 = path4.join;
31261
+ var resolve14 = path4.resolve;
31262
31262
  module.exports = View;
31263
31263
  function View(name, options) {
31264
31264
  var opts = options || {};
31265
31265
  this.defaultEngine = opts.defaultEngine;
31266
- this.ext = extname2(name);
31266
+ this.ext = extname3(name);
31267
31267
  this.name = name;
31268
31268
  this.root = opts.root;
31269
31269
  if (!this.ext && !this.defaultEngine) {
@@ -31292,9 +31292,9 @@ var require_view = __commonJS({
31292
31292
  debug('lookup "%s"', name);
31293
31293
  for (var i = 0; i < roots.length && !path5; i++) {
31294
31294
  var root = roots[i];
31295
- var loc = resolve13(root, name);
31295
+ var loc = resolve14(root, name);
31296
31296
  var dir = dirname8(loc);
31297
- var file = basename7(loc);
31297
+ var file = basename8(loc);
31298
31298
  path5 = this.resolve(dir, file);
31299
31299
  }
31300
31300
  return path5;
@@ -31317,14 +31317,14 @@ var require_view = __commonJS({
31317
31317
  });
31318
31318
  sync = false;
31319
31319
  };
31320
- View.prototype.resolve = function resolve14(dir, file) {
31320
+ View.prototype.resolve = function resolve15(dir, file) {
31321
31321
  var ext = this.ext;
31322
- var path5 = join18(dir, file);
31322
+ var path5 = join19(dir, file);
31323
31323
  var stat = tryStat(path5);
31324
31324
  if (stat && stat.isFile()) {
31325
31325
  return path5;
31326
31326
  }
31327
- path5 = join18(dir, basename7(file, ext), "index" + ext);
31327
+ path5 = join19(dir, basename8(file, ext), "index" + ext);
31328
31328
  stat = tryStat(path5);
31329
31329
  if (stat && stat.isFile()) {
31330
31330
  return path5;
@@ -32564,9 +32564,9 @@ var require_dist2 = __commonJS({
32564
32564
  return new TokenData(consumeUntil("end"), str2);
32565
32565
  }
32566
32566
  function compile(path4, options = {}) {
32567
- const { encode = encodeURIComponent, delimiter: delimiter5 = DEFAULT_DELIMITER } = options;
32567
+ const { encode = encodeURIComponent, delimiter: delimiter6 = DEFAULT_DELIMITER } = options;
32568
32568
  const data = typeof path4 === "object" ? path4 : parse4(path4, options);
32569
- const fn = tokensToFunction(data.tokens, delimiter5, encode);
32569
+ const fn = tokensToFunction(data.tokens, delimiter6, encode);
32570
32570
  return function path5(params = {}) {
32571
32571
  const [path6, ...missing] = fn(params);
32572
32572
  if (missing.length) {
@@ -32575,8 +32575,8 @@ var require_dist2 = __commonJS({
32575
32575
  return path6;
32576
32576
  };
32577
32577
  }
32578
- function tokensToFunction(tokens, delimiter5, encode) {
32579
- const encoders = tokens.map((token) => tokenToFunction(token, delimiter5, encode));
32578
+ function tokensToFunction(tokens, delimiter6, encode) {
32579
+ const encoders = tokens.map((token) => tokenToFunction(token, delimiter6, encode));
32580
32580
  return (data) => {
32581
32581
  const result = [""];
32582
32582
  for (const encoder of encoders) {
@@ -32587,11 +32587,11 @@ var require_dist2 = __commonJS({
32587
32587
  return result;
32588
32588
  };
32589
32589
  }
32590
- function tokenToFunction(token, delimiter5, encode) {
32590
+ function tokenToFunction(token, delimiter6, encode) {
32591
32591
  if (token.type === "text")
32592
32592
  return () => [token.value];
32593
32593
  if (token.type === "group") {
32594
- const fn = tokensToFunction(token.tokens, delimiter5, encode);
32594
+ const fn = tokensToFunction(token.tokens, delimiter6, encode);
32595
32595
  return (data) => {
32596
32596
  const [value, ...missing] = fn(data);
32597
32597
  if (!missing.length)
@@ -32614,7 +32614,7 @@ var require_dist2 = __commonJS({
32614
32614
  throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
32615
32615
  }
32616
32616
  return encodeValue(value2);
32617
- }).join(delimiter5)
32617
+ }).join(delimiter6)
32618
32618
  ];
32619
32619
  };
32620
32620
  }
@@ -32629,14 +32629,14 @@ var require_dist2 = __commonJS({
32629
32629
  };
32630
32630
  }
32631
32631
  function match(path4, options = {}) {
32632
- const { decode = decodeURIComponent, delimiter: delimiter5 = DEFAULT_DELIMITER } = options;
32632
+ const { decode = decodeURIComponent, delimiter: delimiter6 = DEFAULT_DELIMITER } = options;
32633
32633
  const { regexp, keys } = pathToRegexp(path4, options);
32634
32634
  const decoders = keys.map((key) => {
32635
32635
  if (decode === false)
32636
32636
  return NOOP_VALUE;
32637
32637
  if (key.type === "param")
32638
32638
  return decode;
32639
- return (value) => value.split(delimiter5).map(decode);
32639
+ return (value) => value.split(delimiter6).map(decode);
32640
32640
  });
32641
32641
  return function match2(input) {
32642
32642
  const m = regexp.exec(input);
@@ -32655,20 +32655,20 @@ var require_dist2 = __commonJS({
32655
32655
  };
32656
32656
  }
32657
32657
  function pathToRegexp(path4, options = {}) {
32658
- const { delimiter: delimiter5 = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
32658
+ const { delimiter: delimiter6 = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
32659
32659
  const keys = [];
32660
32660
  const flags = sensitive ? "" : "i";
32661
32661
  const sources = [];
32662
32662
  for (const input of pathsToArray(path4, [])) {
32663
32663
  const data = typeof input === "object" ? input : parse4(input, options);
32664
32664
  for (const tokens of flatten(data.tokens, 0, [])) {
32665
- sources.push(toRegExpSource(tokens, delimiter5, keys, data.originalPath));
32665
+ sources.push(toRegExpSource(tokens, delimiter6, keys, data.originalPath));
32666
32666
  }
32667
32667
  }
32668
32668
  let pattern = `^(?:${sources.join("|")})`;
32669
32669
  if (trailing)
32670
- pattern += `(?:${escape2(delimiter5)}$)?`;
32671
- pattern += end ? "$" : `(?=${escape2(delimiter5)}|$)`;
32670
+ pattern += `(?:${escape2(delimiter6)}$)?`;
32671
+ pattern += end ? "$" : `(?=${escape2(delimiter6)}|$)`;
32672
32672
  const regexp = new RegExp(pattern, flags);
32673
32673
  return { regexp, keys };
32674
32674
  }
@@ -32695,7 +32695,7 @@ var require_dist2 = __commonJS({
32695
32695
  }
32696
32696
  yield* flatten(tokens, index + 1, init);
32697
32697
  }
32698
- function toRegExpSource(tokens, delimiter5, keys, originalPath) {
32698
+ function toRegExpSource(tokens, delimiter6, keys, originalPath) {
32699
32699
  let result = "";
32700
32700
  let backtrack = "";
32701
32701
  let isSafeSegmentParam = true;
@@ -32703,7 +32703,7 @@ var require_dist2 = __commonJS({
32703
32703
  if (token.type === "text") {
32704
32704
  result += escape2(token.value);
32705
32705
  backtrack += token.value;
32706
- isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter5));
32706
+ isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter6));
32707
32707
  continue;
32708
32708
  }
32709
32709
  if (token.type === "param" || token.type === "wildcard") {
@@ -32711,7 +32711,7 @@ var require_dist2 = __commonJS({
32711
32711
  throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
32712
32712
  }
32713
32713
  if (token.type === "param") {
32714
- result += `(${negate(delimiter5, isSafeSegmentParam ? "" : backtrack)}+)`;
32714
+ result += `(${negate(delimiter6, isSafeSegmentParam ? "" : backtrack)}+)`;
32715
32715
  } else {
32716
32716
  result += `([\\s\\S]+)`;
32717
32717
  }
@@ -32723,16 +32723,16 @@ var require_dist2 = __commonJS({
32723
32723
  }
32724
32724
  return result;
32725
32725
  }
32726
- function negate(delimiter5, backtrack) {
32726
+ function negate(delimiter6, backtrack) {
32727
32727
  if (backtrack.length < 2) {
32728
- if (delimiter5.length < 2)
32729
- return `[^${escape2(delimiter5 + backtrack)}]`;
32730
- return `(?:(?!${escape2(delimiter5)})[^${escape2(backtrack)}])`;
32728
+ if (delimiter6.length < 2)
32729
+ return `[^${escape2(delimiter6 + backtrack)}]`;
32730
+ return `(?:(?!${escape2(delimiter6)})[^${escape2(backtrack)}])`;
32731
32731
  }
32732
- if (delimiter5.length < 2) {
32733
- return `(?:(?!${escape2(backtrack)})[^${escape2(delimiter5)}])`;
32732
+ if (delimiter6.length < 2) {
32733
+ return `(?:(?!${escape2(backtrack)})[^${escape2(delimiter6)}])`;
32734
32734
  }
32735
- return `(?:(?!${escape2(backtrack)}|${escape2(delimiter5)})[\\s\\S])`;
32735
+ return `(?:(?!${escape2(backtrack)}|${escape2(delimiter6)})[\\s\\S])`;
32736
32736
  }
32737
32737
  function stringifyTokens(tokens) {
32738
32738
  let value = "";
@@ -33458,7 +33458,7 @@ var require_application = __commonJS({
33458
33458
  var compileETag = require_utils4().compileETag;
33459
33459
  var compileQueryParser = require_utils4().compileQueryParser;
33460
33460
  var compileTrust = require_utils4().compileTrust;
33461
- var resolve13 = __require("node:path").resolve;
33461
+ var resolve14 = __require("node:path").resolve;
33462
33462
  var once = require_once();
33463
33463
  var Router = require_router();
33464
33464
  var slice = Array.prototype.slice;
@@ -33512,7 +33512,7 @@ var require_application = __commonJS({
33512
33512
  this.mountpath = "/";
33513
33513
  this.locals.settings = this.settings;
33514
33514
  this.set("view", View);
33515
- this.set("views", resolve13("views"));
33515
+ this.set("views", resolve14("views"));
33516
33516
  this.set("jsonp callback name", "callback");
33517
33517
  if (env === "production") {
33518
33518
  this.enable("view cache");
@@ -34608,7 +34608,7 @@ var require_content_disposition = __commonJS({
34608
34608
  "use strict";
34609
34609
  module.exports = contentDisposition;
34610
34610
  module.exports.parse = parse4;
34611
- var basename7 = __require("path").basename;
34611
+ var basename8 = __require("path").basename;
34612
34612
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
34613
34613
  var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
34614
34614
  var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g;
@@ -34643,9 +34643,9 @@ var require_content_disposition = __commonJS({
34643
34643
  if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
34644
34644
  throw new TypeError("fallback must be ISO-8859-1 string");
34645
34645
  }
34646
- var name = basename7(filename);
34646
+ var name = basename8(filename);
34647
34647
  var isQuotedString = TEXT_REGEXP.test(name);
34648
- var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename7(fallback);
34648
+ var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename8(fallback);
34649
34649
  var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
34650
34650
  if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
34651
34651
  params["filename*"] = name;
@@ -34968,10 +34968,10 @@ var require_send = __commonJS({
34968
34968
  var statuses = require_statuses();
34969
34969
  var Stream = __require("stream");
34970
34970
  var util2 = __require("util");
34971
- var extname2 = path4.extname;
34972
- var join18 = path4.join;
34971
+ var extname3 = path4.extname;
34972
+ var join19 = path4.join;
34973
34973
  var normalize = path4.normalize;
34974
- var resolve13 = path4.resolve;
34974
+ var resolve14 = path4.resolve;
34975
34975
  var sep2 = path4.sep;
34976
34976
  var BYTES_RANGE_REGEXP = /^ *bytes=/;
34977
34977
  var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
@@ -35000,7 +35000,7 @@ var require_send = __commonJS({
35000
35000
  this._maxage = opts.maxAge || opts.maxage;
35001
35001
  this._maxage = typeof this._maxage === "string" ? ms(this._maxage) : Number(this._maxage);
35002
35002
  this._maxage = !isNaN(this._maxage) ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) : 0;
35003
- this._root = opts.root ? resolve13(opts.root) : null;
35003
+ this._root = opts.root ? resolve14(opts.root) : null;
35004
35004
  }
35005
35005
  util2.inherits(SendStream, Stream);
35006
35006
  SendStream.prototype.error = function error2(status, err) {
@@ -35141,7 +35141,7 @@ var require_send = __commonJS({
35141
35141
  return res;
35142
35142
  }
35143
35143
  parts = path5.split(sep2);
35144
- path5 = normalize(join18(root, path5));
35144
+ path5 = normalize(join19(root, path5));
35145
35145
  } else {
35146
35146
  if (UP_PATH_REGEXP.test(path5)) {
35147
35147
  debug('malicious path "%s"', path5);
@@ -35149,7 +35149,7 @@ var require_send = __commonJS({
35149
35149
  return res;
35150
35150
  }
35151
35151
  parts = normalize(path5).split(sep2);
35152
- path5 = resolve13(path5);
35152
+ path5 = resolve14(path5);
35153
35153
  }
35154
35154
  if (containsDotFile(parts)) {
35155
35155
  debug('%s dotfile "%s"', this._dotfiles, path5);
@@ -35243,7 +35243,7 @@ var require_send = __commonJS({
35243
35243
  debug('stat "%s"', path5);
35244
35244
  fs3.stat(path5, function onstat(err, stat) {
35245
35245
  var pathEndsWithSep = path5[path5.length - 1] === sep2;
35246
- if (err && err.code === "ENOENT" && !extname2(path5) && !pathEndsWithSep) {
35246
+ if (err && err.code === "ENOENT" && !extname3(path5) && !pathEndsWithSep) {
35247
35247
  return next(err);
35248
35248
  }
35249
35249
  if (err) return self.onStatError(err);
@@ -35274,7 +35274,7 @@ var require_send = __commonJS({
35274
35274
  if (err) return self.onStatError(err);
35275
35275
  return self.error(404);
35276
35276
  }
35277
- var p = join18(path5, self._index[i]);
35277
+ var p = join19(path5, self._index[i]);
35278
35278
  debug('stat "%s"', p);
35279
35279
  fs3.stat(p, function(err2, stat) {
35280
35280
  if (err2) return next(err2);
@@ -35306,7 +35306,7 @@ var require_send = __commonJS({
35306
35306
  SendStream.prototype.type = function type2(path5) {
35307
35307
  var res = this.res;
35308
35308
  if (res.getHeader("Content-Type")) return;
35309
- var ext = extname2(path5);
35309
+ var ext = extname3(path5);
35310
35310
  var type3 = mime.contentType(ext) || "application/octet-stream";
35311
35311
  debug("content-type %s", type3);
35312
35312
  res.setHeader("Content-Type", type3);
@@ -35526,8 +35526,8 @@ var require_response = __commonJS({
35526
35526
  var setCharset = require_utils4().setCharset;
35527
35527
  var cookie = require_cookie();
35528
35528
  var send = require_send();
35529
- var extname2 = path4.extname;
35530
- var resolve13 = path4.resolve;
35529
+ var extname3 = path4.extname;
35530
+ var resolve14 = path4.resolve;
35531
35531
  var vary = require_vary();
35532
35532
  var { Buffer: Buffer2 } = __require("node:buffer");
35533
35533
  var res = Object.create(http.ServerResponse.prototype);
@@ -35733,7 +35733,7 @@ var require_response = __commonJS({
35733
35733
  }
35734
35734
  opts = Object.create(opts);
35735
35735
  opts.headers = headers;
35736
- var fullPath = !opts.root ? resolve13(path5) : path5;
35736
+ var fullPath = !opts.root ? resolve14(path5) : path5;
35737
35737
  return this.sendFile(fullPath, opts, done);
35738
35738
  };
35739
35739
  res.contentType = res.type = function contentType(type2) {
@@ -35764,7 +35764,7 @@ var require_response = __commonJS({
35764
35764
  };
35765
35765
  res.attachment = function attachment(filename) {
35766
35766
  if (filename) {
35767
- this.type(extname2(filename));
35767
+ this.type(extname3(filename));
35768
35768
  }
35769
35769
  this.set("Content-Disposition", contentDisposition(filename));
35770
35770
  return this;
@@ -35982,7 +35982,7 @@ var require_serve_static = __commonJS({
35982
35982
  var encodeUrl = require_encodeurl();
35983
35983
  var escapeHtml = require_escape_html();
35984
35984
  var parseUrl = require_parseurl();
35985
- var resolve13 = __require("path").resolve;
35985
+ var resolve14 = __require("path").resolve;
35986
35986
  var send = require_send();
35987
35987
  var url = __require("url");
35988
35988
  module.exports = serveStatic;
@@ -36001,7 +36001,7 @@ var require_serve_static = __commonJS({
36001
36001
  throw new TypeError("option setHeaders must be function");
36002
36002
  }
36003
36003
  opts.maxage = opts.maxage || opts.maxAge || 0;
36004
- opts.root = resolve13(root);
36004
+ opts.root = resolve14(root);
36005
36005
  var onDirectory = redirect ? createRedirectDirectoryListener() : createNotFoundDirectoryListener();
36006
36006
  return function serveStatic2(req, res, next) {
36007
36007
  if (req.method !== "GET" && req.method !== "HEAD") {
@@ -36992,7 +36992,7 @@ var init_temp_dir = __esm({
36992
36992
  import { clearTimeout as clearTimeout2, setTimeout as setTimeout2 } from "timers";
36993
36993
  function waitForProcessReady(child, name, opts) {
36994
36994
  const timeoutMs = opts?.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
36995
- return new Promise((resolve13, reject) => {
36995
+ return new Promise((resolve14, reject) => {
36996
36996
  let settled = false;
36997
36997
  const cleanup = () => {
36998
36998
  settled = true;
@@ -37006,13 +37006,13 @@ function waitForProcessReady(child, name, opts) {
37006
37006
  if (settled) return;
37007
37007
  logger.debug(`${name}: ready (stderr output detected)`);
37008
37008
  cleanup();
37009
- resolve13();
37009
+ resolve14();
37010
37010
  };
37011
37011
  const onStdout = () => {
37012
37012
  if (settled) return;
37013
37013
  logger.debug(`${name}: ready (stdout output detected)`);
37014
37014
  cleanup();
37015
- resolve13();
37015
+ resolve14();
37016
37016
  };
37017
37017
  const onError = (error2) => {
37018
37018
  if (settled) return;
@@ -37028,7 +37028,7 @@ function waitForProcessReady(child, name, opts) {
37028
37028
  if (settled) return;
37029
37029
  logger.warn(`${name}: readiness timeout (${timeoutMs} ms) \u2014 proceeding anyway`);
37030
37030
  cleanup();
37031
- resolve13();
37031
+ resolve14();
37032
37032
  }, timeoutMs);
37033
37033
  child.stderr?.on("data", onStderr);
37034
37034
  child.stdout?.on("data", onStdout);
@@ -37196,7 +37196,7 @@ var init_language_server = __esm({
37196
37196
  method,
37197
37197
  params
37198
37198
  };
37199
- return new Promise((resolve13, reject) => {
37199
+ return new Promise((resolve14, reject) => {
37200
37200
  const timer = setTimeout3(() => {
37201
37201
  if (this.pendingResponses.has(id)) {
37202
37202
  this.pendingResponses.delete(id);
@@ -37210,7 +37210,7 @@ var init_language_server = __esm({
37210
37210
  },
37211
37211
  resolve: (val) => {
37212
37212
  clearTimeout3(timer);
37213
- resolve13(val);
37213
+ resolve14(val);
37214
37214
  }
37215
37215
  });
37216
37216
  this.sendMessage(message);
@@ -37299,7 +37299,7 @@ var init_language_server = __esm({
37299
37299
  throw new Error("Language server is not initialized");
37300
37300
  }
37301
37301
  const documentUri = uri || pathToFileURL(join2(getProjectTmpDir("lsp-eval"), "eval.ql")).href;
37302
- return new Promise((resolve13, reject) => {
37302
+ return new Promise((resolve14, reject) => {
37303
37303
  let diagnosticsReceived = false;
37304
37304
  const timeout = setTimeout3(() => {
37305
37305
  if (!diagnosticsReceived) {
@@ -37315,7 +37315,7 @@ var init_language_server = __esm({
37315
37315
  this.sendNotification("textDocument/didClose", {
37316
37316
  textDocument: { uri: documentUri }
37317
37317
  });
37318
- resolve13(params.diagnostics);
37318
+ resolve14(params.diagnostics);
37319
37319
  }
37320
37320
  };
37321
37321
  this.on("diagnostics", diagnosticsHandler);
@@ -37430,22 +37430,22 @@ var init_language_server = __esm({
37430
37430
  } catch (error2) {
37431
37431
  logger.warn("Error during graceful shutdown:", error2);
37432
37432
  }
37433
- await new Promise((resolve13) => {
37433
+ await new Promise((resolve14) => {
37434
37434
  const timer = setTimeout3(() => {
37435
37435
  if (this.server) {
37436
37436
  this.server.kill("SIGTERM");
37437
37437
  }
37438
- resolve13();
37438
+ resolve14();
37439
37439
  }, 1e3);
37440
37440
  if (this.server) {
37441
37441
  this.server.once("exit", () => {
37442
37442
  clearTimeout3(timer);
37443
37443
  this.server = null;
37444
- resolve13();
37444
+ resolve14();
37445
37445
  });
37446
37446
  } else {
37447
37447
  clearTimeout3(timer);
37448
- resolve13();
37448
+ resolve14();
37449
37449
  }
37450
37450
  });
37451
37451
  this.isInitialized = false;
@@ -37535,8 +37535,8 @@ var init_query_server = __esm({
37535
37535
  method,
37536
37536
  params
37537
37537
  };
37538
- return new Promise((resolve13, reject) => {
37539
- this.pendingRequests.set(id, { reject, resolve: resolve13 });
37538
+ return new Promise((resolve14, reject) => {
37539
+ this.pendingRequests.set(id, { reject, resolve: resolve14 });
37540
37540
  try {
37541
37541
  this.sendRaw(message);
37542
37542
  } catch (error2) {
@@ -37550,7 +37550,7 @@ var init_query_server = __esm({
37550
37550
  reject(new Error(`Query server request timeout for method: ${method}`));
37551
37551
  }
37552
37552
  }, timeoutMs);
37553
- const originalResolve = resolve13;
37553
+ const originalResolve = resolve14;
37554
37554
  const originalReject = reject;
37555
37555
  const wrapped = {
37556
37556
  reject: (err) => {
@@ -37578,23 +37578,23 @@ var init_query_server = __esm({
37578
37578
  } catch (error2) {
37579
37579
  logger.warn("Error during query server graceful shutdown:", error2);
37580
37580
  }
37581
- await new Promise((resolve13) => {
37581
+ await new Promise((resolve14) => {
37582
37582
  const timer = setTimeout4(() => {
37583
37583
  if (this.process) {
37584
37584
  this.process.kill("SIGTERM");
37585
37585
  this.process = null;
37586
37586
  }
37587
- resolve13();
37587
+ resolve14();
37588
37588
  }, 2e3);
37589
37589
  if (this.process) {
37590
37590
  this.process.once("exit", () => {
37591
37591
  clearTimeout4(timer);
37592
37592
  this.process = null;
37593
- resolve13();
37593
+ resolve14();
37594
37594
  });
37595
37595
  } else {
37596
37596
  clearTimeout4(timer);
37597
- resolve13();
37597
+ resolve14();
37598
37598
  }
37599
37599
  });
37600
37600
  }
@@ -37755,9 +37755,9 @@ var init_cli_server = __esm({
37755
37755
  * @returns The stdout output from the command.
37756
37756
  */
37757
37757
  runCommand(args) {
37758
- return new Promise((resolve13, reject) => {
37758
+ return new Promise((resolve14, reject) => {
37759
37759
  const execute = () => {
37760
- this.executeCommand({ args, reject, resolve: resolve13 });
37760
+ this.executeCommand({ args, reject, resolve: resolve14 });
37761
37761
  };
37762
37762
  if (this.commandInProgress) {
37763
37763
  this.commandQueue.push(execute);
@@ -37780,23 +37780,23 @@ var init_cli_server = __esm({
37780
37780
  } catch (error2) {
37781
37781
  logger.warn("Error during CLI server shutdown request:", error2);
37782
37782
  }
37783
- await new Promise((resolve13) => {
37783
+ await new Promise((resolve14) => {
37784
37784
  const timer = setTimeout5(() => {
37785
37785
  if (this.process) {
37786
37786
  this.process.kill("SIGTERM");
37787
37787
  this.process = null;
37788
37788
  }
37789
- resolve13();
37789
+ resolve14();
37790
37790
  }, 2e3);
37791
37791
  if (this.process) {
37792
37792
  this.process.once("exit", () => {
37793
37793
  clearTimeout5(timer);
37794
37794
  this.process = null;
37795
- resolve13();
37795
+ resolve14();
37796
37796
  });
37797
37797
  } else {
37798
37798
  clearTimeout5(timer);
37799
- resolve13();
37799
+ resolve14();
37800
37800
  }
37801
37801
  });
37802
37802
  this.commandInProgress = false;
@@ -38041,11 +38041,11 @@ var init_server_manager = __esm({
38041
38041
  async warmUpLanguageServer() {
38042
38042
  try {
38043
38043
  const { packageRootDir: packageRootDir2 } = await Promise.resolve().then(() => (init_package_paths(), package_paths_exports));
38044
- const { resolve: resolve13 } = await import("path");
38044
+ const { resolve: resolve14 } = await import("path");
38045
38045
  const config2 = {
38046
38046
  checkErrors: "ON_CHANGE",
38047
38047
  loglevel: "WARN",
38048
- searchPath: resolve13(packageRootDir2, "ql")
38048
+ searchPath: resolve14(packageRootDir2, "ql")
38049
38049
  };
38050
38050
  logger.info("Warming up language server (background JVM start)...");
38051
38051
  await this.getLanguageServer(config2);
@@ -40527,8 +40527,8 @@ var require_adm_zip = __commonJS({
40527
40527
  return null;
40528
40528
  }
40529
40529
  function fixPath(zipPath) {
40530
- const { join: join18, normalize, sep: sep2 } = pth.posix;
40531
- return join18(".", normalize(sep2 + zipPath.split("\\").join(sep2) + sep2));
40530
+ const { join: join19, normalize, sep: sep2 } = pth.posix;
40531
+ return join19(".", normalize(sep2 + zipPath.split("\\").join(sep2) + sep2));
40532
40532
  }
40533
40533
  function filenameFilter(filterfn) {
40534
40534
  if (filterfn instanceof RegExp) {
@@ -40923,10 +40923,10 @@ var require_adm_zip = __commonJS({
40923
40923
  * @param {function|string} [props.namefix] - optional function to help fix filename
40924
40924
  */
40925
40925
  addLocalFolderPromise: function(localPath2, props) {
40926
- return new Promise((resolve13, reject) => {
40926
+ return new Promise((resolve14, reject) => {
40927
40927
  this.addLocalFolderAsync2(Object.assign({ localPath: localPath2 }, props), (err, done) => {
40928
40928
  if (err) reject(err);
40929
- if (done) resolve13(this);
40929
+ if (done) resolve14(this);
40930
40930
  });
40931
40931
  });
40932
40932
  },
@@ -41113,12 +41113,12 @@ var require_adm_zip = __commonJS({
41113
41113
  keepOriginalPermission = get_Bool(false, keepOriginalPermission);
41114
41114
  overwrite = get_Bool(false, overwrite);
41115
41115
  if (!callback) {
41116
- return new Promise((resolve13, reject) => {
41116
+ return new Promise((resolve14, reject) => {
41117
41117
  this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function(err) {
41118
41118
  if (err) {
41119
41119
  reject(err);
41120
41120
  } else {
41121
- resolve13(this);
41121
+ resolve14(this);
41122
41122
  }
41123
41123
  });
41124
41124
  });
@@ -41216,11 +41216,11 @@ var require_adm_zip = __commonJS({
41216
41216
  */
41217
41217
  writeZipPromise: function(targetFileName, props) {
41218
41218
  const { overwrite, perm } = Object.assign({ overwrite: true }, props);
41219
- return new Promise((resolve13, reject) => {
41219
+ return new Promise((resolve14, reject) => {
41220
41220
  if (!targetFileName && opts.filename) targetFileName = opts.filename;
41221
41221
  if (!targetFileName) reject("ADM-ZIP: ZIP File Name Missing");
41222
41222
  this.toBufferPromise().then((zipData) => {
41223
- const ret = (done) => done ? resolve13(done) : reject("ADM-ZIP: Wasn't able to write zip file");
41223
+ const ret = (done) => done ? resolve14(done) : reject("ADM-ZIP: Wasn't able to write zip file");
41224
41224
  filetools.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);
41225
41225
  }, reject);
41226
41226
  });
@@ -41229,8 +41229,8 @@ var require_adm_zip = __commonJS({
41229
41229
  * @returns {Promise<Buffer>} A promise to the Buffer.
41230
41230
  */
41231
41231
  toBufferPromise: function() {
41232
- return new Promise((resolve13, reject) => {
41233
- _zip.toAsyncBuffer(resolve13, reject);
41232
+ return new Promise((resolve14, reject) => {
41233
+ _zip.toAsyncBuffer(resolve14, reject);
41234
41234
  });
41235
41235
  },
41236
41236
  /**
@@ -53328,7 +53328,7 @@ var Protocol = class {
53328
53328
  return;
53329
53329
  }
53330
53330
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
53331
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
53331
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
53332
53332
  options?.signal?.throwIfAborted();
53333
53333
  }
53334
53334
  } catch (error2) {
@@ -53345,7 +53345,7 @@ var Protocol = class {
53345
53345
  */
53346
53346
  request(request, resultSchema, options) {
53347
53347
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
53348
- return new Promise((resolve13, reject) => {
53348
+ return new Promise((resolve14, reject) => {
53349
53349
  const earlyReject = (error2) => {
53350
53350
  reject(error2);
53351
53351
  };
@@ -53423,7 +53423,7 @@ var Protocol = class {
53423
53423
  if (!parseResult.success) {
53424
53424
  reject(parseResult.error);
53425
53425
  } else {
53426
- resolve13(parseResult.data);
53426
+ resolve14(parseResult.data);
53427
53427
  }
53428
53428
  } catch (error2) {
53429
53429
  reject(error2);
@@ -53684,12 +53684,12 @@ var Protocol = class {
53684
53684
  }
53685
53685
  } catch {
53686
53686
  }
53687
- return new Promise((resolve13, reject) => {
53687
+ return new Promise((resolve14, reject) => {
53688
53688
  if (signal.aborted) {
53689
53689
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
53690
53690
  return;
53691
53691
  }
53692
- const timeoutId = setTimeout(resolve13, interval);
53692
+ const timeoutId = setTimeout(resolve14, interval);
53693
53693
  signal.addEventListener("abort", () => {
53694
53694
  clearTimeout(timeoutId);
53695
53695
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -54789,7 +54789,7 @@ var McpServer = class {
54789
54789
  let task = createTaskResult.task;
54790
54790
  const pollInterval = task.pollInterval ?? 5e3;
54791
54791
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
54792
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
54792
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
54793
54793
  const updatedTask = await extra.taskStore.getTask(taskId);
54794
54794
  if (!updatedTask) {
54795
54795
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -55432,12 +55432,12 @@ var StdioServerTransport = class {
55432
55432
  this.onclose?.();
55433
55433
  }
55434
55434
  send(message) {
55435
- return new Promise((resolve13) => {
55435
+ return new Promise((resolve14) => {
55436
55436
  const json2 = serializeMessage(message);
55437
55437
  if (this._stdout.write(json2)) {
55438
- resolve13();
55438
+ resolve14();
55439
55439
  } else {
55440
- this._stdout.once("drain", resolve13);
55440
+ this._stdout.once("drain", resolve14);
55441
55441
  }
55442
55442
  });
55443
55443
  }
@@ -55870,7 +55870,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
55870
55870
  });
55871
55871
  if (!chunk) {
55872
55872
  if (i === 1) {
55873
- await new Promise((resolve13) => setTimeout(resolve13));
55873
+ await new Promise((resolve14) => setTimeout(resolve14));
55874
55874
  maxReadCount = 3;
55875
55875
  continue;
55876
55876
  }
@@ -56366,9 +56366,9 @@ data:
56366
56366
  const initRequest = messages.find((m) => isInitializeRequest(m));
56367
56367
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
56368
56368
  if (this._enableJsonResponse) {
56369
- return new Promise((resolve13) => {
56369
+ return new Promise((resolve14) => {
56370
56370
  this._streamMapping.set(streamId, {
56371
- resolveJson: resolve13,
56371
+ resolveJson: resolve14,
56372
56372
  cleanup: () => {
56373
56373
  this._streamMapping.delete(streamId);
56374
56374
  }
@@ -56702,8 +56702,8 @@ var StreamableHTTPServerTransport = class {
56702
56702
  var import_express = __toESM(require_express2(), 1);
56703
56703
  var import_cors = __toESM(require_lib3(), 1);
56704
56704
  var import_dotenv = __toESM(require_main(), 1);
56705
- import { realpathSync } from "fs";
56706
- import { resolve as resolve12 } from "path";
56705
+ import { realpathSync as realpathSync2 } from "fs";
56706
+ import { resolve as resolve13 } from "path";
56707
56707
  import { pathToFileURL as pathToFileURL5 } from "url";
56708
56708
 
56709
56709
  // src/lib/cli-tool-registry.ts
@@ -57005,8 +57005,41 @@ function getOrCreateLogDirectory(logDir) {
57005
57005
  // src/lib/cli-tool-registry.ts
57006
57006
  init_package_paths();
57007
57007
  init_temp_dir();
57008
- import { writeFileSync as writeFileSync2, rmSync, existsSync as existsSync4, mkdirSync as mkdirSync5 } from "fs";
57008
+ import { writeFileSync as writeFileSync2, rmSync, existsSync as existsSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
57009
57009
  import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute4, join as join6, resolve as resolve4 } from "path";
57010
+ function resolveDatabasePath(dbPath) {
57011
+ if (existsSync4(join6(dbPath, "codeql-database.yml"))) {
57012
+ return dbPath;
57013
+ }
57014
+ try {
57015
+ const entries = readdirSync2(dbPath);
57016
+ const candidates = [];
57017
+ for (const entry of entries) {
57018
+ const candidate = join6(dbPath, entry);
57019
+ try {
57020
+ if (statSync2(candidate).isDirectory() && existsSync4(join6(candidate, "codeql-database.yml"))) {
57021
+ candidates.push(candidate);
57022
+ }
57023
+ } catch {
57024
+ }
57025
+ }
57026
+ if (candidates.length === 1) {
57027
+ logger.info(`Resolved database directory: ${dbPath} -> ${candidates[0]}`);
57028
+ return candidates[0];
57029
+ }
57030
+ if (candidates.length > 1) {
57031
+ const names = candidates.map((c) => basename2(c)).join(", ");
57032
+ throw new Error(
57033
+ `Ambiguous database path: ${dbPath} contains multiple databases (${names}). Specify the full path to the desired database subfolder.`
57034
+ );
57035
+ }
57036
+ } catch (err) {
57037
+ if (err instanceof Error && err.message.startsWith("Ambiguous database path")) {
57038
+ throw err;
57039
+ }
57040
+ }
57041
+ return dbPath;
57042
+ }
57010
57043
  var defaultCLIResultProcessor = (result, _params) => {
57011
57044
  if (!result.success) {
57012
57045
  return `Command failed (exit code ${result.exitCode || "unknown"}):
@@ -57044,7 +57077,7 @@ function registerCLITool(server, definition) {
57044
57077
  const tempDirsToCleanup = [];
57045
57078
  try {
57046
57079
  logger.info(`Executing CLI tool: ${name}`, { command, subcommand, params });
57047
- const formatShouldBePassedToCLI = name === "codeql_bqrs_interpret" || name === "codeql_bqrs_decode" || name === "codeql_bqrs_info" || name === "codeql_generate_query-help" || name === "codeql_database_analyze";
57080
+ const formatShouldBePassedToCLI = name === "codeql_bqrs_interpret" || name === "codeql_bqrs_decode" || name === "codeql_bqrs_info" || name === "codeql_generate_query-help" || name === "codeql_database_analyze" || name === "codeql_resolve_files";
57048
57081
  const extractedParams = formatShouldBePassedToCLI ? {
57049
57082
  _positional: params._positional || [],
57050
57083
  files: params.files,
@@ -57122,7 +57155,7 @@ function registerCLITool(server, definition) {
57122
57155
  positionalArgs = [...positionalArgs, qlref];
57123
57156
  }
57124
57157
  if (options.database && name === "codeql_resolve_database") {
57125
- positionalArgs = [...positionalArgs, options.database];
57158
+ positionalArgs = [...positionalArgs, resolveDatabasePath(options.database)];
57126
57159
  delete options.database;
57127
57160
  }
57128
57161
  if (options.database && name === "codeql_database_create") {
@@ -57131,7 +57164,7 @@ function registerCLITool(server, definition) {
57131
57164
  }
57132
57165
  if (name === "codeql_database_analyze") {
57133
57166
  if (options.database) {
57134
- positionalArgs = [...positionalArgs, options.database];
57167
+ positionalArgs = [...positionalArgs, resolveDatabasePath(options.database)];
57135
57168
  delete options.database;
57136
57169
  }
57137
57170
  if (options.queries) {
@@ -57162,6 +57195,9 @@ function registerCLITool(server, definition) {
57162
57195
  options.database = resolve4(getUserWorkspaceDir(), options.database);
57163
57196
  logger.info(`Resolved database path to: ${options.database}`);
57164
57197
  }
57198
+ if (options.database && typeof options.database === "string") {
57199
+ options.database = resolveDatabasePath(options.database);
57200
+ }
57165
57201
  const resolvedQuery = await resolveQueryPath(params, logger);
57166
57202
  if (resolvedQuery) {
57167
57203
  positionalArgs = [...positionalArgs, resolvedQuery];
@@ -57241,6 +57277,11 @@ function registerCLITool(server, definition) {
57241
57277
  positionalArgs = [...positionalArgs, directory];
57242
57278
  }
57243
57279
  break;
57280
+ case "codeql_resolve_files":
57281
+ if (dir) {
57282
+ positionalArgs = [...positionalArgs, dir];
57283
+ }
57284
+ break;
57244
57285
  default:
57245
57286
  break;
57246
57287
  }
@@ -60714,6 +60755,18 @@ async function findCodeQLQueryFiles(queryFilePath, language, resolveMetadata = t
60714
60755
  }
60715
60756
  const testPackPath = findNearestQlpack(testDir);
60716
60757
  const testPackDir = testPackPath ? path.dirname(testPackPath) : testDir;
60758
+ const hints = [];
60759
+ if (!testDirectory.exists) {
60760
+ hints.push("No test directory found. To run this query you will need a user-provided database (databasePath). Test-driven profiling is not available without tests.");
60761
+ } else if (testCodePaths.length === 0) {
60762
+ hints.push("Test directory exists but contains no test source code files. Consider creating test code to enable test-driven workflows.");
60763
+ }
60764
+ if (!expectedResultsPath.exists && testDirectory.exists) {
60765
+ hints.push("No .expected file found. Run codeql_test_run to generate initial expected results, then verify them.");
60766
+ }
60767
+ if (!documentationPath.exists) {
60768
+ hints.push("No query documentation (.md) file found. Use the document_codeql_query prompt to generate one.");
60769
+ }
60717
60770
  return {
60718
60771
  queryName,
60719
60772
  language: detectedLanguage,
@@ -60736,6 +60789,7 @@ async function findCodeQLQueryFiles(queryFilePath, language, resolveMetadata = t
60736
60789
  testDatabaseDir: testDatabasePath.path
60737
60790
  }
60738
60791
  },
60792
+ hints,
60739
60793
  metadata,
60740
60794
  missingFiles,
60741
60795
  packMetadata,
@@ -60837,15 +60891,16 @@ var codeqlGenerateQueryHelpTool = {
60837
60891
  };
60838
60892
 
60839
60893
  // src/tools/codeql/list-databases.ts
60840
- import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
60894
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
60841
60895
  import { join as join8 } from "path";
60842
60896
 
60843
60897
  // src/lib/discovery-config.ts
60898
+ import { delimiter as delimiter5 } from "path";
60844
60899
  function parsePathList(envValue) {
60845
60900
  if (!envValue) {
60846
60901
  return [];
60847
60902
  }
60848
- return envValue.split(":").map((p) => p.trim()).filter((p) => p.length > 0);
60903
+ return envValue.split(delimiter5).map((p) => p.trim()).filter((p) => p.length > 0);
60849
60904
  }
60850
60905
  function getDatabaseBaseDirs() {
60851
60906
  return parsePathList(process.env.CODEQL_DATABASES_BASE_DIRS);
@@ -60894,14 +60949,14 @@ async function discoverDatabases(baseDirs, language) {
60894
60949
  }
60895
60950
  let entries;
60896
60951
  try {
60897
- entries = readdirSync3(baseDir);
60952
+ entries = readdirSync4(baseDir);
60898
60953
  } catch {
60899
60954
  continue;
60900
60955
  }
60901
60956
  for (const entry of entries) {
60902
60957
  const entryPath = join8(baseDir, entry);
60903
60958
  try {
60904
- if (!statSync3(entryPath).isDirectory()) {
60959
+ if (!statSync4(entryPath).isDirectory()) {
60905
60960
  continue;
60906
60961
  }
60907
60962
  } catch {
@@ -60990,7 +61045,7 @@ function registerListDatabasesTool(server) {
60990
61045
  }
60991
61046
 
60992
61047
  // src/tools/codeql/list-mrva-run-results.ts
60993
- import { existsSync as existsSync7, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
61048
+ import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
60994
61049
  import { join as join9 } from "path";
60995
61050
  init_logger();
60996
61051
  var NUMERIC_DIR_PATTERN = /^\d+$/;
@@ -61003,14 +61058,14 @@ async function discoverMrvaRunResults(resultsDirs, runId) {
61003
61058
  }
61004
61059
  let entries;
61005
61060
  try {
61006
- entries = readdirSync4(dir);
61061
+ entries = readdirSync5(dir);
61007
61062
  } catch {
61008
61063
  continue;
61009
61064
  }
61010
61065
  for (const entry of entries) {
61011
61066
  const entryPath = join9(dir, entry);
61012
61067
  try {
61013
- if (!statSync4(entryPath).isDirectory()) {
61068
+ if (!statSync5(entryPath).isDirectory()) {
61014
61069
  continue;
61015
61070
  }
61016
61071
  } catch {
@@ -61045,7 +61100,7 @@ function discoverRepoResults(runPath) {
61045
61100
  const repos = [];
61046
61101
  let ownerEntries;
61047
61102
  try {
61048
- ownerEntries = readdirSync4(runPath);
61103
+ ownerEntries = readdirSync5(runPath);
61049
61104
  } catch {
61050
61105
  return repos;
61051
61106
  }
@@ -61055,7 +61110,7 @@ function discoverRepoResults(runPath) {
61055
61110
  }
61056
61111
  const ownerPath = join9(runPath, ownerEntry);
61057
61112
  try {
61058
- if (!statSync4(ownerPath).isDirectory()) {
61113
+ if (!statSync5(ownerPath).isDirectory()) {
61059
61114
  continue;
61060
61115
  }
61061
61116
  } catch {
@@ -61063,14 +61118,14 @@ function discoverRepoResults(runPath) {
61063
61118
  }
61064
61119
  let repoEntries;
61065
61120
  try {
61066
- repoEntries = readdirSync4(ownerPath);
61121
+ repoEntries = readdirSync5(ownerPath);
61067
61122
  } catch {
61068
61123
  continue;
61069
61124
  }
61070
61125
  for (const repoEntry of repoEntries) {
61071
61126
  const repoPath = join9(ownerPath, repoEntry);
61072
61127
  try {
61073
- if (!statSync4(repoPath).isDirectory()) {
61128
+ if (!statSync5(repoPath).isDirectory()) {
61074
61129
  continue;
61075
61130
  }
61076
61131
  } catch {
@@ -61177,7 +61232,7 @@ function registerListMrvaRunResultsTool(server) {
61177
61232
  }
61178
61233
 
61179
61234
  // src/tools/codeql/list-query-run-results.ts
61180
- import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
61235
+ import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
61181
61236
  import { join as join10 } from "path";
61182
61237
  init_logger();
61183
61238
  var QUERY_RUN_DIR_PATTERN = /^(.+\.ql)-(.+)$/;
@@ -61219,14 +61274,14 @@ async function discoverQueryRunResults(resultsDirs, filter) {
61219
61274
  }
61220
61275
  let entries;
61221
61276
  try {
61222
- entries = readdirSync5(dir);
61277
+ entries = readdirSync6(dir);
61223
61278
  } catch {
61224
61279
  continue;
61225
61280
  }
61226
61281
  for (const entry of entries) {
61227
61282
  const entryPath = join10(dir, entry);
61228
61283
  try {
61229
- if (!statSync5(entryPath).isDirectory()) {
61284
+ if (!statSync6(entryPath).isDirectory()) {
61230
61285
  continue;
61231
61286
  }
61232
61287
  } catch {
@@ -61434,57 +61489,87 @@ import { basename as basename4, dirname as dirname6, join as join11 } from "path
61434
61489
 
61435
61490
  // src/lib/evaluator-log-parser.ts
61436
61491
  init_logger();
61437
- import { readFileSync as readFileSync8 } from "fs";
61492
+ import { createReadStream } from "fs";
61493
+ import { createInterface } from "readline";
61438
61494
  function detectLogFormat(firstEvent) {
61439
61495
  if (typeof firstEvent.type === "string") {
61440
61496
  return "raw";
61441
61497
  }
61442
61498
  return "summary";
61443
61499
  }
61444
- function splitJsonObjects(content) {
61445
- const trimmed = content.trim();
61446
- if (trimmed.length === 0) {
61447
- return [];
61448
- }
61449
- const parts = trimmed.split(/\n\}\s*\n\s*\{/);
61450
- if (parts.length === 1) {
61451
- return [trimmed];
61452
- }
61453
- return parts.map((part, idx) => {
61454
- if (idx === 0) {
61455
- return part + "\n}";
61456
- }
61457
- if (idx === parts.length - 1) {
61458
- return "{\n" + part;
61459
- }
61460
- return "{\n" + part + "\n}";
61500
+ async function* streamJsonObjects(logPath) {
61501
+ const rl = createInterface({
61502
+ input: createReadStream(logPath, { encoding: "utf-8" }),
61503
+ crlfDelay: Infinity
61461
61504
  });
61462
- }
61463
- function parseJsonObjects(logPath) {
61464
- const content = readFileSync8(logPath, "utf-8");
61465
- const objectStrings = splitJsonObjects(content);
61466
- const results = [];
61467
- for (const objStr of objectStrings) {
61468
- try {
61469
- results.push(JSON.parse(objStr));
61470
- } catch {
61471
- logger.warn(
61472
- `Failed to parse evaluator log object: ${objStr.substring(0, 120)}...`
61473
- );
61505
+ let depth = 0;
61506
+ let inString = false;
61507
+ let escape2 = false;
61508
+ const lines = [];
61509
+ for await (const line of rl) {
61510
+ for (const ch of line) {
61511
+ if (escape2) {
61512
+ escape2 = false;
61513
+ continue;
61514
+ }
61515
+ if (ch === "\\" && inString) {
61516
+ escape2 = true;
61517
+ continue;
61518
+ }
61519
+ if (ch === '"') {
61520
+ inString = !inString;
61521
+ continue;
61522
+ }
61523
+ if (inString) continue;
61524
+ if (ch === "{") depth++;
61525
+ if (ch === "}") depth--;
61526
+ }
61527
+ if (depth > 0 || depth === 0 && line.trim().length > 0 && lines.length > 0) {
61528
+ lines.push(line);
61529
+ } else if (depth === 0 && lines.length === 0 && line.trim().length > 0) {
61530
+ lines.push(line);
61531
+ }
61532
+ if (depth === 0 && lines.length > 0) {
61533
+ const objStr = lines.join("\n");
61534
+ lines.length = 0;
61535
+ inString = false;
61536
+ escape2 = false;
61537
+ if (objStr.trim().length === 0) continue;
61538
+ try {
61539
+ yield JSON.parse(objStr);
61540
+ } catch {
61541
+ logger.warn(
61542
+ `Failed to parse evaluator log object: ${objStr.substring(0, 120)}...`
61543
+ );
61544
+ }
61545
+ }
61546
+ }
61547
+ if (lines.length > 0) {
61548
+ const objStr = lines.join("\n");
61549
+ if (objStr.trim().length > 0) {
61550
+ try {
61551
+ yield JSON.parse(objStr);
61552
+ } catch {
61553
+ logger.warn(
61554
+ `Failed to parse trailing evaluator log object: ${objStr.substring(0, 120)}...`
61555
+ );
61556
+ }
61474
61557
  }
61475
61558
  }
61476
- return results;
61477
61559
  }
61478
- function parseRawEvaluatorLog(logPath) {
61479
- const events = parseJsonObjects(logPath);
61560
+ async function processRawEvents(events) {
61480
61561
  let codeqlVersion;
61481
61562
  const queryStartEvents = /* @__PURE__ */ new Map();
61482
61563
  const predicateStartEvents = /* @__PURE__ */ new Map();
61564
+ const pipelineStartNanoTimes = /* @__PURE__ */ new Map();
61565
+ const pipelineToPredicateMap = /* @__PURE__ */ new Map();
61483
61566
  const queryPredicates = /* @__PURE__ */ new Map();
61484
61567
  const queryEndNanoTimes = /* @__PURE__ */ new Map();
61485
61568
  const queryCacheHits = /* @__PURE__ */ new Map();
61486
61569
  let firstQueryEventId;
61487
- for (const event of events) {
61570
+ let totalEvents = 0;
61571
+ for await (const event of events) {
61572
+ totalEvents++;
61488
61573
  const eventType = event.type;
61489
61574
  switch (eventType) {
61490
61575
  case "LOG_HEADER": {
@@ -61513,6 +61598,11 @@ function parseRawEvaluatorLog(logPath) {
61513
61598
  case "PREDICATE_STARTED": {
61514
61599
  const eid = event.eventId;
61515
61600
  const deps = event.dependencies;
61601
+ const raObj = event.ra;
61602
+ let raSteps;
61603
+ if (raObj && Array.isArray(raObj.pipeline)) {
61604
+ raSteps = raObj.pipeline.map((s) => s.trim());
61605
+ }
61516
61606
  predicateStartEvents.set(eid, {
61517
61607
  predicateName: event.predicateName || "unknown",
61518
61608
  position: event.position,
@@ -61520,20 +61610,34 @@ function parseRawEvaluatorLog(logPath) {
61520
61610
  dependencies: deps ? Object.keys(deps) : [],
61521
61611
  queryCausingWork: event.queryCausingWork,
61522
61612
  nanoTime: event.nanoTime,
61523
- pipelineCount: 0
61613
+ pipelineCount: 0,
61614
+ raSteps,
61615
+ pipelineStages: []
61524
61616
  });
61525
61617
  break;
61526
61618
  }
61619
+ case "PIPELINE_STARTED": {
61620
+ const eid = event.eventId;
61621
+ pipelineStartNanoTimes.set(eid, event.nanoTime);
61622
+ const predEid = event.predicateStartEvent;
61623
+ pipelineToPredicateMap.set(eid, predEid);
61624
+ break;
61625
+ }
61527
61626
  case "PIPELINE_COMPLETED": {
61528
61627
  const pipelineStartEid = event.startEvent;
61529
- const pipelineStartEvt = events.find(
61530
- (e) => e.type === "PIPELINE_STARTED" && e.eventId === pipelineStartEid
61531
- );
61532
- if (pipelineStartEvt) {
61533
- const predEid = pipelineStartEvt.predicateStartEvent;
61628
+ const predEid = pipelineToPredicateMap.get(pipelineStartEid);
61629
+ const startNano = pipelineStartNanoTimes.get(pipelineStartEid);
61630
+ if (predEid !== void 0) {
61534
61631
  const predStart = predicateStartEvents.get(predEid);
61535
61632
  if (predStart) {
61536
61633
  predStart.pipelineCount += 1;
61634
+ const pipelineDurationMs = startNano !== void 0 ? (event.nanoTime - startNano) / 1e6 : 0;
61635
+ predStart.pipelineStages.push({
61636
+ durationMs: pipelineDurationMs,
61637
+ resultSize: event.resultSize ?? 0,
61638
+ counts: event.counts ?? [],
61639
+ duplicationPercentages: event.duplicationPercentages
61640
+ });
61537
61641
  }
61538
61642
  }
61539
61643
  break;
@@ -61551,7 +61655,9 @@ function parseRawEvaluatorLog(logPath) {
61551
61655
  resultSize: event.resultSize,
61552
61656
  pipelineCount: predStart.pipelineCount > 0 ? predStart.pipelineCount : void 0,
61553
61657
  evaluationStrategy: predStart.predicateType,
61554
- dependencies: predStart.dependencies
61658
+ dependencies: predStart.dependencies,
61659
+ raSteps: predStart.raSteps,
61660
+ pipelineStages: predStart.pipelineStages.length > 0 ? predStart.pipelineStages : void 0
61555
61661
  };
61556
61662
  const qEid = predStart.queryCausingWork ?? firstQueryEventId;
61557
61663
  if (qEid !== void 0) {
@@ -61591,16 +61697,17 @@ function parseRawEvaluatorLog(logPath) {
61591
61697
  codeqlVersion,
61592
61698
  logFormat: "raw",
61593
61699
  queries,
61594
- totalEvents: events.length
61700
+ totalEvents
61595
61701
  };
61596
61702
  }
61597
- function parseSummaryLog(logPath) {
61598
- const events = parseJsonObjects(logPath);
61703
+ async function processSummaryEvents(events) {
61599
61704
  let codeqlVersion;
61600
61705
  const queryPredicatesMap = /* @__PURE__ */ new Map();
61601
61706
  const queryTotalMs = /* @__PURE__ */ new Map();
61602
61707
  const queryCacheHits = /* @__PURE__ */ new Map();
61603
- for (const event of events) {
61708
+ let totalEvents = 0;
61709
+ for await (const event of events) {
61710
+ totalEvents++;
61604
61711
  if (event.summaryLogVersion !== void 0) {
61605
61712
  codeqlVersion = event.codeqlVersion;
61606
61713
  continue;
@@ -61617,6 +61724,11 @@ function parseSummaryLog(logPath) {
61617
61724
  const queryName = event.queryCausingWork || "unknown";
61618
61725
  const deps = event.dependencies;
61619
61726
  const pipelineRuns = event.pipelineRuns;
61727
+ const raObj = event.ra;
61728
+ let raSteps;
61729
+ if (typeof raObj === "string" && raObj.length > 0) {
61730
+ raSteps = raObj.replace(/\r\n/g, "\n").split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
61731
+ }
61620
61732
  const profile = {
61621
61733
  predicateName,
61622
61734
  position: event.position,
@@ -61624,7 +61736,8 @@ function parseSummaryLog(logPath) {
61624
61736
  resultSize: event.resultSize,
61625
61737
  pipelineCount: pipelineRuns,
61626
61738
  evaluationStrategy: strategy,
61627
- dependencies: deps ? Object.keys(deps) : []
61739
+ dependencies: deps ? Object.keys(deps) : [],
61740
+ raSteps
61628
61741
  };
61629
61742
  if (event.isCached === true || strategy === "CACHEHIT") {
61630
61743
  queryCacheHits.set(
@@ -61657,143 +61770,142 @@ function parseSummaryLog(logPath) {
61657
61770
  codeqlVersion,
61658
61771
  logFormat: "summary",
61659
61772
  queries,
61660
- totalEvents: events.length
61773
+ totalEvents
61661
61774
  };
61662
61775
  }
61663
- function parseEvaluatorLog(logPath) {
61664
- const events = parseJsonObjects(logPath);
61665
- if (events.length === 0) {
61776
+ async function parseEvaluatorLog(logPath) {
61777
+ const stream = streamJsonObjects(logPath);
61778
+ const iterator = stream[Symbol.asyncIterator]();
61779
+ const first = await iterator.next();
61780
+ if (first.done) {
61666
61781
  return {
61667
61782
  logFormat: "raw",
61668
61783
  queries: [],
61669
61784
  totalEvents: 0
61670
61785
  };
61671
61786
  }
61672
- const format = detectLogFormat(events[0]);
61787
+ const firstEvent = first.value;
61788
+ const format = detectLogFormat(firstEvent);
61789
+ async function* prependFirst() {
61790
+ yield firstEvent;
61791
+ for (; ; ) {
61792
+ const next = await iterator.next();
61793
+ if (next.done) break;
61794
+ yield next.value;
61795
+ }
61796
+ }
61673
61797
  if (format === "raw") {
61674
- return parseRawEvaluatorLog(logPath);
61798
+ return processRawEvents(prependFirst());
61675
61799
  }
61676
- return parseSummaryLog(logPath);
61800
+ return processSummaryEvents(prependFirst());
61677
61801
  }
61678
61802
 
61679
61803
  // src/tools/codeql/profile-codeql-query-from-logs.ts
61680
61804
  init_logger();
61681
- function formatAsJson(profile) {
61682
- return JSON.stringify(profile, null, 2);
61805
+ function getTopPredicates(predicates, topN) {
61806
+ return [...predicates].sort((a, b) => b.durationMs - a.durationMs).slice(0, topN);
61683
61807
  }
61684
- function formatAsMermaid(profile, topN) {
61808
+ function buildDetailFile(profile, topN) {
61685
61809
  const lines = [];
61686
- lines.push("```mermaid");
61687
- lines.push("graph TD");
61810
+ const lineIndex = /* @__PURE__ */ new Map();
61811
+ lines.push("# CodeQL Evaluator Profile \u2014 Predicate Detail");
61812
+ lines.push(`# Log format: ${profile.logFormat}`);
61813
+ if (profile.codeqlVersion) {
61814
+ lines.push(`# CodeQL version: ${profile.codeqlVersion}`);
61815
+ }
61816
+ lines.push(`# Use read_file with line ranges from the JSON response to access individual predicates.`);
61688
61817
  lines.push("");
61689
- if (profile.queries.length <= 1) {
61690
- const query = profile.queries[0] ?? {
61691
- queryName: "unknown",
61692
- totalDurationMs: 0,
61693
- predicates: [],
61694
- predicateCount: 0,
61695
- cacheHits: 0
61696
- };
61697
- const qLabel = sanitizeMermaid(basename4(query.queryName));
61698
- lines.push(
61699
- ` QUERY["${qLabel}<br/>Total: ${query.totalDurationMs.toFixed(2)}ms<br/>Predicates: ${query.predicateCount}"]`
61700
- );
61818
+ for (let qIdx = 0; qIdx < profile.queries.length; qIdx++) {
61819
+ const query = profile.queries[qIdx];
61820
+ const qName = basename4(query.queryName);
61821
+ lines.push(`== Query: ${qName} ==`);
61822
+ lines.push(` Total: ${query.totalDurationMs.toFixed(2)}ms | Predicates evaluated: ${query.predicateCount} | Cache hits: ${query.cacheHits}`);
61701
61823
  lines.push("");
61702
- const topPredicates = getTopPredicates(query.predicates, topN);
61703
- topPredicates.forEach((pred, idx) => {
61704
- const nodeId = `P${idx}`;
61705
- const name = sanitizeMermaid(pred.predicateName).substring(0, 50);
61706
- const dur = pred.durationMs.toFixed(2);
61707
- const size = pred.resultSize !== void 0 ? String(pred.resultSize) : "?";
61708
- lines.push(
61709
- ` ${nodeId}["${name}<br/>${dur}ms | ${size} results"]`
61710
- );
61711
- });
61712
- lines.push("");
61713
- topPredicates.forEach((_pred, idx) => {
61714
- lines.push(` QUERY --> P${idx}`);
61824
+ const evalOrderMap = /* @__PURE__ */ new Map();
61825
+ query.predicates.forEach((pred, idx) => {
61826
+ evalOrderMap.set(pred, idx + 1);
61715
61827
  });
61716
- } else {
61717
- lines.push(
61718
- ` ROOT["Evaluation Log<br/>${profile.queries.length} queries"]`
61719
- );
61720
- lines.push("");
61721
- profile.queries.forEach((query, qIdx) => {
61722
- const qNodeId = `Q${qIdx}`;
61723
- const qLabel = sanitizeMermaid(basename4(query.queryName));
61724
- lines.push(
61725
- ` ${qNodeId}["${qLabel}<br/>${query.totalDurationMs.toFixed(2)}ms<br/>Predicates: ${query.predicateCount}"]`
61726
- );
61727
- lines.push(` ROOT --> ${qNodeId}`);
61728
- const topPredicates = getTopPredicates(query.predicates, topN);
61729
- topPredicates.forEach((pred, pIdx) => {
61730
- const nodeId = `Q${qIdx}P${pIdx}`;
61731
- const name = sanitizeMermaid(pred.predicateName).substring(0, 50);
61732
- const dur = pred.durationMs.toFixed(2);
61733
- const size = pred.resultSize !== void 0 ? String(pred.resultSize) : "?";
61734
- lines.push(
61735
- ` ${nodeId}["${name}<br/>${dur}ms | ${size} results"]`
61736
- );
61737
- lines.push(` ${qNodeId} --> ${nodeId}`);
61738
- });
61828
+ const top = getTopPredicates(query.predicates, topN);
61829
+ for (const pred of top) {
61830
+ const startLine = lines.length + 1;
61831
+ lines.push(`--- ${pred.predicateName} ---`);
61832
+ lines.push(` Eval order: ${evalOrderMap.get(pred) ?? "?"} of ${query.predicateCount}`);
61833
+ lines.push(` Duration: ${pred.durationMs.toFixed(2)} ms`);
61834
+ lines.push(` Result: ${pred.resultSize ?? "?"} tuples`);
61835
+ lines.push(` Strategy: ${pred.evaluationStrategy ?? "unknown"}`);
61836
+ if (pred.position) {
61837
+ lines.push(` Position: ${pred.position}`);
61838
+ }
61839
+ if (pred.dependencies.length > 0) {
61840
+ lines.push(` Dependencies (${pred.dependencies.length}):`);
61841
+ for (const dep of pred.dependencies) {
61842
+ lines.push(` - ${dep}`);
61843
+ }
61844
+ }
61845
+ if (pred.raSteps && pred.raSteps.length > 0) {
61846
+ lines.push(` RA operations (${pred.raSteps.length} steps):`);
61847
+ for (const step of pred.raSteps) {
61848
+ lines.push(` ${step}`);
61849
+ }
61850
+ }
61851
+ if (pred.pipelineStages && pred.pipelineStages.length > 0) {
61852
+ lines.push(` Pipeline stages (${pred.pipelineStages.length}):`);
61853
+ for (let pIdx = 0; pIdx < pred.pipelineStages.length; pIdx++) {
61854
+ const stage = pred.pipelineStages[pIdx];
61855
+ const countsStr = stage.counts.length > 0 ? `counts=[${stage.counts.join(", ")}]` : "counts=[]";
61856
+ lines.push(` [${pIdx + 1}] ${stage.durationMs.toFixed(2)}ms -> ${stage.resultSize} tuples (${countsStr})`);
61857
+ }
61858
+ }
61739
61859
  lines.push("");
61740
- });
61860
+ const endLine = lines.length;
61861
+ const key = `${qIdx}:${pred.predicateName}`;
61862
+ lineIndex.set(key, { start: startLine, end: endLine });
61863
+ }
61741
61864
  }
61742
- lines.push("");
61743
- lines.push(
61744
- " classDef default fill:#e1f5ff,stroke:#333,stroke-width:2px"
61745
- );
61746
- lines.push(
61747
- " classDef query fill:#ffe1e1,stroke:#333,stroke-width:3px"
61748
- );
61749
- lines.push(" class QUERY query");
61750
- lines.push("```");
61751
- return lines.join("\n");
61752
- }
61753
- function sanitizeMermaid(text) {
61754
- return text.replace(/[<>"]/g, "");
61865
+ return { content: lines.join("\n"), lineIndex };
61755
61866
  }
61756
- function getTopPredicates(predicates, topN) {
61757
- return [...predicates].sort((a, b) => b.durationMs - a.durationMs).slice(0, topN);
61758
- }
61759
- function buildTextSummary(profile, topN, outputFiles) {
61760
- const sections = [];
61761
- sections.push("Query log profiling completed successfully!");
61762
- sections.push("");
61763
- sections.push("Output Files:");
61764
- for (const f of outputFiles) {
61765
- sections.push(` - ${f}`);
61766
- }
61767
- sections.push("");
61768
- sections.push(`Log Format: ${profile.logFormat}`);
61769
- if (profile.codeqlVersion) {
61770
- sections.push(`CodeQL Version: ${profile.codeqlVersion}`);
61771
- }
61772
- sections.push(`Total Events: ${profile.totalEvents}`);
61773
- sections.push(`Queries: ${profile.queries.length}`);
61774
- for (const query of profile.queries) {
61775
- sections.push("");
61776
- sections.push(`--- ${basename4(query.queryName)} ---`);
61777
- sections.push(` Total Duration: ${query.totalDurationMs.toFixed(2)} ms`);
61778
- sections.push(` Predicates Evaluated: ${query.predicateCount}`);
61779
- sections.push(` Cache Hits: ${query.cacheHits}`);
61867
+ function buildInlineResponse(profile, topN, detailLineIndex, files) {
61868
+ const queries = profile.queries.map((query, qIdx) => {
61869
+ const evalOrderMap = /* @__PURE__ */ new Map();
61870
+ query.predicates.forEach((pred, idx) => {
61871
+ evalOrderMap.set(pred, idx + 1);
61872
+ });
61780
61873
  const top = getTopPredicates(query.predicates, topN);
61781
- if (top.length > 0) {
61782
- sections.push(` Top ${top.length} Most Expensive Predicates:`);
61783
- top.forEach((pred, idx) => {
61784
- const sizeStr = pred.resultSize !== void 0 ? `, ${pred.resultSize} results` : "";
61785
- sections.push(
61786
- ` ${idx + 1}. ${pred.predicateName} (${pred.durationMs.toFixed(2)} ms${sizeStr})`
61787
- );
61788
- });
61789
- }
61790
- }
61791
- return sections.join("\n");
61874
+ return {
61875
+ queryName: query.queryName,
61876
+ totalDurationMs: query.totalDurationMs,
61877
+ predicateCount: query.predicateCount,
61878
+ cacheHits: query.cacheHits,
61879
+ slowestPredicates: top.map((pred) => {
61880
+ const key = `${qIdx}:${pred.predicateName}`;
61881
+ const detailLines = detailLineIndex.get(key) ?? { start: 0, end: 0 };
61882
+ return {
61883
+ evalOrder: evalOrderMap.get(pred) ?? 0,
61884
+ name: pred.predicateName,
61885
+ durationMs: pred.durationMs,
61886
+ resultSize: pred.resultSize,
61887
+ strategy: pred.evaluationStrategy,
61888
+ dependencyCount: pred.dependencies.length,
61889
+ pipelineCount: pred.pipelineCount,
61890
+ detailLines
61891
+ };
61892
+ })
61893
+ };
61894
+ });
61895
+ return {
61896
+ logFormat: profile.logFormat,
61897
+ codeqlVersion: profile.codeqlVersion,
61898
+ totalEvents: profile.totalEvents,
61899
+ queries,
61900
+ detailFile: files.detailFile,
61901
+ fullProfileJson: files.fullProfileJson,
61902
+ evaluatorLog: files.evaluatorLog
61903
+ };
61792
61904
  }
61793
61905
  function registerProfileCodeQLQueryFromLogsTool(server) {
61794
61906
  server.tool(
61795
61907
  "profile_codeql_query_from_logs",
61796
- "Parse CodeQL query evaluation logs into a performance profile without re-running the query. Works with logs from codeql query run, codeql database analyze, or vscode-codeql query history.",
61908
+ "Parse CodeQL evaluator logs into a structured performance profile. Returns compact JSON with per-query summaries and top-N slowest predicates (name, duration, result size, eval order, dependency count). Full RA operations, pipeline-stage tuple progressions, and dependency lists are written to a line-indexed detail file \u2014 each predicate includes detailLines: {start, end} for targeted read_file access to its full analysis. Works with logs from codeql query run, codeql database analyze, or vscode-codeql.",
61797
61909
  {
61798
61910
  evaluatorLog: external_exports.string().describe(
61799
61911
  "Path to evaluator-log.jsonl or evaluator-log.summary.jsonl"
@@ -61802,7 +61914,7 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61802
61914
  "Directory to write profile output files (defaults to same directory as log)"
61803
61915
  ),
61804
61916
  topN: external_exports.number().optional().describe(
61805
- "Number of most expensive predicates to highlight (default: 20)"
61917
+ "Number of slowest predicates to include per query (default: 20)"
61806
61918
  )
61807
61919
  },
61808
61920
  async (params) => {
@@ -61814,51 +61926,42 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61814
61926
  content: [
61815
61927
  {
61816
61928
  type: "text",
61817
- text: `Evaluator log not found at: ${evaluatorLog}`
61929
+ text: JSON.stringify({ error: `Evaluator log not found at: ${evaluatorLog}` })
61818
61930
  }
61819
61931
  ],
61820
61932
  isError: true
61821
61933
  };
61822
61934
  }
61823
61935
  logger.info(`Parsing evaluator log from: ${evaluatorLog}`);
61824
- const profile = parseEvaluatorLog(evaluatorLog);
61936
+ const profile = await parseEvaluatorLog(evaluatorLog);
61825
61937
  const profileOutputDir = outputDir ?? dirname6(evaluatorLog);
61826
61938
  mkdirSync6(profileOutputDir, { recursive: true });
61827
- const jsonPath = join11(
61828
- profileOutputDir,
61829
- "query-evaluation-profile.json"
61830
- );
61831
- writeFileSync3(jsonPath, formatAsJson(profile));
61832
- logger.info(`Profile JSON written to: ${jsonPath}`);
61833
- const mdPath = join11(
61834
- profileOutputDir,
61835
- "query-evaluation-profile.md"
61836
- );
61837
- writeFileSync3(mdPath, formatAsMermaid(profile, effectiveTopN));
61838
- logger.info(`Profile Mermaid diagram written to: ${mdPath}`);
61839
- const outputFilesList = [
61840
- `Profile JSON: ${jsonPath}`,
61841
- `Profile Mermaid: ${mdPath}`,
61842
- `Evaluator Log: ${evaluatorLog}`
61843
- ];
61844
- const responseText = buildTextSummary(
61845
- profile,
61846
- effectiveTopN,
61847
- outputFilesList
61848
- );
61939
+ const jsonPath = join11(profileOutputDir, "query-evaluation-profile.json");
61940
+ writeFileSync3(jsonPath, JSON.stringify(profile, null, 2));
61941
+ logger.info(`Full profile JSON written to: ${jsonPath}`);
61942
+ const { content: detailContent, lineIndex } = buildDetailFile(profile, effectiveTopN);
61943
+ const detailPath = join11(profileOutputDir, "query-evaluation-detail.txt");
61944
+ writeFileSync3(detailPath, detailContent);
61945
+ logger.info(`Detail file written to: ${detailPath}`);
61946
+ const response = buildInlineResponse(profile, effectiveTopN, lineIndex, {
61947
+ detailFile: detailPath,
61948
+ fullProfileJson: jsonPath,
61949
+ evaluatorLog
61950
+ });
61849
61951
  return {
61850
- content: [{ type: "text", text: responseText }]
61952
+ content: [
61953
+ { type: "text", text: JSON.stringify(response) }
61954
+ ]
61851
61955
  };
61852
61956
  } catch (error2) {
61853
- logger.error(
61854
- "Error profiling CodeQL query from logs:",
61855
- error2
61856
- );
61957
+ logger.error("Error profiling CodeQL query from logs:", error2);
61857
61958
  return {
61858
61959
  content: [
61859
61960
  {
61860
61961
  type: "text",
61861
- text: `Failed to profile query from logs: ${error2 instanceof Error ? error2.message : String(error2)}`
61962
+ text: JSON.stringify({
61963
+ error: `Failed to profile query from logs: ${error2 instanceof Error ? error2.message : String(error2)}`
61964
+ })
61862
61965
  }
61863
61966
  ],
61864
61967
  isError: true
@@ -61871,76 +61974,114 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61871
61974
  // src/tools/codeql/profile-codeql-query.ts
61872
61975
  init_cli_executor();
61873
61976
  init_logger();
61874
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync9, existsSync as existsSync10 } from "fs";
61977
+ import { writeFileSync as writeFileSync4, existsSync as existsSync10 } from "fs";
61978
+ import { createReadStream as createReadStream2 } from "fs";
61875
61979
  import { join as join12, dirname as dirname7, basename as basename5 } from "path";
61876
61980
  import { mkdirSync as mkdirSync7 } from "fs";
61877
- function parseEvaluatorLog2(logPath) {
61878
- const logContent = readFileSync9(logPath, "utf-8");
61879
- const jsonObjects = logContent.split("\n\n").filter((s) => s.trim());
61880
- const events = jsonObjects.map((obj) => {
61881
- try {
61882
- return JSON.parse(obj);
61883
- } catch (_error) {
61884
- logger.warn(`Failed to parse evaluator log object: ${obj.substring(0, 100)}...`);
61885
- return null;
61886
- }
61887
- }).filter((event) => event !== null);
61981
+ import { createInterface as createInterface2 } from "readline";
61982
+ async function parseEvaluatorLog2(logPath) {
61888
61983
  const pipelineMap = /* @__PURE__ */ new Map();
61889
61984
  const predicateNameToEventId = /* @__PURE__ */ new Map();
61985
+ const predicateStartNanoTimes = /* @__PURE__ */ new Map();
61890
61986
  let queryName = "";
61891
61987
  let queryStartTime = 0;
61892
61988
  let queryEndTime = 0;
61893
- for (const event of events) {
61894
- switch (event.type) {
61895
- case "QUERY_STARTED":
61896
- queryName = event.queryName || "";
61897
- queryStartTime = event.nanoTime;
61898
- break;
61899
- case "QUERY_COMPLETED":
61900
- queryEndTime = event.nanoTime;
61901
- break;
61902
- case "PREDICATE_STARTED": {
61903
- const predicateName = event.predicateName;
61904
- const position = event.position;
61905
- const predicateType = event.predicateType;
61906
- const dependencies = event.dependencies;
61907
- predicateNameToEventId.set(predicateName, event.eventId);
61908
- const dependencyEventIds = [];
61909
- const dependencyNames = [];
61910
- if (dependencies) {
61911
- for (const depName of Object.keys(dependencies)) {
61912
- dependencyNames.push(depName);
61913
- const depEventId = predicateNameToEventId.get(depName);
61914
- if (depEventId !== void 0) {
61915
- dependencyEventIds.push(depEventId);
61989
+ let totalEvents = 0;
61990
+ const rl = createInterface2({
61991
+ input: createReadStream2(logPath, { encoding: "utf-8" }),
61992
+ crlfDelay: Infinity
61993
+ });
61994
+ let depth = 0;
61995
+ let inString = false;
61996
+ let escape2 = false;
61997
+ const lines = [];
61998
+ for await (const line of rl) {
61999
+ for (const ch of line) {
62000
+ if (escape2) {
62001
+ escape2 = false;
62002
+ continue;
62003
+ }
62004
+ if (ch === "\\" && inString) {
62005
+ escape2 = true;
62006
+ continue;
62007
+ }
62008
+ if (ch === '"') {
62009
+ inString = !inString;
62010
+ continue;
62011
+ }
62012
+ if (inString) continue;
62013
+ if (ch === "{") depth++;
62014
+ if (ch === "}") depth--;
62015
+ }
62016
+ if (depth > 0 || depth === 0 && line.trim().length > 0 && lines.length > 0) {
62017
+ lines.push(line);
62018
+ } else if (depth === 0 && lines.length === 0 && line.trim().length > 0) {
62019
+ lines.push(line);
62020
+ }
62021
+ if (depth === 0 && lines.length > 0) {
62022
+ const objStr = lines.join("\n");
62023
+ lines.length = 0;
62024
+ inString = false;
62025
+ escape2 = false;
62026
+ if (objStr.trim().length === 0) continue;
62027
+ let event;
62028
+ try {
62029
+ event = JSON.parse(objStr);
62030
+ } catch {
62031
+ logger.warn(`Failed to parse evaluator log object: ${objStr.substring(0, 100)}...`);
62032
+ continue;
62033
+ }
62034
+ totalEvents++;
62035
+ switch (event.type) {
62036
+ case "QUERY_STARTED":
62037
+ queryName = event.queryName || "";
62038
+ queryStartTime = event.nanoTime;
62039
+ break;
62040
+ case "QUERY_COMPLETED":
62041
+ queryEndTime = event.nanoTime;
62042
+ break;
62043
+ case "PREDICATE_STARTED": {
62044
+ const predicateName = event.predicateName;
62045
+ const position = event.position;
62046
+ const predicateType = event.predicateType;
62047
+ const dependencies = event.dependencies;
62048
+ predicateNameToEventId.set(predicateName, event.eventId);
62049
+ predicateStartNanoTimes.set(event.eventId, event.nanoTime);
62050
+ const dependencyEventIds = [];
62051
+ const dependencyNames = [];
62052
+ if (dependencies) {
62053
+ for (const depName of Object.keys(dependencies)) {
62054
+ dependencyNames.push(depName);
62055
+ const depEventId = predicateNameToEventId.get(depName);
62056
+ if (depEventId !== void 0) {
62057
+ dependencyEventIds.push(depEventId);
62058
+ }
61916
62059
  }
61917
62060
  }
62061
+ pipelineMap.set(event.eventId, {
62062
+ eventId: event.eventId,
62063
+ name: predicateName,
62064
+ position,
62065
+ type: predicateType,
62066
+ startTime: event.nanoTime,
62067
+ dependencies: dependencyNames,
62068
+ dependencyEventIds
62069
+ });
62070
+ break;
61918
62071
  }
61919
- pipelineMap.set(event.eventId, {
61920
- eventId: event.eventId,
61921
- name: predicateName,
61922
- position,
61923
- type: predicateType,
61924
- startTime: event.nanoTime,
61925
- dependencies: dependencyNames,
61926
- dependencyEventIds
61927
- });
61928
- break;
61929
- }
61930
- case "PREDICATE_COMPLETED": {
61931
- const startEventId = event.startEvent;
61932
- const pipelineInfo = pipelineMap.get(startEventId);
61933
- if (pipelineInfo) {
61934
- const startEvent = events.find((e) => e.eventId === startEventId);
61935
- if (startEvent) {
61936
- const duration3 = (event.nanoTime - startEvent.nanoTime) / 1e6;
62072
+ case "PREDICATE_COMPLETED": {
62073
+ const startEventId = event.startEvent;
62074
+ const pipelineInfo = pipelineMap.get(startEventId);
62075
+ const startNano = predicateStartNanoTimes.get(startEventId);
62076
+ if (pipelineInfo && startNano !== void 0) {
62077
+ const duration3 = (event.nanoTime - startNano) / 1e6;
61937
62078
  pipelineInfo.endTime = event.nanoTime;
61938
62079
  pipelineInfo.duration = duration3;
61939
62080
  pipelineInfo.resultSize = event.resultSize;
61940
62081
  pipelineInfo.tupleCount = event.tupleCount;
61941
62082
  }
62083
+ break;
61942
62084
  }
61943
- break;
61944
62085
  }
61945
62086
  }
61946
62087
  }
@@ -61949,14 +62090,14 @@ function parseEvaluatorLog2(logPath) {
61949
62090
  return {
61950
62091
  queryName,
61951
62092
  totalDuration,
61952
- totalEvents: events.length,
62093
+ totalEvents,
61953
62094
  pipelines
61954
62095
  };
61955
62096
  }
61956
- function formatAsJson2(profile) {
62097
+ function formatAsJson(profile) {
61957
62098
  return JSON.stringify(profile, null, 2);
61958
62099
  }
61959
- function formatAsMermaid2(profile) {
62100
+ function formatAsMermaid(profile) {
61960
62101
  const lines = [];
61961
62102
  lines.push("```mermaid");
61962
62103
  lines.push("graph TD");
@@ -62063,15 +62204,15 @@ function registerProfileCodeQLQueryTool(server) {
62063
62204
  };
62064
62205
  }
62065
62206
  logger.info(`Parsing evaluator log from: ${logPath}`);
62066
- const profile = parseEvaluatorLog2(logPath);
62207
+ const profile = await parseEvaluatorLog2(logPath);
62067
62208
  const profileOutputDir = outputDir || dirname7(logPath);
62068
62209
  mkdirSync7(profileOutputDir, { recursive: true });
62069
62210
  const jsonPath = join12(profileOutputDir, "query-evaluation-profile.json");
62070
- const jsonContent = formatAsJson2(profile);
62211
+ const jsonContent = formatAsJson(profile);
62071
62212
  writeFileSync4(jsonPath, jsonContent);
62072
62213
  logger.info(`Profile JSON written to: ${jsonPath}`);
62073
62214
  const mdPath = join12(profileOutputDir, "query-evaluation-profile.md");
62074
- const mdContent = formatAsMermaid2(profile);
62215
+ const mdContent = formatAsMermaid(profile);
62075
62216
  writeFileSync4(mdPath, mdContent);
62076
62217
  logger.info(`Profile Mermaid diagram written to: ${mdPath}`);
62077
62218
  const outputFiles = [
@@ -62280,7 +62421,7 @@ function registerQuickEvaluateTool(server) {
62280
62421
 
62281
62422
  // src/tools/codeql/read-database-source.ts
62282
62423
  var import_adm_zip = __toESM(require_adm_zip(), 1);
62283
- import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
62424
+ import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync8, statSync as statSync7 } from "fs";
62284
62425
  import { join as join14, resolve as resolve7 } from "path";
62285
62426
  import { fileURLToPath as fileURLToPath2 } from "url";
62286
62427
  init_logger();
@@ -62297,9 +62438,9 @@ function toFilesystemPath(uri) {
62297
62438
  return uri;
62298
62439
  }
62299
62440
  function* walkDirectory(dir, base = dir) {
62300
- for (const entry of readdirSync6(dir)) {
62441
+ for (const entry of readdirSync7(dir)) {
62301
62442
  const fullPath = join14(dir, entry);
62302
- if (statSync6(fullPath).isDirectory()) {
62443
+ if (statSync7(fullPath).isDirectory()) {
62303
62444
  yield* walkDirectory(fullPath, base);
62304
62445
  } else {
62305
62446
  yield fullPath.slice(base.length).replace(/\\/g, "/").replace(/^\//, "");
@@ -62442,7 +62583,7 @@ Directory contains ${availableEntries.length} entries. Use read_database_source
62442
62583
  );
62443
62584
  }
62444
62585
  const fullPath = join14(srcDirPath, matchedRelative);
62445
- const rawContent = readFileSync10(fullPath, "utf-8");
62586
+ const rawContent = readFileSync8(fullPath, "utf-8");
62446
62587
  const { content, effectiveEnd, effectiveStart, totalLines } = applyLineRange(
62447
62588
  rawContent,
62448
62589
  startLine,
@@ -62601,6 +62742,32 @@ var codeqlResolveDatabaseTool = {
62601
62742
  resultProcessor: defaultCLIResultProcessor
62602
62743
  };
62603
62744
 
62745
+ // src/tools/codeql/resolve-files.ts
62746
+ var codeqlResolveFilesTool = {
62747
+ name: "codeql_resolve_files",
62748
+ description: "Find files in a directory tree, filtered by extension and glob patterns. Useful for discovering QL library files, query files, and other CodeQL-related files within packs or workspaces.",
62749
+ command: "codeql",
62750
+ subcommand: "resolve files",
62751
+ inputSchema: {
62752
+ dir: external_exports.string().describe("The directory to search for files"),
62753
+ "include-extension": external_exports.array(external_exports.string()).optional().describe("Include files with given extensions (e.g., ['.qll', '.ql'])"),
62754
+ include: external_exports.array(external_exports.string()).optional().describe("Glob patterns to include (e.g., ['**/RemoteFlowSource*'])"),
62755
+ exclude: external_exports.array(external_exports.string()).optional().describe("Glob patterns to exclude"),
62756
+ prune: external_exports.array(external_exports.string()).optional().describe("Glob patterns for directories to prune from search"),
62757
+ "also-match": external_exports.array(external_exports.string()).optional().describe("Additional glob filter all results must match"),
62758
+ format: external_exports.enum(["text", "json"]).optional().describe("Output format (default: text)"),
62759
+ "follow-symlinks": external_exports.boolean().optional().describe("Follow symlinks when searching"),
62760
+ additionalArgs: createCodeQLSchemas.additionalArgs()
62761
+ },
62762
+ examples: [
62763
+ "codeql resolve files --include-extension=.qll --format=json -- /path/to/pack",
62764
+ "codeql resolve files --include=**/RemoteFlowSource* -- /path/to/pack",
62765
+ "codeql resolve files --include-extension=.ql --include-extension=.qll -- /path/to/pack",
62766
+ "codeql resolve files --include-extension=.qll --also-match=**/FlowSource* -- /path/to/pack"
62767
+ ],
62768
+ resultProcessor: defaultCLIResultProcessor
62769
+ };
62770
+
62604
62771
  // src/tools/codeql/resolve-languages.ts
62605
62772
  var codeqlResolveLanguagesTool = {
62606
62773
  name: "codeql_resolve_languages",
@@ -62745,6 +62912,255 @@ var codeqlResolveTestsTool = {
62745
62912
  resultProcessor: defaultCLIResultProcessor
62746
62913
  };
62747
62914
 
62915
+ // src/tools/codeql/search-ql-code.ts
62916
+ import { closeSync, createReadStream as createReadStream3, fstatSync, lstatSync, openSync, readdirSync as readdirSync8, readFileSync as readFileSync9, realpathSync } from "fs";
62917
+ import { basename as basename6, extname as extname2, join as join15, resolve as resolve9 } from "path";
62918
+ import { createInterface as createInterface3 } from "readline";
62919
+ init_logger();
62920
+ var MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
62921
+ var MAX_FILES_TRAVERSED = 1e4;
62922
+ var MAX_CONTEXT_LINES = 50;
62923
+ var MAX_MAX_RESULTS = 1e4;
62924
+ var SKIP_DIRS2 = /* @__PURE__ */ new Set([".codeql", "node_modules", ".git"]);
62925
+ function collectFiles(paths, extensions, fileCount) {
62926
+ const files = [];
62927
+ const visitedDirs = /* @__PURE__ */ new Set();
62928
+ function walk(p) {
62929
+ if (fileCount.value >= MAX_FILES_TRAVERSED) return;
62930
+ let stat;
62931
+ try {
62932
+ stat = lstatSync(p);
62933
+ } catch {
62934
+ return;
62935
+ }
62936
+ if (stat.isSymbolicLink()) return;
62937
+ if (stat.isFile()) {
62938
+ if (extensions.length === 0 || extensions.includes(extname2(p))) {
62939
+ files.push(p);
62940
+ }
62941
+ fileCount.value++;
62942
+ } else if (stat.isDirectory()) {
62943
+ if (SKIP_DIRS2.has(basename6(p))) return;
62944
+ let realPath;
62945
+ try {
62946
+ realPath = realpathSync(p);
62947
+ } catch {
62948
+ return;
62949
+ }
62950
+ if (visitedDirs.has(realPath)) return;
62951
+ visitedDirs.add(realPath);
62952
+ let entries;
62953
+ try {
62954
+ entries = readdirSync8(p);
62955
+ } catch {
62956
+ return;
62957
+ }
62958
+ for (const entry of entries) {
62959
+ if (fileCount.value >= MAX_FILES_TRAVERSED) return;
62960
+ walk(join15(p, entry));
62961
+ }
62962
+ }
62963
+ }
62964
+ for (const p of paths) {
62965
+ if (fileCount.value >= MAX_FILES_TRAVERSED) break;
62966
+ walk(resolve9(p));
62967
+ }
62968
+ return files;
62969
+ }
62970
+ async function searchFile(filePath, regex, contextLines, maxCollect) {
62971
+ let fd;
62972
+ try {
62973
+ fd = openSync(filePath, "r");
62974
+ } catch {
62975
+ return { matches: [], totalCount: 0 };
62976
+ }
62977
+ let size;
62978
+ try {
62979
+ size = fstatSync(fd).size;
62980
+ } catch {
62981
+ try {
62982
+ closeSync(fd);
62983
+ } catch {
62984
+ }
62985
+ return { matches: [], totalCount: 0 };
62986
+ }
62987
+ if (size > MAX_FILE_SIZE_BYTES) {
62988
+ return searchFileStreaming(filePath, regex, contextLines, maxCollect, fd);
62989
+ }
62990
+ let content;
62991
+ try {
62992
+ content = readFileSync9(fd, "utf-8");
62993
+ } catch {
62994
+ try {
62995
+ closeSync(fd);
62996
+ } catch {
62997
+ }
62998
+ return { matches: [], totalCount: 0 };
62999
+ }
63000
+ try {
63001
+ closeSync(fd);
63002
+ } catch {
63003
+ }
63004
+ const lines = content.replace(/\r\n/g, "\n").split("\n");
63005
+ const matches = [];
63006
+ let totalCount = 0;
63007
+ for (let i = 0; i < lines.length; i++) {
63008
+ if (regex.test(lines[i])) {
63009
+ totalCount++;
63010
+ if (matches.length < maxCollect) {
63011
+ const match = {
63012
+ filePath,
63013
+ lineNumber: i + 1,
63014
+ lineContent: lines[i]
63015
+ };
63016
+ if (contextLines > 0) {
63017
+ const beforeStart = Math.max(0, i - contextLines);
63018
+ const afterEnd = Math.min(lines.length - 1, i + contextLines);
63019
+ match.contextBefore = lines.slice(beforeStart, i);
63020
+ match.contextAfter = lines.slice(i + 1, afterEnd + 1);
63021
+ }
63022
+ matches.push(match);
63023
+ }
63024
+ }
63025
+ }
63026
+ return { matches, totalCount };
63027
+ }
63028
+ async function searchFileStreaming(filePath, regex, contextLines, maxCollect, fd) {
63029
+ const matches = [];
63030
+ const recentLines = [];
63031
+ const pending = [];
63032
+ let lineNumber = 0;
63033
+ let totalCount = 0;
63034
+ let rl;
63035
+ try {
63036
+ const streamOpts = { encoding: "utf-8" };
63037
+ if (fd !== void 0) {
63038
+ streamOpts.fd = fd;
63039
+ streamOpts.autoClose = true;
63040
+ streamOpts.start = 0;
63041
+ }
63042
+ rl = createInterface3({
63043
+ input: createReadStream3(filePath, streamOpts),
63044
+ crlfDelay: Infinity
63045
+ });
63046
+ } catch {
63047
+ if (fd !== void 0) {
63048
+ try {
63049
+ closeSync(fd);
63050
+ } catch {
63051
+ }
63052
+ }
63053
+ return { matches: [], totalCount: 0 };
63054
+ }
63055
+ for await (const line of rl) {
63056
+ lineNumber++;
63057
+ for (const p of pending) {
63058
+ if (p.afterNeeded > 0) {
63059
+ p.match.contextAfter.push(line);
63060
+ p.afterNeeded--;
63061
+ }
63062
+ }
63063
+ while (pending.length > 0 && pending[0].afterNeeded === 0) {
63064
+ pending.shift();
63065
+ }
63066
+ if (regex.test(line)) {
63067
+ totalCount++;
63068
+ if (matches.length < maxCollect) {
63069
+ const match = {
63070
+ filePath,
63071
+ lineNumber,
63072
+ lineContent: line
63073
+ };
63074
+ if (contextLines > 0) {
63075
+ match.contextBefore = recentLines.slice(-contextLines);
63076
+ match.contextAfter = [];
63077
+ pending.push({ match, afterNeeded: contextLines });
63078
+ }
63079
+ matches.push(match);
63080
+ }
63081
+ }
63082
+ if (contextLines > 0) {
63083
+ recentLines.push(line);
63084
+ if (recentLines.length > contextLines) {
63085
+ recentLines.shift();
63086
+ }
63087
+ }
63088
+ }
63089
+ return { matches, totalCount };
63090
+ }
63091
+ async function searchQlCode(params) {
63092
+ const {
63093
+ pattern,
63094
+ paths,
63095
+ includeExtensions = [".ql", ".qll"],
63096
+ caseSensitive = true,
63097
+ contextLines: rawContextLines = 0,
63098
+ maxResults: rawMaxResults = 100
63099
+ } = params;
63100
+ const contextLines = Math.min(Math.max(0, Math.floor(rawContextLines)), MAX_CONTEXT_LINES);
63101
+ const maxResults = Math.min(Math.max(1, Math.floor(rawMaxResults)), MAX_MAX_RESULTS);
63102
+ const flags = caseSensitive ? "" : "i";
63103
+ const regex = new RegExp(pattern, flags);
63104
+ const fileCount = { value: 0 };
63105
+ const filesToSearch = collectFiles(paths, includeExtensions, fileCount);
63106
+ const allMatches = [];
63107
+ let totalMatches = 0;
63108
+ for (const file of filesToSearch) {
63109
+ const remainingSlots = Math.max(0, maxResults - allMatches.length);
63110
+ const { matches: fileMatches, totalCount } = await searchFile(
63111
+ file,
63112
+ regex,
63113
+ contextLines,
63114
+ remainingSlots
63115
+ );
63116
+ totalMatches += totalCount;
63117
+ allMatches.push(...fileMatches);
63118
+ }
63119
+ return {
63120
+ results: allMatches,
63121
+ totalMatches,
63122
+ returnedMatches: allMatches.length,
63123
+ truncated: totalMatches > maxResults,
63124
+ filesSearched: filesToSearch.length
63125
+ };
63126
+ }
63127
+ function registerSearchQlCodeTool(server) {
63128
+ server.tool(
63129
+ "search_ql_code",
63130
+ "Search QL source files (.ql/.qll) for text or regex patterns. Returns structured results with file paths, line numbers, and optional context lines. Use this instead of grep for searching CodeQL source code.",
63131
+ {
63132
+ pattern: external_exports.string().describe("Text or regex pattern to search for (JavaScript regex syntax)"),
63133
+ paths: external_exports.array(external_exports.string()).min(1).describe("Directories or files to search in"),
63134
+ includeExtensions: external_exports.array(external_exports.string()).optional().default([".ql", ".qll"]).describe("File extensions to search (default: ['.ql', '.qll'])"),
63135
+ caseSensitive: external_exports.boolean().optional().default(true).describe("Whether search is case sensitive (default: true)"),
63136
+ contextLines: external_exports.number().int().min(0).max(MAX_CONTEXT_LINES).optional().default(0).describe("Lines of context before and after each match (default: 0, max: 50)"),
63137
+ maxResults: external_exports.number().int().min(1).max(MAX_MAX_RESULTS).optional().default(100).describe("Maximum number of matching lines to return (default: 100, max: 10000)")
63138
+ },
63139
+ async ({ pattern, paths, includeExtensions, caseSensitive, contextLines, maxResults }) => {
63140
+ try {
63141
+ const result = await searchQlCode({
63142
+ pattern,
63143
+ paths,
63144
+ includeExtensions,
63145
+ caseSensitive,
63146
+ contextLines,
63147
+ maxResults
63148
+ });
63149
+ return {
63150
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
63151
+ };
63152
+ } catch (error2) {
63153
+ logger.error("Error in search_ql_code:", error2);
63154
+ const message = error2 instanceof SyntaxError || error2 instanceof Error && error2.message.includes("Invalid regular expression") ? `Invalid regex pattern: ${error2.message}` : `Error: ${error2 instanceof Error ? error2.message : String(error2)}`;
63155
+ return {
63156
+ content: [{ type: "text", text: message }],
63157
+ isError: true
63158
+ };
63159
+ }
63160
+ }
63161
+ );
63162
+ }
63163
+
62748
63164
  // src/tools/codeql/test-accept.ts
62749
63165
  var codeqlTestAcceptTool = {
62750
63166
  name: "codeql_test_accept",
@@ -63015,6 +63431,7 @@ function registerCodeQLTools(server) {
63015
63431
  registerCLITool(server, codeqlQueryFormatTool);
63016
63432
  registerCLITool(server, codeqlQueryRunTool);
63017
63433
  registerCLITool(server, codeqlResolveDatabaseTool);
63434
+ registerCLITool(server, codeqlResolveFilesTool);
63018
63435
  registerCLITool(server, codeqlResolveLanguagesTool);
63019
63436
  registerCLITool(server, codeqlResolveLibraryPathTool);
63020
63437
  registerCLITool(server, codeqlResolveMetadataTool);
@@ -63035,6 +63452,7 @@ function registerCodeQLTools(server) {
63035
63452
  registerQuickEvaluateTool(server);
63036
63453
  registerReadDatabaseSourceTool(server);
63037
63454
  registerRegisterDatabaseTool(server);
63455
+ registerSearchQlCodeTool(server);
63038
63456
  }
63039
63457
 
63040
63458
  // src/resources/dataflow-migration-v1-to-v2.md
@@ -63044,7 +63462,7 @@ var dataflow_migration_v1_to_v2_default = '# Dataflow API Migration: v1 to v2\n\
63044
63462
  var learning_query_basics_default = '# Writing CodeQL Queries\n\nThis resource is a practical reference for writing CodeQL queries using the MCP server\'s tools. It covers query structure, metadata annotations, common QL patterns, compilation, testing, and the file conventions used by the CodeQL test framework.\n\n## Query Structure\n\nEvery CodeQL query has three main clauses:\n\n```ql\n/**\n * @name Descriptive name of what the query finds\n * @description Longer explanation of the vulnerability or pattern\n * @kind problem\n * @problem.severity warning\n * @precision medium\n * @id lang/query-id\n * @tags security\n * correctness\n */\n\nimport language\n\nfrom SourceType source, SinkType sink\nwhere <conditions linking source to sink>\nselect <result expression>, <message string>\n```\n\n### `from` Clause\n\nDeclares typed variables. Each variable ranges over all values of its type in the database:\n\n```ql\nfrom Function f, FunctionCall call\n```\n\n### `where` Clause\n\nFilters the cross-product of `from` variables using predicates:\n\n```ql\nwhere call.getTarget() = f\n and f.getName() = "eval"\n```\n\n### `select` Clause\n\nDefines the output columns. The first expression is the "element" (the location in source code), followed by a message string:\n\n```ql\nselect call, "Call to dangerous function " + f.getName()\n```\n\n## Metadata Annotations\n\nMetadata goes in a QLDoc comment block (`/** ... */`) at the top of the query file:\n\n| Annotation | Required | Description |\n| -------------------- | ---------------------------- | ------------------------------------------------------------ |\n| `@name` | Yes | Short human-readable name |\n| `@description` | Yes | Explanation of the query\'s purpose |\n| `@kind` | Yes | Output format: `problem`, `path-problem`, `table`, `graph` |\n| `@id` | Yes | Unique identifier (e.g., `js/sql-injection`) |\n| `@problem.severity` | For `problem`/`path-problem` | `error`, `warning`, or `recommendation` |\n| `@security-severity` | For security queries | CVSS score (e.g., `8.8`) |\n| `@precision` | Recommended | `very-high`, `high`, `medium`, or `low` |\n| `@tags` | Recommended | Categories like `security`, `correctness`, `maintainability` |\n\nUse `codeql_resolve_metadata` to extract and validate a query\'s metadata.\n\n## Common `@kind` Values\n\n- **`problem`** \u2014 Reports a single location with a message. Use `select element, message`.\n- **`path-problem`** \u2014 Reports a source-to-sink data flow path. Requires a `PathGraph` import and `select sink, source, sink, message`.\n- **`table`** \u2014 Generic tabular output (no alert interpretation).\n- **`graph`** \u2014 Structural output (AST, CFG, call graphs). Used by `PrintAST`, `PrintCFG`, `CallGraphFrom`, `CallGraphTo` tool queries.\n\n## Common QL Patterns\n\n### Predicate Definition\n\n```ql\npredicate isUserInput(DataFlow::Node node) {\n exists(Parameter p | p = node.asParameter() |\n p.getFunction().isPublic()\n )\n}\n```\n\n### Class Definition\n\n```ql\nclass DangerousCall extends MethodCall {\n DangerousCall() {\n this.getMethodName() = ["exec", "eval", "system"]\n }\n}\n```\n\n### Existential Quantifier (`exists`)\n\n```ql\nwhere exists(Assignment a | a.getLhs() = var and a.getRhs() instanceof NullLiteral)\n```\n\n### Aggregates\n\n```ql\nselect f, count(FunctionCall call | call.getTarget() = f) as callCount\n order by callCount desc\n```\n\n## Taint Tracking / Data Flow Configuration (v2 API)\n\n```ql\nmodule MyFlowConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n // define sources\n }\n\n predicate isSink(DataFlow::Node sink) {\n // define sinks\n }\n\n predicate isBarrier(DataFlow::Node node) {\n // define sanitizers (optional)\n }\n}\n\nmodule MyFlow = TaintTracking::Global<MyFlowConfig>;\n```\n\n## Query Compilation and Validation\n\nUse these tools to validate queries at different fidelity levels:\n\n| Tool | Speed | Fidelity | When to Use |\n| ------------------------ | ------- | ------------------ | ----------------------------------------------------------------- |\n| `validate_codeql_query` | Instant | Heuristic only | Quick structure check (no compilation) |\n| `codeql_query_compile` | Fast | Full compilation | Syntax and type checking |\n| `codeql_lsp_diagnostics` | Fast | Full (single file) | Real-time validation during editing (cannot resolve pack imports) |\n\nTypical workflow:\n\n1. `validate_codeql_query` \u2014 quick structural check\n2. `codeql_query_compile` with `checkOnly: true` \u2014 full compilation\n3. `codeql_lsp_diagnostics` \u2014 interactive feedback during editing\n\n## Test File Conventions\n\nCodeQL query tests use this directory layout:\n\n```text\npack-root/\n\u251C\u2500\u2500 src/\n\u2502 \u251C\u2500\u2500 codeql-pack.yml # Source pack\n\u2502 \u2514\u2500\u2500 MyQuery/\n\u2502 \u2514\u2500\u2500 MyQuery.ql # The query\n\u2514\u2500\u2500 test/\n \u251C\u2500\u2500 codeql-pack.yml # Test pack\n \u2514\u2500\u2500 MyQuery/\n \u251C\u2500\u2500 MyQuery.qlref # Points to ../../src/MyQuery/MyQuery.ql\n \u251C\u2500\u2500 test.js # Test source code (language-appropriate)\n \u2514\u2500\u2500 MyQuery.expected # Expected query output\n```\n\n- **`.qlref` file**: Contains the relative path from the test pack\'s `src/` directory to the query file.\n- **`.expected` file**: Contains the expected output of running the query against the test code. Use `codeql_test_accept` to generate or update this file.\n- **Test source code**: Write code with both positive cases (should trigger the query) and negative cases (should not trigger).\n\n### Running Tests\n\n1. `codeql_test_run` \u2014 run tests and compare against `.expected` files\n2. `codeql_test_accept` \u2014 update `.expected` files when results are verified correct\n3. `codeql_resolve_tests` \u2014 discover and validate test structure\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/queries` \u2014 Bundled tools queries (PrintAST, PrintCFG, CallGraphFrom, CallGraphTo)\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://templates/security` \u2014 Security query templates\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for CodeQL queries\n';
63045
63463
 
63046
63464
  // src/resources/performance-patterns.md
63047
- var performance_patterns_default = '# Performance Optimization Patterns\n\nThis resource describes how to evaluate and improve the performance of CodeQL queries using the MCP server\'s profiling tools. Rather than prescribing generic optimization rules, it focuses on using the `profile_codeql_query_from_logs` tool and the `explain_codeql_query` prompt to make evidence-based performance improvements.\n\n## Primary Performance Tool: `profile_codeql_query_from_logs`\n\nThe `profile_codeql_query_from_logs` tool is the primary means of evaluating the actual performance of a CodeQL query. It parses existing CodeQL evaluator logs into a structured performance profile without re-running the query.\n\n### Workflow\n\n1. **Run the query**: Use `codeql_query_run` with `evaluationOutput` set to a directory path. This generates evaluator log files.\n2. **Generate a log summary**: Use `codeql_generate_log-summary` to create a human-readable summary of the evaluator log.\n3. **Profile**: Use `profile_codeql_query_from_logs` to parse the evaluator log into a structured performance profile identifying expensive predicates, pipeline stages, and tuple counts.\n4. **Identify bottlenecks**: Review the profile output for predicates with high evaluation times or unexpectedly large result sets.\n5. **Refine**: Modify the query to address identified bottlenecks, then re-run and re-profile to verify improvements.\n\n### What the Profile Shows\n\n- **Predicate evaluation times** \u2014 which predicates are the most expensive\n- **Tuple counts** \u2014 how many intermediate results each predicate produces\n- **Pipeline stages** \u2014 the internal evaluation plan chosen by the CodeQL engine\n- **RA (relational algebra) operations** \u2014 join orders, aggregation steps, and recursive evaluations\n\n## Using `explain_codeql_query` for Performance Understanding\n\nThe `explain_codeql_query` prompt generates a detailed explanation of a query, including Mermaid evaluation diagrams that visualize the data flow and evaluation order. This is useful for understanding _why_ a query may be slow before profiling.\n\n## Key Performance Concepts\n\nThe following concepts are relevant when interpreting profiling output. Verify these against actual profiling data rather than applying them blindly.\n\n### Large Intermediate Result Sets\n\nWhen a predicate produces significantly more tuples than expected, it may indicate:\n\n- Missing or insufficiently restrictive filter conditions in the `where` clause\n- A cross-product between two large relations that should be joined more tightly\n\n**How to detect**: Look for predicates in the profile output with high tuple counts relative to their expected output size.\n\n### Recursive Predicate Costs\n\nRecursive predicates (e.g., transitive closures via `+` or `*`) can be expensive when the underlying relation is large. The profiler shows iteration counts and per-iteration tuple growth.\n\n**How to detect**: Look for recursive predicates with many iterations or high per-iteration costs in the profile output.\n\n### Join Order Sensitivity\n\nThe CodeQL evaluator chooses a join order for predicates in the `where` clause. In some cases, the chosen order may not be optimal.\n\n**How to detect**: Look for pipeline stages where a large intermediate result is produced before being filtered down. The profiler shows tuple counts at each stage.\n\n### Improving "Performance" \u2014 Two Dimensions\n\nThe word "performance" for CodeQL queries has two meanings:\n\n1. **Runtime efficiency** \u2014 how fast the query evaluates. Addressed by reducing tuple counts, improving join orders, and simplifying recursive predicates.\n2. **Result quality** \u2014 how accurate the query\'s output is (precision and recall). Addressed by refining source/sink/sanitizer definitions, adding or removing filter conditions, and testing against diverse codebases.\n\nThe `profile_codeql_query_from_logs` tool addresses runtime efficiency. For result quality, use the `run_query_and_summarize_false_positives` prompt and the `sarif_rank_false_positives` / `sarif_rank_true_positives` prompts.\n\n## Performance Review for GitHub Actions CodeQL Scans\n\nWhen reviewing CodeQL performance in the context of GitHub Actions CI/CD scans, key areas to examine include:\n\n### Code Exclusion\n\nExcluding non-essential files from analysis (vendored dependencies, generated code, test files) is one of the most impactful performance improvements. Any interpreted language or compiled language using `build-mode: none` can use a `paths-ignore` array in the CodeQL configuration file to exclude paths.\n\n### Hardware Sizing\n\nRecommended runner sizes based on lines of code:\n\n- Small (< 100K lines): 8 GB RAM, 2 cores\n- Medium (100K\u20131M lines): 16 GB RAM, 4\u20138 cores\n- Large (> 1M lines): 64 GB RAM, 8 cores\n\n### Monorepo Splitting\n\nFor monorepos with multiple independent applications separated by process/network boundaries, consider splitting CodeQL scans by application. This reduces database size and enables parallel scanning via Actions matrix strategies.\n\n## Related Tools and Prompts\n\n| Tool / Prompt | Purpose |\n| ------------------------------------------------ | -------------------------------------------------------- |\n| `profile_codeql_query_from_logs` | Profile from existing evaluator logs (no re-run needed) |\n| `codeql_generate_log-summary` | Generate a human-readable evaluator log summary |\n| `codeql_query_run` | Execute a query (set `evaluationOutput` to capture logs) |\n| `explain_codeql_query` prompt | Understand query evaluation flow with Mermaid diagrams |\n| `run_query_and_summarize_false_positives` prompt | Assess result quality (precision) |\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://learning/query-basics` \u2014 Query structure and compilation tools\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for iterative query improvement\n';
63465
+ var performance_patterns_default = '# Performance Optimization Patterns\n\nThis resource describes how to evaluate and improve the performance of CodeQL queries using the MCP server\'s profiling tools. Rather than prescribing generic optimization rules, it focuses on using the `profile_codeql_query_from_logs` tool and the `explain_codeql_query` prompt to make evidence-based performance improvements.\n\n## Primary Performance Tool: `profile_codeql_query_from_logs`\n\nThe `profile_codeql_query_from_logs` tool is the primary means of evaluating the actual performance of a CodeQL query. It parses existing CodeQL evaluator logs into a structured performance profile without re-running the query.\n\n### Workflow\n\n1. **Run the query**: Use `codeql_query_run` with `evaluationOutput` set to a directory path. This generates evaluator log files.\n2. **Profile**: Use `profile_codeql_query_from_logs` to parse the evaluator log. Returns compact JSON with the slowest predicates (by wall-clock time) and per-predicate metrics. Full RA operations and pipeline-stage tuple progressions are in a line-indexed detail file \u2014 use `read_file` with the `detailLines` ranges from the response to drill into any predicate.\n3. **Identify bottlenecks**: Review the profile JSON for predicates with high evaluation times, tuple count explosions in pipeline stages, or expensive RA operations (large JOINs, cross-products).\n4. **Refine**: Modify the query to address identified bottlenecks, then re-run and re-profile to verify improvements.\n\n### What the Profile Shows\n\n- **Predicate evaluation times** \u2014 which predicates are the most expensive\n- **Tuple counts** \u2014 how many intermediate results each predicate produces\n- **Pipeline stages** \u2014 the internal evaluation plan chosen by the CodeQL engine\n- **RA (relational algebra) operations** \u2014 join orders, aggregation steps, and recursive evaluations\n\n## Using `explain_codeql_query` for Performance Understanding\n\nThe `explain_codeql_query` prompt generates a detailed explanation of a query, including Mermaid evaluation diagrams that visualize the data flow and evaluation order. This is useful for understanding _why_ a query may be slow before profiling.\n\n## Key Performance Concepts\n\nThe following concepts are relevant when interpreting profiling output. Verify these against actual profiling data rather than applying them blindly.\n\n### Large Intermediate Result Sets\n\nWhen a predicate produces significantly more tuples than expected, it may indicate:\n\n- Missing or insufficiently restrictive filter conditions in the `where` clause\n- A cross-product between two large relations that should be joined more tightly\n\n**How to detect**: Look for predicates in the profile output with high tuple counts relative to their expected output size.\n\n### Recursive Predicate Costs\n\nRecursive predicates (e.g., transitive closures via `+` or `*`) can be expensive when the underlying relation is large. The profiler shows iteration counts and per-iteration tuple growth.\n\n**How to detect**: Look for recursive predicates with many iterations or high per-iteration costs in the profile output.\n\n### Join Order Sensitivity\n\nThe CodeQL evaluator chooses a join order for predicates in the `where` clause. In some cases, the chosen order may not be optimal.\n\n**How to detect**: Look for pipeline stages where a large intermediate result is produced before being filtered down. The profiler shows tuple counts at each stage.\n\n### Improving "Performance" \u2014 Two Dimensions\n\nThe word "performance" for CodeQL queries has two meanings:\n\n1. **Runtime efficiency** \u2014 how fast the query evaluates. Addressed by reducing tuple counts, improving join orders, and simplifying recursive predicates.\n2. **Result quality** \u2014 how accurate the query\'s output is (precision and recall). Addressed by refining source/sink/sanitizer definitions, adding or removing filter conditions, and testing against diverse codebases.\n\nThe `profile_codeql_query_from_logs` tool addresses runtime efficiency. For result quality, use the `run_query_and_summarize_false_positives` prompt and the `sarif_rank_false_positives` / `sarif_rank_true_positives` prompts.\n\n## Performance Review for GitHub Actions CodeQL Scans\n\nWhen reviewing CodeQL performance in the context of GitHub Actions CI/CD scans, key areas to examine include:\n\n### Code Exclusion\n\nExcluding non-essential files from analysis (vendored dependencies, generated code, test files) is one of the most impactful performance improvements. Any interpreted language or compiled language using `build-mode: none` can use a `paths-ignore` array in the CodeQL configuration file to exclude paths.\n\n### Hardware Sizing\n\nRecommended runner sizes based on lines of code:\n\n- Small (< 100K lines): 8 GB RAM, 2 cores\n- Medium (100K\u20131M lines): 16 GB RAM, 4\u20138 cores\n- Large (> 1M lines): 64 GB RAM, 8 cores\n\n### Monorepo Splitting\n\nFor monorepos with multiple independent applications separated by process/network boundaries, consider splitting CodeQL scans by application. This reduces database size and enables parallel scanning via Actions matrix strategies.\n\n## Related Tools and Prompts\n\n| Tool / Prompt | Purpose |\n| ------------------------------------------------ | -------------------------------------------------------- |\n| `profile_codeql_query_from_logs` | Profile from existing evaluator logs (primary tool) |\n| `codeql_generate_log-summary` | Optional: human-readable evaluator log summary |\n| `codeql_query_run` | Execute a query (set `evaluationOutput` to capture logs) |\n| `explain_codeql_query` prompt | Understand query evaluation flow with Mermaid diagrams |\n| `run_query_and_summarize_false_positives` prompt | Assess result quality (precision) |\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://learning/query-basics` \u2014 Query structure and compilation tools\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for iterative query improvement\n';
63048
63466
 
63049
63467
  // src/resources/ql-test-driven-development.md
63050
63468
  var ql_test_driven_development_default = "# Test-Driven Development for CodeQL Queries\n\nThis resource explains the theory and value of test-driven development (TDD) for CodeQL queries, and how the MCP server's tools and prompts support the TDD workflow. It is a conceptual overview \u2014 for step-by-step guided workflows, use the `test_driven_development`, `ql_tdd_basic`, or `ql_tdd_advanced` prompts.\n\n## Why TDD for CodeQL?\n\nCodeQL queries are programs that search for patterns in source code. Like any program, they can have bugs: false positives (flagging safe code), false negatives (missing vulnerable code), and runtime performance issues. TDD addresses all three by establishing a feedback loop between expected and actual behavior.\n\n### Why TDD Makes LLMs More Effective\n\nLLMs generating CodeQL queries face two challenges:\n\n1. **Syntactic correctness** \u2014 QL has unique syntax (classes, predicates, `exists`, aggregates) that differs from mainstream languages. Compilation via `codeql_query_compile` catches syntax errors early.\n2. **Semantic correctness** \u2014 A query that compiles may still produce wrong results. Test cases with `.expected` files provide ground truth that the LLM can compare against, enabling iterative refinement.\n\nTDD provides the LLM with a concrete, automated signal (tests pass / tests fail) at every iteration, replacing guesswork with evidence. This is especially valuable for data flow and taint tracking queries where the correctness of source/sink/sanitizer definitions can only be verified by running the query against representative code.\n\n## The TDD Cycle\n\n```text\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 1. Write Tests \u2502 \u2190 Define expected behavior through test cases\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u25BC\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 2. Run (Red) \u2502 \u2190 Verify tests fail (no query logic yet)\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u25BC\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 3. Implement \u2502 \u2190 Write minimal query logic to pass tests\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u25BC\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 4. Run (Green) \u2502 \u2190 Verify tests pass\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u25BC\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 5. Refactor \u2502 \u2190 Improve query while keeping tests green\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u25BC\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 6. Repeat \u2502 \u2190 Add more tests for additional scenarios\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n## The Value of AST Data in Test Code\n\nA critical step in the TDD workflow is running `PrintAST` on test source code before writing the query. The AST output reveals how the CodeQL database represents the test code \u2014 which QL classes correspond to which source constructs, and which predicates are available for matching.\n\nWithout AST data, the LLM must guess which classes and predicates to use, leading to trial-and-error. With AST data, the LLM can:\n\n- **Map source patterns to QL classes**: See exactly which QL class represents a `for` loop, a method call, or an assignment\n- **Discover available predicates**: Learn what methods are available on each AST node type\n- **Write precise `from`/`where` clauses**: Use the correct class names and predicate calls from the start\n\nUse `codeql_query_run` with `queryName=\"PrintAST\"` to generate AST data for test source files. The `ql_tdd_advanced` prompt guides this step in detail.\n\n## MCP Tools for TDD\n\n| Step | Tool | Purpose |\n| ------------ | ------------------------------------- | ---------------------------------------------------- |\n| Scaffold | `create_codeql_query` | Generate query, test, and `.qlref` files |\n| Dependencies | `codeql_pack_install` | Install pack dependencies for src and test packs |\n| Extract | `codeql_test_extract` | Create a test database from test source files |\n| AST Analysis | `codeql_query_run` (PrintAST) | Understand test code structure via AST |\n| CFG Analysis | `codeql_query_run` (PrintCFG) | Understand control flow (advanced) |\n| Call Graph | `codeql_query_run` (CallGraphFrom/To) | Trace call relationships (advanced) |\n| Compile | `codeql_query_compile` | Validate query syntax before testing |\n| Test | `codeql_test_run` | Run tests and compare against `.expected` |\n| Accept | `codeql_test_accept` | Update `.expected` when results are verified correct |\n| Profile | `profile_codeql_query_from_logs` | Analyze query performance from evaluator logs |\n| Format | `codeql_query_format` | Auto-format query source code |\n| Metadata | `codeql_resolve_metadata` | Validate query metadata annotations |\n\n## MCP Prompts for TDD\n\n| Prompt | When to Use |\n| ------------------------- | ---------------------------------------------------------- |\n| `test_driven_development` | End-to-end TDD workflow with required `language` parameter |\n| `ql_tdd_basic` | Standalone TDD checklist (all parameters optional) |\n| `ql_tdd_advanced` | Extended TDD with AST/CFG/call graph analysis |\n| `tools_query_workflow` | Focused exploration of code structure via tool queries |\n| `explain_codeql_query` | Understand an existing query's logic before modifying it |\n\n## Writing Effective Test Cases\n\n### Structure\n\nEach test directory contains:\n\n- **Test source code** (e.g., `test.js`) \u2014 code that the query will analyze\n- **`.qlref` file** \u2014 points to the query being tested\n- **`.expected` file** \u2014 the expected query output\n\n### Best Practices\n\n1. **Include both positive and negative cases**: Write code that should trigger the query (vulnerable patterns) and code that should not (safe patterns)\n2. **Start simple**: Begin with the most obvious positive and negative cases, then add edge cases\n3. **Use realistic code**: Test against code patterns that occur in real-world projects\n4. **One concept per test directory**: Each test should verify one specific behavior\n5. **Document intent**: Use comments in test code to explain why each case should or should not match\n\n### Example Test Structure\n\n```text\ntest/SqlInjection/\n\u251C\u2500\u2500 SqlInjection.qlref # Points to src/SqlInjection/SqlInjection.ql\n\u251C\u2500\u2500 test.py # Test source code\n\u2514\u2500\u2500 SqlInjection.expected # Expected results\n```\n\nThe `.expected` file contains one line per query result, matching the `select` clause output.\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation and quick-start guide\n- `codeql://learning/query-basics` \u2014 Query structure, metadata, and compilation reference\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://templates/security` \u2014 Security query templates with TDD workflow\n- `codeql://patterns/performance` \u2014 Performance profiling tools\n- `codeql://languages/{language}/ast` \u2014 Language-specific AST class reference\n- `codeql://languages/{language}/security` \u2014 Language-specific security patterns\n";
@@ -63065,7 +63483,7 @@ var server_prompts_default = "# MCP Server Prompts\n\nThis resource provides a c
63065
63483
  var server_queries_default = '# MCP Server Bundled Queries\n\nThis resource describes the tools queries bundled with the CodeQL Development MCP Server. These queries run via `codeql_query_run` and provide structural insight into how source code is represented in a CodeQL database. Use them to understand code structure before writing detection queries.\n\nFor general QL query writing guidance (syntax, metadata, `from`/`where`/`select`, testing conventions), see `codeql://learning/query-basics`.\n\n## Bundled Tools Queries\n\nThe server bundles four tools queries that operate on CodeQL databases:\n\n| Query | Purpose | Output Format |\n| --------------- | ------------------------------------------------- | ------------------------- |\n| `PrintAST` | Visualize the Abstract Syntax Tree of source code | `@kind graph` (graphtext) |\n| `PrintCFG` | Visualize the Control Flow Graph of a function | `@kind graph` (graphtext) |\n| `CallGraphFrom` | Show all functions called FROM a given function | `@kind graph` (graphtext) |\n| `CallGraphTo` | Show all call sites that call TO a given function | `@kind graph` (graphtext) |\n\nAll four queries use `@kind graph` metadata and produce output in graphtext format.\n\n## PrintAST\n\n**Purpose**: Outputs a hierarchical representation of the Abstract Syntax Tree showing parent-child relationships between declarations, statements, and expressions.\n\n**When to use**: Before writing any CodeQL query, run `PrintAST` on your test source code to understand which QL classes represent which source constructs and which predicates are available for matching.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "PrintAST"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFiles: "<comma-separated-filenames>" (optional \u2014 filter to specific files)\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A tree showing each AST node with its QL class name, properties, and position in the hierarchy. This reveals exactly which QL classes and predicates to use in `from`/`where`/`select` clauses.\n\n## PrintCFG\n\n**Purpose**: Produces a Control Flow Graph representation showing the order in which statements and expressions execute, including branching paths.\n\n**When to use**: When writing queries that reason about execution order, reachability, or branching logic (e.g., "is this check always performed before this call?").\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "PrintCFG"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFunction: "<function-name>" (optional \u2014 target a specific function)\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: Nodes representing CFG basic blocks and edges representing possible execution transitions (successor relationships).\n\n## CallGraphFrom\n\n**Purpose**: Shows all functions called FROM a specified source function \u2014 the outbound call dependencies.\n\n**When to use**: When analyzing what a function does by tracing the functions it invokes. Useful for understanding call chains and identifying potential data flow paths.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "CallGraphFrom"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFunction: "<function-name>"\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A graph showing each call site within the source function and the target function being called.\n\n## CallGraphTo\n\n**Purpose**: Shows all call sites that invoke a specified target function \u2014 the inbound callers.\n\n**When to use**: When performing impact analysis to understand where a function is used, or when identifying all locations that pass data to a particular sink function.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "CallGraphTo"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n targetFunction: "<function-name>"\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A graph showing each caller function and the specific call site where the target function is invoked.\n\n## Language Support\n\n| Language | PrintAST | PrintCFG | CallGraphFrom | CallGraphTo |\n| ---------- | :------: | :------: | :-----------: | :---------: |\n| actions | \u2713 | \u2713 | | |\n| cpp | \u2713 | \u2713 | \u2713 | \u2713 |\n| csharp | \u2713 | \u2713 | \u2713 | \u2713 |\n| go | \u2713 | \u2713 | \u2713 | \u2713 |\n| java | \u2713 | \u2713 | \u2713 | \u2713 |\n| javascript | \u2713 | \u2713 | \u2713 | \u2713 |\n| python | \u2713 | \u2713 | \u2713 | \u2713 |\n| ruby | \u2713 | \u2713 | \u2713 | \u2713 |\n| swift | \u2713 | \u2713 | \u2713 | \u2713 |\n\nNote: The `actions` language supports PrintAST and PrintCFG only (no call graph queries).\n\n## Recommended Workflow\n\nUse the `tools_query_workflow` prompt for a guided step-by-step workflow:\n\n1. **Identify or create a database**: Use `list_codeql_databases` or `codeql_database_create`\n2. **Run PrintAST**: Understand how the source code maps to QL classes\n3. **Run PrintCFG**: Understand control flow for the functions of interest\n4. **Run CallGraphFrom / CallGraphTo**: Trace call relationships to identify sources and sinks\n5. **Write detection queries**: Use the insights from steps 2\u20134 to select the right QL classes and predicates\n\n## Related Resources\n\n- `codeql://learning/query-basics` \u2014 QL query writing reference (syntax, metadata, patterns, testing)\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for CodeQL queries\n- `codeql://languages/{language}/ast` \u2014 Language-specific AST class reference\n';
63066
63484
 
63067
63485
  // src/resources/server-tools.md
63068
- var server_tools_default = '# MCP Server Tools\n\nThis resource provides a complete reference of the default tools exposed by the CodeQL Development MCP Server. These tools wrap the CodeQL CLI and supporting utilities, enabling an LLM to develop, test, and analyze CodeQL queries programmatically.\n\n## CodeQL CLI Tools\n\n| Tool | Description |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_bqrs_decode` | Decode BQRS result files to human-readable formats (text, csv, json). Supports `--result-set` and `--rows` for pagination |\n| `codeql_bqrs_info` | Get metadata about BQRS result files: result sets, column types, row counts |\n| `codeql_bqrs_interpret` | Interpret BQRS result files according to query metadata and generate output in specified formats (CSV, SARIF, graph formats) |\n| `codeql_database_analyze` | Run queries or query suites against CodeQL databases. Produces evaluator logs, BQRS, and SARIF output |\n| `codeql_database_create` | Create a CodeQL database from source code |\n| `codeql_generate_log-summary` | Create a summary of a structured JSON evaluator event log file |\n| `codeql_generate_query-help` | Generate query help documentation from QLDoc comments |\n| `codeql_pack_install` | Install CodeQL pack dependencies |\n| `codeql_pack_ls` | List CodeQL packs under a local directory path |\n| `codeql_query_compile` | Compile and validate CodeQL queries |\n| `codeql_query_format` | Automatically format CodeQL source code files |\n| `codeql_query_run` | Execute a CodeQL query against a database |\n| `codeql_resolve_database` | Resolve database path and validate database structure |\n| `codeql_resolve_languages` | List installed CodeQL extractor packs |\n| `codeql_resolve_library-path` | Resolve library path for CodeQL queries and libraries |\n| `codeql_resolve_metadata` | Resolve and return key-value metadata pairs from a CodeQL query source file |\n| `codeql_resolve_qlref` | Resolve `.qlref` files to their corresponding query files |\n| `codeql_resolve_queries` | List available CodeQL queries found on the local filesystem |\n| `codeql_resolve_tests` | Resolve the local filesystem paths of unit tests and/or queries under a base directory |\n| `codeql_test_accept` | Accept new test results as the expected baseline |\n| `codeql_test_extract` | Extract test databases for CodeQL query tests |\n| `codeql_test_run` | Run CodeQL query tests |\n\n## Language Server Protocol (LSP) Tools\n\n| Tool | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_lsp_completion` | Get code completions at a cursor position in a CodeQL file |\n| `codeql_lsp_definition` | Go to the definition of a CodeQL symbol at a given position |\n| `codeql_lsp_diagnostics` | Syntax and semantic validation of CodeQL code via the Language Server. Note: inline `ql_code` cannot resolve pack imports; use `codeql_query_compile` for files with imports |\n| `codeql_lsp_references` | Find all references to a CodeQL symbol at a given position |\n\n## Query Development Tools\n\n| Tool | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| `create_codeql_query` | Create directory structure and files for a new CodeQL query with tests |\n| `find_class_position` | Find the start/end line and column of a class for quick evaluation |\n| `find_codeql_query_files` | Find and track all files and directories related to a CodeQL query, including resolved metadata |\n| `find_predicate_position` | Find the start/end line and column of a predicate for quick evaluation |\n| `list_codeql_databases` | List CodeQL databases discovered in configured base directories |\n| `list_mrva_run_results` | List MRVA (Multi-Repository Variant Analysis) run results with per-repo details |\n| `list_query_run_results` | List query run result directories with artifact inventory. Filter by `queryName`, `language`, or `queryPath` |\n| `profile_codeql_query` | Profile the performance of a CodeQL query run against a specific database by analyzing the evaluator log |\n| `profile_codeql_query_from_logs` | Parse existing CodeQL evaluator logs into a performance profile without re-running the query |\n| `quick_evaluate` | Quick evaluate either a class or a predicate in a CodeQL query for debugging |\n| `read_database_source` | Read source file contents from a CodeQL database source archive. Omit `filePath` to list all files |\n| `register_database` | Register a CodeQL database given a local path to the database directory |\n| `validate_codeql_query` | Quick heuristic validation for CodeQL query structure (does not compile the query) |\n\n## Common Tool Workflows\n\n### Create and Test a Query\n\n1. `create_codeql_query` \u2014 scaffold files\n2. `codeql_pack_install` \u2014 install dependencies\n3. `codeql_query_compile` \u2014 validate syntax\n4. `codeql_test_run` \u2014 run tests\n5. `codeql_test_accept` \u2014 accept correct results\n\n### Understand Code Structure\n\n1. `codeql_query_run` with `queryName="PrintAST"` \u2014 visualize the AST\n2. `codeql_query_run` with `queryName="PrintCFG"` \u2014 visualize control flow\n3. `codeql_query_run` with `queryName="CallGraphFrom"` / `"CallGraphTo"` \u2014 trace call relationships\n\n### Profile Query Performance\n\n1. `codeql_query_run` with `evaluationOutput` \u2014 run query and capture evaluator logs\n2. `profile_codeql_query_from_logs` \u2014 analyze evaluator logs for bottlenecks\n3. `codeql_generate_log-summary` \u2014 generate a human-readable log summary\n\n### Interactive Development\n\n1. `codeql_lsp_completion` \u2014 get QL code completions\n2. `codeql_lsp_definition` \u2014 navigate to definitions\n3. `codeql_lsp_references` \u2014 find all references\n4. `codeql_lsp_diagnostics` \u2014 real-time validation\n\n## Tool Input Conventions\n\n- **LSP tools** use **0-based** line and column positions for input. Output uses 1-based `startLine`/`endLine`.\n- **`find_predicate_position`** and **`find_class_position`** return **1-based** positions.\n- **`workspace_uri`** for LSP tools must be a **plain directory path** to the pack root containing `codeql-pack.yml`, not a `file://` URI.\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/prompts` \u2014 Complete prompt reference\n- `codeql://learning/query-basics` \u2014 Query writing reference\n- `codeql://patterns/performance` \u2014 Performance profiling guide\n';
63486
+ var server_tools_default = '# MCP Server Tools\n\nThis resource provides a complete reference of the default tools exposed by the CodeQL Development MCP Server. These tools wrap the CodeQL CLI and supporting utilities, enabling an LLM to develop, test, and analyze CodeQL queries programmatically.\n\n## CodeQL CLI Tools\n\n| Tool | Description |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_bqrs_decode` | Decode BQRS result files to human-readable formats (text, csv, json). Supports `--result-set` and `--rows` for pagination |\n| `codeql_bqrs_info` | Get metadata about BQRS result files: result sets, column types, row counts |\n| `codeql_bqrs_interpret` | Interpret BQRS result files according to query metadata and generate output in specified formats (CSV, SARIF, graph formats) |\n| `codeql_database_analyze` | Run queries or query suites against CodeQL databases. Produces evaluator logs, BQRS, and SARIF output |\n| `codeql_database_create` | Create a CodeQL database from source code |\n| `codeql_generate_log-summary` | Create a summary of a structured JSON evaluator event log file |\n| `codeql_generate_query-help` | Generate query help documentation from QLDoc comments |\n| `codeql_pack_install` | Install CodeQL pack dependencies |\n| `codeql_pack_ls` | List CodeQL packs under a local directory path |\n| `codeql_query_compile` | Compile and validate CodeQL queries |\n| `codeql_query_format` | Automatically format CodeQL source code files |\n| `codeql_query_run` | Execute a CodeQL query against a database |\n| `codeql_resolve_database` | Resolve database path and validate database structure |\n| `codeql_resolve_files` | Find files in a directory tree, filtered by extension and glob patterns. Useful for discovering QL library files |\n| `codeql_resolve_languages` | List installed CodeQL extractor packs |\n| `codeql_resolve_library-path` | Resolve library path for CodeQL queries and libraries |\n| `codeql_resolve_metadata` | Resolve and return key-value metadata pairs from a CodeQL query source file |\n| `codeql_resolve_qlref` | Resolve `.qlref` files to their corresponding query files |\n| `codeql_resolve_queries` | List available CodeQL queries found on the local filesystem |\n| `codeql_resolve_tests` | Resolve the local filesystem paths of unit tests and/or queries under a base directory |\n| `codeql_test_accept` | Accept new test results as the expected baseline |\n| `codeql_test_extract` | Extract test databases for CodeQL query tests |\n| `codeql_test_run` | Run CodeQL query tests |\n\n## Language Server Protocol (LSP) Tools\n\n| Tool | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_lsp_completion` | Get code completions at a cursor position in a CodeQL file |\n| `codeql_lsp_definition` | Go to the definition of a CodeQL symbol at a given position |\n| `codeql_lsp_diagnostics` | Syntax and semantic validation of CodeQL code via the Language Server. Note: inline `ql_code` cannot resolve pack imports; use `codeql_query_compile` for files with imports |\n| `codeql_lsp_references` | Find all references to a CodeQL symbol at a given position |\n\n## Query Development Tools\n\n| Tool | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| `create_codeql_query` | Create directory structure and files for a new CodeQL query with tests |\n| `find_class_position` | Find the start/end line and column of a class for quick evaluation |\n| `find_codeql_query_files` | Find and track all files and directories related to a CodeQL query, including resolved metadata |\n| `find_predicate_position` | Find the start/end line and column of a predicate for quick evaluation |\n| `list_codeql_databases` | List CodeQL databases discovered in configured base directories |\n| `list_mrva_run_results` | List MRVA (Multi-Repository Variant Analysis) run results with per-repo details |\n| `list_query_run_results` | List query run result directories with artifact inventory. Filter by `queryName`, `language`, or `queryPath` |\n| `profile_codeql_query` | Profile the performance of a CodeQL query run against a specific database by analyzing the evaluator log |\n| `profile_codeql_query_from_logs` | Parse evaluator logs into a compact profile with line-indexed detail file for targeted read_file access |\n| `quick_evaluate` | Quick evaluate either a class or a predicate in a CodeQL query for debugging |\n| `read_database_source` | Read source file contents from a CodeQL database source archive. Omit `filePath` to list all files |\n| `register_database` | Register a CodeQL database given a local path to the database directory |\n| `search_ql_code` | Search QL source files for text or regex patterns with structured results (replaces grep for QL code) |\n| `validate_codeql_query` | Quick heuristic validation for CodeQL query structure (does not compile the query) |\n\n## Common Tool Workflows\n\n### Create and Test a Query\n\n1. `create_codeql_query` \u2014 scaffold files\n2. `codeql_pack_install` \u2014 install dependencies\n3. `codeql_query_compile` \u2014 validate syntax\n4. `codeql_test_run` \u2014 run tests\n5. `codeql_test_accept` \u2014 accept correct results\n\n### Understand Code Structure\n\n1. `codeql_query_run` with `queryName="PrintAST"` \u2014 visualize the AST\n2. `codeql_query_run` with `queryName="PrintCFG"` \u2014 visualize control flow\n3. `codeql_query_run` with `queryName="CallGraphFrom"` / `"CallGraphTo"` \u2014 trace call relationships\n\n### Profile Query Performance\n\n1. `codeql_query_run` with `evaluationOutput` \u2014 run query and capture evaluator logs\n2. `profile_codeql_query_from_logs` \u2014 analyze evaluator logs: slowest predicates, RA operations, tuple count progressions, dependencies\n\n### Discover and Search QL Code\n\n1. `codeql_resolve_files` \u2014 find QL files by extension and glob patterns in library packs\n2. `search_ql_code` \u2014 search QL source files for classes, predicates, or patterns by text/regex\n3. `codeql_lsp_definition` \u2014 navigate to the definition of a discovered symbol\n4. `codeql_lsp_references` \u2014 find all usages of a symbol across a pack\n\n### Interactive Development\n\n1. `codeql_lsp_completion` \u2014 get QL code completions\n2. `codeql_lsp_definition` \u2014 navigate to definitions\n3. `codeql_lsp_references` \u2014 find all references\n4. `codeql_lsp_diagnostics` \u2014 real-time validation\n\n## Tool Input Conventions\n\n- **LSP tools** use **0-based** line and column positions for input. Output uses 1-based `startLine`/`endLine`.\n- **`find_predicate_position`** and **`find_class_position`** return **1-based** positions.\n- **`workspace_uri`** for LSP tools must be a **plain directory path** to the pack root containing `codeql-pack.yml`, not a `file://` URI.\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/prompts` \u2014 Complete prompt reference\n- `codeql://learning/query-basics` \u2014 Query writing reference\n- `codeql://patterns/performance` \u2014 Performance profiling guide\n';
63069
63487
 
63070
63488
  // src/lib/resources.ts
63071
63489
  function getLearningQueryBasics() {
@@ -63296,13 +63714,13 @@ function registerCodeQLResources(server) {
63296
63714
  // src/tools/lsp/lsp-diagnostics.ts
63297
63715
  init_logger();
63298
63716
  init_temp_dir();
63299
- import { join as join16 } from "path";
63717
+ import { join as join17 } from "path";
63300
63718
  import { pathToFileURL as pathToFileURL3 } from "url";
63301
63719
 
63302
63720
  // src/tools/lsp/lsp-server-helper.ts
63303
63721
  init_server_manager();
63304
63722
  init_logger();
63305
- import { isAbsolute as isAbsolute5, resolve as resolve10 } from "path";
63723
+ import { isAbsolute as isAbsolute5, resolve as resolve11 } from "path";
63306
63724
  import { pathToFileURL as pathToFileURL2 } from "url";
63307
63725
  async function getInitializedLanguageServer(opts = {}) {
63308
63726
  const { packageRootDir: pkgRoot, getUserWorkspaceDir: getUserWorkspaceDir2 } = await Promise.resolve().then(() => (init_package_paths(), package_paths_exports));
@@ -63310,7 +63728,7 @@ async function getInitializedLanguageServer(opts = {}) {
63310
63728
  const config2 = {
63311
63729
  checkErrors: "ON_CHANGE",
63312
63730
  loglevel: options.loglevel ?? "WARN",
63313
- searchPath: options.searchPath ?? resolve10(pkgRoot, "ql"),
63731
+ searchPath: options.searchPath ?? resolve11(pkgRoot, "ql"),
63314
63732
  synchronous: options.synchronous,
63315
63733
  verbosity: options.verbosity
63316
63734
  };
@@ -63318,10 +63736,10 @@ async function getInitializedLanguageServer(opts = {}) {
63318
63736
  const server = await manager.getLanguageServer(config2);
63319
63737
  let effectiveUri = opts.workspaceUri;
63320
63738
  if (effectiveUri && !effectiveUri.startsWith("file://")) {
63321
- const absWorkspace = isAbsolute5(effectiveUri) ? effectiveUri : resolve10(getUserWorkspaceDir2(), effectiveUri);
63739
+ const absWorkspace = isAbsolute5(effectiveUri) ? effectiveUri : resolve11(getUserWorkspaceDir2(), effectiveUri);
63322
63740
  effectiveUri = pathToFileURL2(absWorkspace).href;
63323
63741
  }
63324
- effectiveUri = effectiveUri ?? pathToFileURL2(resolve10(pkgRoot, "ql")).href;
63742
+ effectiveUri = effectiveUri ?? pathToFileURL2(resolve11(pkgRoot, "ql")).href;
63325
63743
  await server.initialize(effectiveUri);
63326
63744
  logger.debug(`Language server initialized with workspace: ${effectiveUri}`);
63327
63745
  return server;
@@ -63394,7 +63812,7 @@ async function lspDiagnostics({
63394
63812
  serverOptions,
63395
63813
  workspaceUri
63396
63814
  });
63397
- const evalUri = pathToFileURL3(join16(getProjectTmpDir("lsp-eval"), `eval_${Date.now()}.ql`)).href;
63815
+ const evalUri = pathToFileURL3(join17(getProjectTmpDir("lsp-eval"), `eval_${Date.now()}.ql`)).href;
63398
63816
  const diagnostics = await languageServer.evaluateQL(qlCode, evalUri);
63399
63817
  const summary = {
63400
63818
  errorCount: diagnostics.filter((d) => d.severity === 1).length,
@@ -63483,7 +63901,7 @@ function registerLspDiagnosticsTool(server) {
63483
63901
  init_logger();
63484
63902
  init_package_paths();
63485
63903
  import { readFile as readFile3 } from "fs/promises";
63486
- import { isAbsolute as isAbsolute6, resolve as resolve11 } from "path";
63904
+ import { isAbsolute as isAbsolute6, resolve as resolve12 } from "path";
63487
63905
  import { pathToFileURL as pathToFileURL4 } from "url";
63488
63906
  async function getInitializedServer(params) {
63489
63907
  return getInitializedLanguageServer({
@@ -63492,7 +63910,7 @@ async function getInitializedServer(params) {
63492
63910
  });
63493
63911
  }
63494
63912
  function prepareDocumentPosition(params) {
63495
- const absPath = isAbsolute6(params.filePath) ? params.filePath : resolve11(getUserWorkspaceDir(), params.filePath);
63913
+ const absPath = isAbsolute6(params.filePath) ? params.filePath : resolve12(getUserWorkspaceDir(), params.filePath);
63496
63914
  const docUri = pathToFileURL4(absPath).href;
63497
63915
  return { absPath, docUri };
63498
63916
  }
@@ -63839,22 +64257,22 @@ function registerLanguageResources(server) {
63839
64257
  }
63840
64258
 
63841
64259
  // src/prompts/workflow-prompts.ts
63842
- import { basename as basename6 } from "path";
64260
+ import { basename as basename7 } from "path";
63843
64261
 
63844
64262
  // src/prompts/document-codeql-query.prompt.md
63845
64263
  var document_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Document a CodeQL Query\n\nThis prompt guides you through creating or updating documentation for a CodeQL query file. The documentation is stored as a sibling file to the query with a standardized markdown format.\n\n## Purpose\n\nThe `document_codeql_query` prompt creates/updates **query documentation files** for a specific version of a CodeQL query. Documentation files are stored alongside the query file and provide concise yet comprehensive information about what the query does.\n\nFor creating **workshop learning content** with detailed explanations and visual diagrams, use the `explain_codeql_query` prompt instead.\n\n## Required Inputs\n\n- **queryPath**: Path to the CodeQL query file (`.ql` or `.qlref`)\n- **language**: Target programming language (actions, cpp, csharp, go, java, javascript, python, ruby, swift)\n\n## Documentation File Conventions\n\n### File Location and Naming\n\nFor a query file `QueryFileBaseName.ql`, the documentation file should be:\n\n- **Primary**: `QueryFileBaseName.md` (markdown format, preferred)\n- **Legacy**: `QueryFileBaseName.qhelp` (XML-based query help format)\n\nDocumentation files are **siblings** to the query file (same directory).\n\n### Handling Existing Documentation\n\n1. **No documentation exists**: Create new `QueryFileBaseName.md` file\n2. **`.md` file exists**: Update the existing markdown file\n3. **`.qhelp` file exists**: Use #codeql_generate_query-help tool to convert to markdown, then update\n\n## Workflow Checklist\n\nUse the following MCP server tools to gather context before creating documentation:\n\n### Phase 1: Query Discovery\n\n- [ ] **Step 1: Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` = provided query path\n - Gather: Query source file path, existing documentation files, test files\n - Check: Does `QueryFileBaseName.md` or `QueryFileBaseName.qhelp` exist?\n\n- [ ] **Step 2: Read query metadata**\n - Tool: #codeql_resolve_metadata\n - Parameters: `query` = query file path\n - Gather: @name, @description, @kind, @id, @tags, @precision, @severity\n\n### Phase 2: Convert Existing qhelp (if needed)\n\n- [ ] **Step 3: Convert qhelp to markdown** (only if `.qhelp` exists)\n - Tool: #codeql_generate_query-help\n - Parameters: `query` = query file path, `format` = "markdown"\n - Use output as starting point for updated documentation\n\n### Phase 3: Gather Query Context\n\n- [ ] **Step 4: Validate query structure**\n - Tool: #validate_codeql_query\n - Parameters: `query` = query source code\n - Gather: Structural validation, suggestions\n - Note: This is a heuristic check only \u2014 for full validation, use #codeql_query_compile\n\n- [ ] **Step 5: Explore query types** (if deeper understanding needed)\n - Tool: #codeql_lsp_definition \u2014 navigate to class/predicate definitions\n - Tool: #codeql_lsp_completion \u2014 explore member predicates on types used in the query\n - Parameters: `file_path`, `line` (0-based), `character` (0-based), `workspace_uri` (pack root)\n - Run #codeql_pack_install first \u2014 LSP tools require resolved dependencies\n\n- [ ] **Step 6: Run tests** (if tests exist from Step 1)\n - Tool: #codeql_test_run\n - Parameters: `tests` = test directories\n - Gather: Pass/fail status, confirms query behavior\n\n### Phase 4: Create/Update Documentation\n\nBased on gathered context, create or update the documentation file.\n\n## Documentation Format\n\nThe documentation file (`QueryFileBaseName.md`) should follow this standardized format with these sections:\n\n### Section 1: Title and Description\n\n- H1 heading with the query name from @name metadata\n- One paragraph description from @description, expanded if needed\n\n### Section 2: Metadata Table\n\nA table with these rows:\n\n- ID: The @id value in backticks\n- Kind: The @kind value (problem, path-problem, etc.)\n- Severity: The @severity value\n- Precision: The @precision value\n- Tags: The @tags values\n\n### Section 3: Overview\n\nConcise explanation of what vulnerability/issue this query detects and why it matters. 2-4 sentences.\n\n### Section 4: Recommendation\n\nBrief guidance on how developers should fix issues flagged by this query. Include code patterns to use or avoid.\n\n### Section 5: Example\n\nTwo subsections:\n\n- **Vulnerable Code**: A code block showing a pattern that would be flagged by this query\n- **Fixed Code**: A code block showing the corrected version of the code\n\nUse the appropriate language identifier for the code blocks (e.g., `javascript`, `python`, `java`).\n\n### Section 6: References\n\nA list of links to:\n\n- Relevant CWE if security query\n- Relevant documentation or standards\n- CodeQL documentation for related concepts\n\n## Output Actions\n\nAfter generating documentation content:\n\n1. **For new documentation**: Create the file at `[QueryDirectory]/QueryFileBaseName.md`\n2. **For existing `.md` file**: Update the file with new content, preserving any custom sections\n3. **For existing `.qhelp` file**: Create new `.md` file (keeping `.qhelp` for backward compatibility)\n\n## Important Notes\n\n- **Be concise**: Documentation should be brief but complete. This is reference documentation, not tutorial content.\n- **Keep it current**: Documentation should reflect the current behavior of the query.\n- **Use examples from tests**: If unit tests exist, use those code patterns as examples.\n- **Standard format**: Always use the format above for consistency across all query documentation.\n- **Metadata accuracy**: Ensure documented metadata matches actual query metadata.\n- **For workshops**: Use `explain_codeql_query` prompt when creating workshop content that requires deeper explanations and visual diagrams.\n';
63846
64264
 
63847
64265
  // src/prompts/explain-codeql-query.prompt.md
63848
- var explain_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Explain a CodeQL Query (Workshop Learning Content)\n\nThis prompt guides you through gathering comprehensive context about a CodeQL query using MCP server tools, then generating detailed explanations suitable for CodeQL workshop learning content.\n\n## Purpose\n\nThe `explain_codeql_query` prompt is designed for creating **learning content** for CodeQL workshops and workshop improvements. It produces in-depth, educational explanations of how a query works, including visual diagrams.\n\nFor creating/updating **query documentation files** (`.md` or `.qhelp`), use the `document_codeql_query` prompt instead.\n\n## Required Inputs\n\n- **queryPath**: Path to the CodeQL query file (`.ql` or `.qlref`)\n- **language**: Target programming language (actions, cpp, csharp, go, java, javascript, python, ruby, swift)\n- **databasePath** (optional): Path to a real CodeQL database for profiling\n\n## Agent AI Instructions\n\n**Critical**: The evaluator logs and profiler outputs from CodeQL can be very large files. Instead of reading them line by line, use grep-style CLI commands to investigate these files efficiently. Key patterns to search for:\n\n- Pipeline evaluation times: `grep -E "Pipeline|eval [0-9]+ms" <logfile>`\n- Predicate evaluation order: `grep -E "Evaluation done|evaluated" <logfile>`\n- Tuple counts: `grep -E "tuples|rows" <logfile>`\n- RA operations: `grep -E "SCAN|JOIN|AGGREGATE" <logfile>`\n\n## Choosing a Database\n\nSeveral steps below require a CodeQL database. Determine which database to use:\n\n1. **User-provided `databasePath`** \u2014 use this if provided and valid (check with #codeql_resolve_database).\n2. **Test database** \u2014 if Step 1 finds tests, run them in Step 3 to create a `.testproj` database.\n3. **No database available** \u2014 skip Steps 4-6, and base the explanation on source code analysis only.\n\nStore the chosen database path as `$DB` for use in Steps 4-6.\n\n## Workflow Checklist\n\nYou MUST use the following MCP server tools in sequence to gather context before generating your explanation:\n\n### Phase 1: Query Discovery and Validation\n\n- [ ] **Step 1: Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` = provided query path\n - Gather: Query source file, test files, expected results, metadata location\n - Note: If tests exist, record the test directory path for later steps\n\n- [ ] **Step 2: Validate query structure**\n - Tool: #validate_codeql_query\n - Parameters: `query` = contents of the query file\n - Gather: Structural validation results, heuristic warnings/suggestions\n\n### Phase 2: Test Execution and Database Creation\n\n- [ ] **Step 3: Run existing tests** (if tests exist from Step 1)\n - Tool: #codeql_test_run\n - Parameters: `tests` = array of test directories from Step 1\n - Purpose: Ensures test database is created and current with test code\n - Gather: Test pass/fail status, test database path (`.testproj` directory)\n - **If no tests exist**: Skip this step. Use user-provided `databasePath` as `$DB`.\n\n### Phase 3: Code Structure Analysis (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 4: Generate PrintAST output**\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFiles`: test source file names (or representative source files from the database)\n - `format`: `"graphtext"`\n - Gather: AST hierarchy showing code structure representation\n\n- [ ] **Step 5: Generate PrintCFG output** (for key functions)\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFunction`: key function name(s) from test code or query source\n - `format`: `"graphtext"`\n - Gather: Control flow graph showing execution paths\n\n### Phase 4: Query Profiling and Evaluation Order (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 6a: Run the query with evaluator logging**\n - Tool: #codeql_query_run (or #codeql_database_analyze)\n - Run the query against `$DB` with evaluator logging enabled\n - The tool returns the path to the evaluator log file (`.jsonl`)\n\n- [ ] **Step 6b: Profile from evaluator logs**\n - Tool: #profile_codeql_query_from_logs\n - Parameters:\n - `evaluatorLog`: path to the evaluator log file from Step 6a\n - Gather: Pipeline execution order, predicate timing data, tuple counts\n - **Critical**: This reveals the actual bottom-up evaluation order of predicates\n\n- [ ] **Step 7: Analyze evaluator log** (for large logs)\n - Use CLI grep commands to extract key performance data from evaluator logs:\n - Replace `<evaluator-log-file>` with the log file path from Step 6a\n\n ```bash\n # Find pipeline evaluation order and timing\n grep -E "Pipeline.*evaluated|eval [0-9]+ms" <evaluator-log-file>\n\n # Find predicate evaluation completion\n grep "Evaluation done" <evaluator-log-file>\n\n # Extract tuple counts for understanding data sizes\n grep -E "tuples|resultSize" <evaluator-log-file>\n\n # Find the most expensive operations\n grep -E "eval [0-9]{4,}ms" <evaluator-log-file> | sort -t\'[\' -k2 -rn | head -20\n ```\n\n- [ ] **Step 8: Quick evaluate specific predicates** (as needed)\n - First, locate the predicate: Tool: #find_predicate_position with `file` and `name`\n - Then evaluate: Tool: #quick_evaluate with `file`, `db`, and `symbol`\n - Use when: You need more context on how a specific predicate or class behaves\n - Note: #find_class_position finds `class` definitions only, not `module` definitions\n - Note: #find_predicate_position returns 1-based positions; LSP tools use 0-based\n\n### Phase 5: Generate Explanation\n\nBased on all gathered context, generate your explanation with both **verbal** and **visual** components.\n\n## Key Aspects to Analyze in Profiler Output\n\nUnderstanding the query profiler output is critical for explaining how the query actually works. Look for:\n\n1. **Evaluation Order**: Which predicates are evaluated first (base predicates) vs last (dependent predicates)\n2. **Pipeline Timing**: Time taken for each pipeline stage - indicates complexity\n3. **Tuple Counts**: Number of results at each stage - shows data flow volume\n4. **RA Operations**: The relational algebra operations (SCAN, JOIN, AGGREGATE) reveal query execution strategy\n5. **Dependencies**: Which predicates depend on others (shown by evaluation order)\n\n## Output Format\n\n### Verbal Explanation Structure\n\nGenerate a single markdown document with these sections in order:\n\n1. **Query Overview** \u2014 2-3 sentence summary of what the query detects and why it matters.\n2. **Query Metadata** \u2014 Table with: Name, Description, Kind, ID, Tags, Precision, Severity (from `@` annotations).\n3. **What This Query Detects** \u2014 Security implications (CWE/OWASP if applicable), why the pattern is problematic, real-world attack scenarios.\n4. **How the Query Works** \u2014 Two subsections:\n - **Bottom-Up Evaluation Order**: Evaluation timeline table (Order, Predicate/Pipeline, Time ms, Tuples) derived from profiler data. Explain that CodeQL evaluates bottom-up.\n - **Key Components**: Imports, classes and characteristic predicates, helper predicates, data flow configuration (sources, sinks, sanitizers, additional flow steps), main query `from`/`where`/`select`.\n5. **Test Code Analysis** (if database was available) \u2014 AST structure insights from PrintAST, control flow insights from PrintCFG.\n6. **Example Patterns** \u2014 Positive test cases (should match) and negative test cases (should not match) with explanations.\n7. **Performance Characteristics** (if profiler data available) \u2014 Most expensive predicates, highest tuple counts, optimization opportunities.\n8. **Limitations and Edge Cases** \u2014 Patterns the query might miss, known false positive scenarios.\n\n### Visual Explanation: Mermaid Evaluation Diagram\n\nGenerate a `mermaid` `flowchart BU` (bottom-up) diagram showing the evaluation order derived from profiler data. Guidelines:\n\n- Use subgraphs to group predicates by evaluation phase (base, intermediate, flow analysis, final select)\n- Label nodes with actual predicate/class names from the query\n- Show dependency edges between predicates\n- Annotate expensive operations with timing (e.g., `[500ms]`)\n- Direction must be `BU` to reflect bottom-up evaluation\n\n## Important Notes\n\n- **Always use tools first**: Do not generate explanations based only on query source code. Use the MCP tools to gather actual runtime data.\n- **Use grep for large files**: Evaluator logs can be huge. Use CLI grep commands to extract relevant data efficiently.\n- **Evaluation order matters**: CodeQL evaluates bottom-up, not top-down. The profiler output reveals the true execution order.\n- **Focus on learning**: This is for workshop content, so include educational context and explanations suitable for CodeQL learners.\n- **Visual diagrams**: Always include a mermaid diagram showing evaluation order.\n- **Reference documentation**: For actual QL evaluation semantics, see [Evaluation of QL programs](https://codeql.github.com/docs/ql-language-reference/evaluation-of-ql-programs/)\n';
64266
+ var explain_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Explain a CodeQL Query (Workshop Learning Content)\n\nThis prompt guides you through gathering comprehensive context about a CodeQL query using MCP server tools, then generating detailed explanations suitable for CodeQL workshop learning content.\n\n## Purpose\n\nThe `explain_codeql_query` prompt is designed for creating **learning content** for CodeQL workshops and workshop improvements. It produces in-depth, educational explanations of how a query works, including visual diagrams.\n\nFor creating/updating **query documentation files** (`.md` or `.qhelp`), use the `document_codeql_query` prompt instead.\n\n## Required Inputs\n\n- **queryPath**: Path to the CodeQL query file (`.ql` or `.qlref`)\n- **language**: Target programming language (actions, cpp, csharp, go, java, javascript, python, ruby, swift)\n- **databasePath** (optional): Path to a real CodeQL database for profiling\n\n## Agent AI Instructions\n\n**Critical**: The evaluator logs and profiler outputs from CodeQL can be very large files. Use the MCP server tools to analyze them efficiently:\n\n- Use #profile_codeql_query_from_logs to extract pipeline timing, predicate evaluation order, tuple count progressions, RA operations, and dependencies from evaluator logs \u2014 this single tool provides all evaluator log analysis\n- Use #search_ql_code to find predicates, classes, or patterns across QL library files\n\n## Choosing a Database\n\nSeveral steps below require a CodeQL database. Determine which database to use:\n\n1. **User-provided `databasePath`** \u2014 use this if provided and valid (check with #codeql_resolve_database).\n2. **Test database** \u2014 if Step 1 finds tests, run them in Step 3 to create a `.testproj` database.\n3. **No database available** \u2014 skip Steps 4-6, and base the explanation on source code analysis only.\n\nStore the chosen database path as `$DB` for use in Steps 4-6.\n\n## Workflow Checklist\n\nYou MUST use the following MCP server tools in sequence to gather context before generating your explanation:\n\n### Phase 1: Query Discovery and Validation\n\n- [ ] **Step 1: Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` = provided query path\n - Gather: Query source file, test files, expected results, metadata location\n - Note: If tests exist, record the test directory path for later steps\n\n- [ ] **Step 2: Validate query structure**\n - Tool: #validate_codeql_query\n - Parameters: `query` = contents of the query file\n - Gather: Structural validation results, heuristic warnings/suggestions\n\n### Phase 2: Test Execution and Database Creation\n\n- [ ] **Step 3: Run existing tests** (if tests exist from Step 1)\n - Tool: #codeql_test_run\n - Parameters: `tests` = array of test directories from Step 1\n - Purpose: Ensures test database is created and current with test code\n - Gather: Test pass/fail status, test database path (`.testproj` directory)\n - **If no tests exist**: Skip this step. Use user-provided `databasePath` as `$DB`.\n\n### Phase 3: Code Structure Analysis (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 4: Generate PrintAST output**\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFiles`: test source file names (or representative source files from the database)\n - `format`: `"graphtext"`\n - Gather: AST hierarchy showing code structure representation\n\n- [ ] **Step 5: Generate PrintCFG output** (for key functions)\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFunction`: key function name(s) from test code or query source\n - `format`: `"graphtext"`\n - Gather: Control flow graph showing execution paths\n\n### Phase 4: Query Profiling and Evaluation Order (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 6a: Run the query with evaluator logging**\n - Tool: #codeql_query_run (or #codeql_database_analyze)\n - Run the query against `$DB` with evaluator logging enabled\n - The tool returns the path to the evaluator log file (`.jsonl`)\n\n- [ ] **Step 6b: Profile from evaluator logs**\n - Tool: #profile_codeql_query_from_logs\n - Parameters:\n - `evaluatorLog`: path to the evaluator log file from Step 6a\n - Gather: Pipeline execution order, predicate timing data, tuple counts\n - **Critical**: This reveals the actual bottom-up evaluation order of predicates\n\n- [ ] **Step 7: Quick evaluate specific predicates** (as needed)\n - First, locate the predicate: Tool: #find_predicate_position with `file` and `name`\n - Then evaluate: Tool: #quick_evaluate with `file`, `db`, and `symbol`\n - Use when: You need more context on how a specific predicate or class behaves\n - Note: #find_class_position finds `class` definitions only, not `module` definitions\n - Note: #find_predicate_position returns 1-based positions; LSP tools use 0-based\n\n### Phase 5: Generate Explanation\n\nBased on all gathered context, generate your explanation with both **verbal** and **visual** components.\n\n## Key Aspects to Analyze in Profiler Output\n\nUnderstanding the query profiler output is critical for explaining how the query actually works. Look for:\n\n1. **Evaluation Order**: Which predicates are evaluated first (base predicates) vs last (dependent predicates)\n2. **Pipeline Timing**: Time taken for each pipeline stage - indicates complexity\n3. **Tuple Counts**: Number of results at each stage - shows data flow volume\n4. **RA Operations**: The relational algebra operations (SCAN, JOIN, AGGREGATE) reveal query execution strategy\n5. **Dependencies**: Which predicates depend on others (shown by evaluation order)\n\n## Output Format\n\n### Verbal Explanation Structure\n\nGenerate a single markdown document with these sections in order:\n\n1. **Query Overview** \u2014 2-3 sentence summary of what the query detects and why it matters.\n2. **Query Metadata** \u2014 Table with: Name, Description, Kind, ID, Tags, Precision, Severity (from `@` annotations).\n3. **What This Query Detects** \u2014 Security implications (CWE/OWASP if applicable), why the pattern is problematic, real-world attack scenarios.\n4. **How the Query Works** \u2014 Two subsections:\n - **Bottom-Up Evaluation Order**: Evaluation timeline table (Order, Predicate/Pipeline, Time ms, Tuples) derived from profiler data. Explain that CodeQL evaluates bottom-up.\n - **Key Components**: Imports, classes and characteristic predicates, helper predicates, data flow configuration (sources, sinks, sanitizers, additional flow steps), main query `from`/`where`/`select`.\n5. **Test Code Analysis** (if database was available) \u2014 AST structure insights from PrintAST, control flow insights from PrintCFG.\n6. **Example Patterns** \u2014 Positive test cases (should match) and negative test cases (should not match) with explanations.\n7. **Performance Characteristics** (if profiler data available) \u2014 Most expensive predicates, highest tuple counts, optimization opportunities.\n8. **Limitations and Edge Cases** \u2014 Patterns the query might miss, known false positive scenarios.\n\n### Visual Explanation: Mermaid Evaluation Diagram\n\nGenerate a `mermaid` `flowchart BU` (bottom-up) diagram showing the evaluation order derived from profiler data. Guidelines:\n\n- Use subgraphs to group predicates by evaluation phase (base, intermediate, flow analysis, final select)\n- Label nodes with actual predicate/class names from the query\n- Show dependency edges between predicates\n- Annotate expensive operations with timing (e.g., `[500ms]`)\n- Direction must be `BU` to reflect bottom-up evaluation\n\n## Important Notes\n\n- **Always use tools first**: Do not generate explanations based only on query source code. Use the MCP tools to gather actual runtime data.\n- **Use the profiler tool for evaluator logs**: Evaluator logs can be huge. Use #profile_codeql_query_from_logs which returns compact JSON with per-predicate metrics and a line-indexed detail file. Use `read_file` with the `detailLines` ranges from the response to access full RA operations and tuple progressions for any predicate \u2014 do not use CLI grep or read log files directly.\n- **Evaluation order matters**: CodeQL evaluates bottom-up, not top-down. The profiler output reveals the true execution order.\n- **Focus on learning**: This is for workshop content, so include educational context and explanations suitable for CodeQL learners.\n- **Visual diagrams**: Always include a mermaid diagram showing evaluation order.\n- **Reference documentation**: For actual QL evaluation semantics, see [Evaluation of QL programs](https://codeql.github.com/docs/ql-language-reference/evaluation-of-ql-programs/)\n';
63849
64267
 
63850
64268
  // src/prompts/ql-lsp-iterative-development.prompt.md
63851
- var ql_lsp_iterative_development_prompt_default = '---\nagent: agent\n---\n\n# Iterative CodeQL Development with LSP Tools\n\nUse the MCP server tools from this prompt to iteratively develop and refine CodeQL queries using the LSP-powered tools.\nThese "iterative" tools work entirely through file paths and numeric positions.\nEvery operation is expressible as a tool call with explicit `file_path`, `line`, and `character` parameters.\nThus, this prompt can be used in any environment where the query files are on disk, and it does not require any special editor integration.\n\n## Use This Prompt When\n\n- Exploring unfamiliar CodeQL libraries to discover available classes and predicates\n- Incrementally building a query clause-by-clause with real-time feedback\n- Navigating from a type usage to its definition to understand its API\n- Finding all usages of a predicate to learn patterns from existing queries\n- Validating query fragments before assembling a complete query\n- Debugging individual predicates by evaluating them in isolation against a database\n\n## Prerequisites\n\n1. A CodeQL pack with `codeql-pack.yml` on disk\n2. Dependencies installed via #codeql_pack_install (pointing at the pack directory)\n3. Query files saved to disk (LSP tools operate on files, not inline strings)\n\n## Key Concept: Positions Are File Path + Line + Character\n\nAll LSP tools identify locations using three values:\n\n- `file_path`: absolute path to a `.ql` or `.qll` file\n- `line`: **0-based** line number (line 1 in the file = `line: 0`)\n- `character`: **0-based** column offset within that line\n\nThe `workspace_uri` parameter must point to the **pack root directory** (the folder\ncontaining `codeql-pack.yml`) for import resolution to work. Without it, completions\nand definitions for imported libraries will be empty.\n\n> **Critical**: LSP line/character positions are 0-based, but `read_file`,\n> #find_predicate_position, and #find_class_position return 1-based positions.\n> Always subtract 1 when passing their output to LSP tools.\n\n## Step 1: Discover Available Types with Completions\n\nUse #codeql_lsp_completion to explore what types and predicates are available at any\nposition in a query file. This replaces manual documentation browsing.\n\n**Example**: To see what classes are available in a `from` clause after `import javascript`:\n\n```text\nTool: codeql_lsp_completion\nParameters:\n file_path: /path/to/your/query.ql\n line: 9 # 0-based line of the `from` clause\n character: 5 # position after `from ` where you want completions\n workspace_uri: /path/to/pack-root # directory containing codeql-pack.yml\n```\n\nCompletions include class names with full documentation. For example, requesting\ncompletions in a JavaScript query\'s `from` clause returns 150+ types like\n`CallNode`, `PropWrite`, `RemoteFlowSource`, etc., each with docstrings.\n\n**Exploring member predicates**: To see what methods a variable offers, request\ncompletions after the dot. For example, if `pw` is typed as `DataFlow::PropWrite`,\nrequesting completions at the position after `pw.` returns all member predicates\nlike `getPropertyName()`, `getRhs()`, `getBase()`, `writes(base, prop, rhs)`,\neach with full signature and documentation.\n\n## Step 2: Navigate to Definitions\n\nUse #codeql_lsp_definition to find where a class, predicate, or module is defined.\nThis returns the file URI and line range of the definition \u2014 even into library pack\nfiles you haven\'t opened.\n\n```text\nTool: codeql_lsp_definition\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line containing the symbol\n character: 30 # 0-based column within the symbol name\n workspace_uri: /path/to/pack-root\n```\n\n**Example**: Navigating to `RemoteFlowSource` at line 12, character 30 returns:\n\n```text\nuri: file:///.../.codeql/packages/codeql/javascript-all/2.6.19/\n semmle/javascript/security/dataflow/RemoteFlowSources.qll\nstartLine: 14, startCharacter: 17\n```\n\nYou can then read that file to understand the class\'s API. This is how you discover\nwhat predicates a type offers without documentation \u2014 go to the definition and read\nthe source.\n\n## Step 3: Find All References\n\nUse #codeql_lsp_references to find how a symbol is used across the workspace.\n\n```text\nTool: codeql_lsp_references\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line\n character: 30 # 0-based column within the symbol\n workspace_uri: /path/to/pack-root\n```\n\n> **Scope note**: References are scoped to the pack identified by `workspace_uri`.\n> To find usages in library code, point `workspace_uri` to the library pack root.\n> For usages within your own pack only, point it to your pack root.\n\nThis is invaluable for learning how experienced query authors use a predicate \u2014\nfind real usage examples instead of guessing from documentation.\n\n## Step 4: Locate Symbols with Position Finders\n\nUse #find_predicate_position and #find_class_position to locate where a specific\nsymbol is defined in a file. These return **1-based** line/column positions.\n\n```text\nTool: find_predicate_position\nParameters:\n file: /path/to/your/query.ql\n name: isSource\nReturns: { start_line: 12, start_col: 13, end_line: 12, end_col: 20 }\n```\n\n> **Note**: #find_class_position finds `class` definitions only \u2014 it does not find\n> `module` definitions. Use #find_predicate_position for predicates inside modules.\n\n**Combining with LSP tools**: To navigate to a predicate\'s definition in library code:\n\n1. Use #find_predicate_position to get its 1-based position\n2. Subtract 1 from line/col to convert to 0-based\n3. Pass to #codeql_lsp_definition to jump to the underlying type\n\n## Step 5: Quick-Evaluate Individual Predicates\n\nUse #quick_evaluate to evaluate a single predicate or class against a database\nwithout running the full query. This is the fastest way to debug whether a predicate\nmatches what you expect.\n\n```text\nTool: quick_evaluate\nParameters:\n file: /path/to/your/query.ql\n db: /path/to/test-database.testproj\n symbol: isSink\n output_path: /tmp/quickeval-results # optional, for inspecting bqrs output\n```\n\nThe tool evaluates just that symbol (predicate or class) and returns the result path.\nUse #codeql_bqrs_decode on the output to inspect results in CSV or JSON format.\n\n## Step 6: Validate at Multiple Levels\n\nUse the right validation tool for each situation:\n\n| Tool | Use When | Input | Resolves Imports? |\n| ----------------------- | --------------------------------------- | ------------------ | ------------------- |\n| #validate_codeql_query | Quick structural check | Inline QL string | No (heuristic only) |\n| #codeql_lsp_diagnostics | Syntax/semantic validation of fragments | Inline QL string | No |\n| #codeql_query_compile | Full compilation check | On-disk `.ql` file | Yes |\n| #codeql_test_run | End-to-end result validation | Test directory | Yes |\n\n**#codeql_lsp_diagnostics** validates QL syntax and semantics for inline code snippets,\nbut **cannot resolve `import` statements** (like `import javascript`). Use it for:\n\n- Checking predicate signatures and QL syntax\n- Verifying `from`/`where`/`select` clause structure\n- Catching type errors in import-free QL fragments\n\nFor queries with imports, always use #codeql_query_compile on the saved file.\n\n## Iterative Development Loop\n\n```text\n1. Write/modify a clause in the query file (save to disk)\n \u2193\n2. codeql_lsp_completion \u2192 verify context is valid (non-empty = good)\n \u2193\n3. codeql_query_compile \u2192 check for compilation errors\n \u2193\n4. codeql_test_run \u2192 validate against expected results\n \u2193\n5. If unexpected results: quick_evaluate on individual predicates\n \u2193\n6. If predicate is wrong: codeql_lsp_completion to explore the API\n \u2193\n7. If types are unclear: codeql_lsp_definition to read the source\n \u2193\n8. If stuck: codeql_lsp_references to find usage examples\n \u2193\n9. Repeat from step 1\n```\n\n## Worked Example: Building a Taint-Tracking Query\n\nThis example shows the tools in action for building a JavaScript XSS query.\n\n### 1. Create the query file and install dependencies\n\nWrite a `.ql` file with `import javascript` and a skeleton `from`/`where`/`select`.\nRun #codeql_pack_install on the pack directory.\n\n### 2. Explore sink types\n\nRequest completions in the `from` clause to discover `DataFlow::PropWrite`:\n\n```text\ncodeql_lsp_completion(file_path=..., line=9, character=5, workspace_uri=pack_root)\n\u2192 155 completions including PropWrite, CallNode, MethodCallNode, ...\n```\n\n### 3. Explore `PropWrite` member predicates\n\nAfter typing `pw.` in the `where` clause, request completions:\n\n```text\ncodeql_lsp_completion(file_path=..., line=12, character=9, workspace_uri=pack_root)\n\u2192 43 predicates: getPropertyName(), getRhs(), getBase(), writes(), ...\n```\n\n### 4. Navigate to `RemoteFlowSource` definition\n\n```text\ncodeql_lsp_definition(file_path=..., line=11, character=30, workspace_uri=pack_root)\n\u2192 RemoteFlowSources.qll line 14 in codeql/javascript-all\n```\n\n### 5. Compile and test incrementally\n\n```text\ncodeql_query_compile(query=file_path) \u2192 check for errors\ncodeql_test_run(tests=[test_dir], learn=true) \u2192 populate .expected files\n```\n\n### 6. Debug a predicate in isolation\n\n```text\nfind_predicate_position(file=..., name="isSink") \u2192 line 16, col 13\nquick_evaluate(file=..., db=test.testproj, symbol="isSink") \u2192 inspect results\n```\n\n## Important Notes\n\n- **All LSP tools use 0-based positions**. #find_class_position and\n #find_predicate_position return 1-based positions. Convert before combining.\n- **`workspace_uri` must be the pack root** (the directory containing\n `codeql-pack.yml`). Without it, completions and definitions will be empty.\n- **Run #codeql_pack_install first**. LSP tools require resolved dependencies.\n- **#codeql_lsp_diagnostics cannot resolve imports**. For `import javascript`\n and similar, use #codeql_query_compile on the on-disk file instead.\n- **#find_class_position finds `class` only**, not `module` definitions.\n Use grep or #find_predicate_position for predicates inside modules.\n- **#codeql_lsp_references scope** depends on `workspace_uri`. Point it at\n a library pack root to find usages across library code.\n';
64269
+ var ql_lsp_iterative_development_prompt_default = '---\nagent: agent\n---\n\n# Iterative CodeQL Development with LSP Tools\n\nUse the MCP server tools from this prompt to iteratively develop and refine CodeQL queries using the LSP-powered tools.\nThese "iterative" tools work entirely through file paths and numeric positions.\nEvery operation is expressible as a tool call with explicit `file_path`, `line`, and `character` parameters.\nThus, this prompt can be used in any environment where the query files are on disk, and it does not require any special editor integration.\n\n## Use This Prompt When\n\n- Exploring unfamiliar CodeQL libraries to discover available classes and predicates\n- Incrementally building a query clause-by-clause with real-time feedback\n- Navigating from a type usage to its definition to understand its API\n- Finding all usages of a predicate to learn patterns from existing queries\n- Validating query fragments before assembling a complete query\n- Debugging individual predicates by evaluating them in isolation against a database\n\n## Prerequisites\n\n1. A CodeQL pack with `codeql-pack.yml` on disk\n2. Dependencies installed via #codeql_pack_install (pointing at the pack directory)\n3. Query files saved to disk (LSP tools operate on files, not inline strings)\n\n## Key Concept: Positions Are File Path + Line + Character\n\nAll LSP tools identify locations using three values:\n\n- `file_path`: absolute path to a `.ql` or `.qll` file\n- `line`: **0-based** line number (line 1 in the file = `line: 0`)\n- `character`: **0-based** column offset within that line\n\nThe `workspace_uri` parameter must point to the **pack root directory** (the folder\ncontaining `codeql-pack.yml`) for import resolution to work. Without it, completions\nand definitions for imported libraries will be empty.\n\n> **Critical**: LSP line/character positions are 0-based, but `read_file`,\n> #find_predicate_position, and #find_class_position return 1-based positions.\n> Always subtract 1 when passing their output to LSP tools.\n\n## Step 1: Discover Available Types with Completions\n\nUse #codeql_lsp_completion to explore what types and predicates are available at any\nposition in a query file. This replaces manual documentation browsing.\n\n**Example**: To see what classes are available in a `from` clause after `import javascript`:\n\n```text\nTool: codeql_lsp_completion\nParameters:\n file_path: /path/to/your/query.ql\n line: 9 # 0-based line of the `from` clause\n character: 5 # position after `from ` where you want completions\n workspace_uri: /path/to/pack-root # directory containing codeql-pack.yml\n```\n\nCompletions include class names with full documentation. For example, requesting\ncompletions in a JavaScript query\'s `from` clause returns 150+ types like\n`CallNode`, `PropWrite`, `RemoteFlowSource`, etc., each with docstrings.\n\n**Exploring member predicates**: To see what methods a variable offers, request\ncompletions after the dot. For example, if `pw` is typed as `DataFlow::PropWrite`,\nrequesting completions at the position after `pw.` returns all member predicates\nlike `getPropertyName()`, `getRhs()`, `getBase()`, `writes(base, prop, rhs)`,\neach with full signature and documentation.\n\n## Step 2: Navigate to Definitions\n\nUse #codeql_lsp_definition to find where a class, predicate, or module is defined.\nThis returns the file URI and line range of the definition \u2014 even into library pack\nfiles you haven\'t opened.\n\n```text\nTool: codeql_lsp_definition\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line containing the symbol\n character: 30 # 0-based column within the symbol name\n workspace_uri: /path/to/pack-root\n```\n\n**Example**: Navigating to `RemoteFlowSource` at line 12, character 30 returns:\n\n```text\nuri: file:///.../.codeql/packages/codeql/javascript-all/2.6.19/\n semmle/javascript/security/dataflow/RemoteFlowSources.qll\nstartLine: 14, startCharacter: 17\n```\n\nYou can then read that file to understand the class\'s API. This is how you discover\nwhat predicates a type offers without documentation \u2014 go to the definition and read\nthe source.\n\n## Step 3: Find All References\n\nUse #codeql_lsp_references to find how a symbol is used across the workspace.\n\n```text\nTool: codeql_lsp_references\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line\n character: 30 # 0-based column within the symbol\n workspace_uri: /path/to/pack-root\n```\n\n> **Scope note**: References are scoped to the pack identified by `workspace_uri`.\n> To find usages in library code, point `workspace_uri` to the library pack root.\n> For usages within your own pack only, point it to your pack root.\n\nThis is invaluable for learning how experienced query authors use a predicate \u2014\nfind real usage examples instead of guessing from documentation.\n\n## Step 4: Locate Symbols with Position Finders\n\nUse #find_predicate_position and #find_class_position to locate where a specific\nsymbol is defined in a file. These return **1-based** line/column positions.\n\n```text\nTool: find_predicate_position\nParameters:\n file: /path/to/your/query.ql\n name: isSource\nReturns: { start_line: 12, start_col: 13, end_line: 12, end_col: 20 }\n```\n\n> **Note**: #find_class_position finds `class` definitions only \u2014 it does not find\n> `module` definitions. Use #find_predicate_position for predicates inside modules,\n> or use #search_ql_code to search across QL files by text or regex pattern.\n\n**Combining with LSP tools**: To navigate to a predicate\'s definition in library code:\n\n1. Use #find_predicate_position to get its 1-based position\n2. Subtract 1 from line/col to convert to 0-based\n3. Pass to #codeql_lsp_definition to jump to the underlying type\n\n## Step 5: Quick-Evaluate Individual Predicates\n\nUse #quick_evaluate to evaluate a single predicate or class against a database\nwithout running the full query. This is the fastest way to debug whether a predicate\nmatches what you expect.\n\n```text\nTool: quick_evaluate\nParameters:\n file: /path/to/your/query.ql\n db: /path/to/test-database.testproj\n symbol: isSink\n output_path: /tmp/quickeval-results # optional, for inspecting bqrs output\n```\n\nThe tool evaluates just that symbol (predicate or class) and returns the result path.\nUse #codeql_bqrs_decode on the output to inspect results in CSV or JSON format.\n\n## Step 6: Validate at Multiple Levels\n\nUse the right validation tool for each situation:\n\n| Tool | Use When | Input | Resolves Imports? |\n| ----------------------- | --------------------------------------- | ------------------ | ------------------- |\n| #validate_codeql_query | Quick structural check | Inline QL string | No (heuristic only) |\n| #codeql_lsp_diagnostics | Syntax/semantic validation of fragments | Inline QL string | No |\n| #codeql_query_compile | Full compilation check | On-disk `.ql` file | Yes |\n| #codeql_test_run | End-to-end result validation | Test directory | Yes |\n\n**#codeql_lsp_diagnostics** validates QL syntax and semantics for inline code snippets,\nbut **cannot resolve `import` statements** (like `import javascript`). Use it for:\n\n- Checking predicate signatures and QL syntax\n- Verifying `from`/`where`/`select` clause structure\n- Catching type errors in import-free QL fragments\n\nFor queries with imports, always use #codeql_query_compile on the saved file.\n\n## Iterative Development Loop\n\n```text\n1. Write/modify a clause in the query file (save to disk)\n \u2193\n2. codeql_lsp_completion \u2192 verify context is valid (non-empty = good)\n \u2193\n3. codeql_query_compile \u2192 check for compilation errors\n \u2193\n4. codeql_test_run \u2192 validate against expected results\n \u2193\n5. If unexpected results: quick_evaluate on individual predicates\n \u2193\n6. If predicate is wrong: codeql_lsp_completion to explore the API\n \u2193\n7. If types are unclear: codeql_lsp_definition to read the source\n \u2193\n8. If stuck: codeql_lsp_references to find usage examples\n \u2193\n9. Repeat from step 1\n```\n\n## Worked Example: Building a Taint-Tracking Query\n\nThis example shows the tools in action for building a JavaScript XSS query.\n\n### 1. Create the query file and install dependencies\n\nWrite a `.ql` file with `import javascript` and a skeleton `from`/`where`/`select`.\nRun #codeql_pack_install on the pack directory.\n\n### 2. Explore sink types\n\nRequest completions in the `from` clause to discover `DataFlow::PropWrite`:\n\n```text\ncodeql_lsp_completion(file_path=..., line=9, character=5, workspace_uri=pack_root)\n\u2192 155 completions including PropWrite, CallNode, MethodCallNode, ...\n```\n\n### 3. Explore `PropWrite` member predicates\n\nAfter typing `pw.` in the `where` clause, request completions:\n\n```text\ncodeql_lsp_completion(file_path=..., line=12, character=9, workspace_uri=pack_root)\n\u2192 43 predicates: getPropertyName(), getRhs(), getBase(), writes(), ...\n```\n\n### 4. Navigate to `RemoteFlowSource` definition\n\n```text\ncodeql_lsp_definition(file_path=..., line=11, character=30, workspace_uri=pack_root)\n\u2192 RemoteFlowSources.qll line 14 in codeql/javascript-all\n```\n\n### 5. Compile and test incrementally\n\n```text\ncodeql_query_compile(query=file_path) \u2192 check for errors\ncodeql_test_run(tests=[test_dir], learn=true) \u2192 populate .expected files\n```\n\n### 6. Debug a predicate in isolation\n\n```text\nfind_predicate_position(file=..., name="isSink") \u2192 line 16, col 13\nquick_evaluate(file=..., db=test.testproj, symbol="isSink") \u2192 inspect results\n```\n\n## Important Notes\n\n- **All LSP tools use 0-based positions**. #find_class_position and\n #find_predicate_position return 1-based positions. Convert before combining.\n- **`workspace_uri` must be the pack root** (the directory containing\n `codeql-pack.yml`). Without it, completions and definitions will be empty.\n- **Run #codeql_pack_install first**. LSP tools require resolved dependencies.\n- **#codeql_lsp_diagnostics cannot resolve imports**. For `import javascript`\n and similar, use #codeql_query_compile on the on-disk file instead.\n- **#find_class_position finds `class` only**, not `module` definitions.\n Use #search_ql_code or #find_predicate_position for predicates inside modules.\n- **#codeql_lsp_references scope** depends on `workspace_uri`. Point it at\n a library pack root to find usages across library code.\n';
63852
64270
 
63853
64271
  // src/prompts/ql-tdd-advanced.prompt.md
63854
- var ql_tdd_advanced_prompt_default = '---\nagent: agent\n---\n\n# Advanced Test-Driven CodeQL Query Development\n\nThis advanced guide builds on the basic TDD methodology with powerful MCP server tools for deeper code analysis. Use this when developing complex queries that require understanding AST structure, control flow, and call relationships.\n\nFor basic TDD workflow, see: `codeql://prompts/ql-tdd-basic`\n\n## When to Use This Advanced Guide\n\n- **Complex AST patterns**: When you need to understand how CodeQL represents specific language constructs\n- **Control flow queries**: When analyzing program flow, branching, or loop structures\n- **Call graph analysis**: When tracing function calls or method invocations\n- **Iterative refinement**: When debugging queries that don\'t produce expected results\n- **Performance optimization**: When understanding query evaluation patterns\n\n## Core Advanced Tools\n\n### 1. AST/CFG Visualization with #codeql_query_run\n\nUse the bundled tools queries to visualize code structure:\n\n```typescript\n// Generate Abstract Syntax Tree for test code\ncodeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "java", // or "javascript", "python", "cpp", etc.\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast-output.txt"\n}\n\n// Generate Control Flow Graph\ncodeql_query_run: {\n queryName: "PrintCFG",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/cfg-output.txt"\n}\n\n// Analyze outbound calls from a function\ncodeql_query_run: {\n queryName: "CallGraphFrom",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n sourceFunction: "myFunction",\n format: "sarif-latest"\n}\n\n// Analyze inbound calls to a function\ncodeql_query_run: {\n queryName: "CallGraphTo",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n targetFunction: "targetMethod",\n format: "sarif-latest"\n}\n```\n\n**Critical**: Always verify that tools queries return **non-empty output** with actual nodes/edges, not just headers.\n\n### 2. Quick Evaluation with #quick_evaluate\n\nUse #quick_evaluate for rapid iteration on specific predicates or classes:\n\n```typescript\n// First, find the position of a predicate\nfind_predicate_position: {\n file: "/path/to/Query.ql",\n name: "isVulnerableSink"\n}\n\n// Then evaluate just that predicate\nquick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "isVulnerableSink",\n output_path: "/tmp/quickeval.bqrs"\n}\n\n// Or evaluate a specific class\n// NOTE: find_class_position finds `class` definitions only, not `module` definitions\nfind_class_position: {\n file: "/path/to/Query.ql",\n name: "ThrowingMethodCall"\n}\n\nquick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "ThrowingMethodCall"\n}\n```\n\n### 3. LSP-Powered Code Navigation\n\nUse the LSP tools for real-time code exploration during query development:\n\n```typescript\n// Discover available types after `import javascript`\ncodeql_lsp_completion: {\n file_path: "/path/to/Query.ql",\n line: 5, // 0-based line with `from` clause\n character: 5, // 0-based column position\n workspace_uri: "/path/to/pack-root" // REQUIRED: directory containing codeql-pack.yml\n}\n\n// Navigate to a class definition to see its predicates\ncodeql_lsp_definition: {\n file_path: "/path/to/Query.ql",\n line: 5, // 0-based line containing the class name\n character: 10, // 0-based column on the class name\n workspace_uri: "/path/to/pack-root"\n}\n\n// Find all usages of a predicate across the pack\ncodeql_lsp_references: {\n file_path: "/path/to/Query.ql",\n line: 8,\n character: 5,\n workspace_uri: "/path/to/pack-root"\n}\n```\n\n**Important LSP tool notes**:\n\n- `workspace_uri` must be a **plain directory path** (not a `file://` URI) pointing to the pack root containing `codeql-pack.yml`\n- All LSP tools use **0-based** line/character positions\n- #find_predicate_position and #find_class_position return **1-based** positions \u2014 subtract 1 before passing to LSP tools\n- Run #codeql_pack_install before using LSP tools \u2014 they require resolved dependencies\n- Request completions **after a dot** (e.g., `pw.`) to see all member predicates with full documentation\n\n### 4. Query File Discovery with #find_codeql_query_files\n\nUse this tool frequently to understand query dependencies and test structure:\n\n```typescript\nfind_codeql_query_files: {\n queryPath: \'/path/to/Query.ql\';\n}\n// Returns: query file, test directory, test files, metadata, dependencies\n```\n\n## Advanced TDD Workflow\n\n### Phase 0: Test Environment Setup (Critical for Java)\n\nFor Java tests that depend on external libraries (JUnit, etc.), create an `options` file in each test directory:\n\n```text\n//semmle-extractor-options: --javac-args -cp ${testdir}/../../stubs/junit-4.13:${testdir}/../../stubs/junit-jupiter-api-5.2.0\n```\n\n**Key points**:\n\n- `${testdir}` is relative to the test directory containing the `options` file\n- Use `:` (colon) to separate multiple classpath entries\n- Stub files must contain minimal class/interface definitions for compilation\n\n### Phase 1: Deep Code Analysis\n\nBefore writing any query logic:\n\n1. **Extract test database**:\n\n ```typescript\n codeql_test_extract: {\n testPath: "/path/to/test/QueryTest",\n searchPath: "/path/to/pack"\n }\n ```\n\n2. **Generate and study the AST**:\n\n ```typescript\n codeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast.txt"\n }\n ```\n\n3. **Identify key AST classes and predicates** from the output:\n - Note the class names (e.g., `MethodCall`, `TryStmt`, `LambdaExpr`)\n - Note parent-child relationships\n - Identify which nodes correspond to your test cases\n\n4. **Generate CFG if analyzing control flow**:\n\n ```typescript\n codeql_query_run: {\n queryName: "PrintCFG",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/cfg.txt"\n }\n ```\n\n### Phase 2: Iterative Predicate Development\n\nInstead of writing the full query at once:\n\n1. **Start with a single class or predicate**:\n\n ```ql\n class MyPattern extends MethodCall {\n MyPattern() {\n this.getMethod().hasName("targetMethod")\n }\n }\n ```\n\n2. **Use #quick_evaluate to test it**:\n\n ```typescript\n quick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "MyPattern"\n }\n ```\n\n3. **Refine based on results**:\n - Too many results? Add constraints\n - Too few results? Relax constraints\n - Wrong results? Study AST output again\n\n4. **Repeat for each component** before combining\n\n### Phase 3: Incremental Query Assembly\n\n1. **Combine validated predicates** into the main query\n2. **Run full tests** after each combination:\n\n ```typescript\n codeql_test_run: {\n testPath: "/path/to/test/QueryTest",\n searchPath: "/path/to/pack"\n }\n ```\n\n3. **Use #find_codeql_query_files** to track all related files:\n\n ```typescript\n find_codeql_query_files: {\n queryPath: \'/path/to/Query.ql\';\n }\n ```\n\n## Common Advanced Patterns\n\n### Pattern: Understanding Nested Structures\n\nWhen your query involves nested constructs (e.g., lambdas inside method calls):\n\n```ql\n// First, find the outer construct\nclass OuterPattern extends MethodCall {\n OuterPattern() {\n this.getMethod().hasName("assertThrows")\n }\n\n // Navigate to inner construct\n Expr getLambdaBody() {\n exists(LambdaExpr le |\n le = this.getAChildExpr() and\n result = le.getExprBody()\n )\n }\n}\n```\n\nUse `PrintAST` to understand the parent-child relationships.\n\n### Pattern: Control Flow Dependencies\n\nWhen your query needs to understand execution order:\n\n```ql\n// Use CFG to understand which statements precede others\npredicate precedesInBlock(Stmt s1, Stmt s2) {\n exists(BasicBlock bb |\n s1.getBasicBlock() = bb and\n s2.getBasicBlock() = bb and\n s1.getLocation().getStartLine() < s2.getLocation().getStartLine()\n )\n}\n```\n\nUse `PrintCFG` to verify the control flow structure.\n\n### Pattern: Call Chain Analysis\n\nWhen tracing calls through multiple functions:\n\n```typescript\n// First, understand the call graph from your entry point\ncodeql_query_run: {\n queryName: "CallGraphFrom",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n sourceFunction: "entryPoint"\n}\n\n// Then trace back from your target\ncodeql_query_run: {\n queryName: "CallGraphTo",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n targetFunction: "sensitiveOperation"\n}\n```\n\n## Debugging Tips\n\n### When Results Are Empty\n\n1. **Check AST first**: Run `PrintAST` to verify the code structure matches expectations\n2. **Simplify the query**: Remove constraints one by one using #quick_evaluate\n3. **Check enclosing callables**: Lambda bodies may have different `getEnclosingCallable()` than expected\n4. **Verify test database extraction**: Ensure the `.testproj` directory was created successfully\n\n### When Results Are Incorrect\n\n1. **Quick evaluate individual predicates**: Isolate which part is wrong\n2. **Compare with AST output**: Verify your understanding of the structure\n3. **Check for missing cases**: Your pattern may not cover all code variations\n\n### When Compilation Fails with "override" Error\n\nIf you see `annotation \'override\' missing on predicate`, you\'ve accidentally created a predicate with the same name as one in the parent class. **Rename your predicate** to avoid the conflict:\n\n```ql\n// BAD: Method already has getAThrownExceptionType()\nclass ThrowingMethod extends Method {\n RefType getAThrownExceptionType() { ... } // Error!\n}\n\n// GOOD: Use a distinct name\nclass ThrowingMethod extends Method {\n RefType getDeclaredExceptionType() { ... } // Works\n}\n```\n\n### When Query Is Slow\n\n1. **Enable evaluator logs**:\n\n ```typescript\n codeql_query_run: {\n query: "/path/to/Query.ql",\n database: "/path/to/db",\n "evaluator-log": "/path/to/log.json",\n "evaluator-log-level": 5\n }\n ```\n\n2. **Generate log summary**:\n\n ```typescript\n codeql_generate_log_summary: {\n inputLog: "/path/to/log.json",\n format: "text"\n }\n ```\n\n3. **Profile from evaluator logs** (after step 1 produces a log file):\n\n ```typescript\n profile_codeql_query_from_logs: {\n evaluatorLog: \'/path/to/log.json\';\n }\n ```\n\n## Checklist for Complex Queries\n\n### Before Starting\n\n- [ ] Test database extracted successfully\n- [ ] `PrintAST` output reviewed and understood\n- [ ] Key AST classes identified\n- [ ] Test cases cover positive, negative, and edge cases\n\n### During Development\n\n- [ ] Each predicate/class tested with #quick_evaluate\n- [ ] #find_codeql_query_files used to track dependencies\n- [ ] CFG consulted for control flow patterns\n- [ ] Call graphs generated for cross-function analysis\n\n### After Each Change\n\n- [ ] Query compiles with #codeql_query_compile\n- [ ] Quick evaluation shows expected results\n- [ ] Full tests pass with #codeql_test_run\n- [ ] No duplicate or missing results\n\n### Final Validation\n\n- [ ] All test cases pass\n- [ ] No false positives in results\n- [ ] No false negatives (all expected cases caught)\n- [ ] Query formatted with #codeql_query_format\n- [ ] Performance acceptable (check with #profile_codeql_query_from_logs)\n\n## Test Acceptance Workflow\n\nWhen your query produces correct results but differs from the `.expected` file:\n\n1. **Review the `.actual` file** to verify results are correct\n2. **Accept the results** to update the expected baseline:\n\n ```typescript\n codeql_test_accept: {\n tests: [\'/path/to/test/QueryTest\'];\n }\n ```\n\n3. **Re-run tests** to confirm they now pass\n\n**Warning**: Only accept results after careful review. Don\'t blindly accept to make tests pass.\n\n## Tool Reference\n\n| Tool | Purpose | When to Use |\n| ------------------------------- | --------------------------------- | ------------------------------- |\n| #codeql_query_run (PrintAST) | Visualize AST structure | Start of development, debugging |\n| #codeql_query_run (PrintCFG) | Visualize control flow | Control flow queries |\n| #codeql_query_run (CallGraph\\*) | Analyze call relationships | Cross-function queries |\n| #codeql_bqrs_interpret | Convert BQRS to readable format | After running graph queries |\n| #quick_evaluate | Test individual predicates | Iterative development |\n| #find_predicate_position | Locate predicate for quickeval | Before quick_evaluate |\n| #find_class_position | Locate class for quickeval | Before quick_evaluate |\n| #find_codeql_query_files | Discover related files | Planning, tracking changes |\n| #codeql_test_accept | Accept actual results as expected | After verifying correct output |\n| #profile_codeql_query_from_logs | Performance analysis | Optimization |\n\n## Interpreting Graph Query Results\n\nWhen running `PrintAST` or `PrintCFG`, the results are stored in BQRS format. To convert to readable text:\n\n```typescript\n// After codeql_query_run produces results.bqrs\ncodeql_bqrs_interpret: {\n file: "/path/to/results.bqrs",\n format: "graphtext",\n output: "/path/to/output.txt",\n t: ["kind=graph", "id=java/tools/print-ast"]\n}\n```\n\n**Note**: The output may create a directory structure (e.g., `output.txt/java/tools/print-ast.txt`) rather than a single file.\n\n## Example: Workshop Development\n\nWhen creating CodeQL workshops, this advanced methodology is essential:\n\n1. **Analyze production query** with #find_codeql_query_files\n2. **Generate AST/CFG** for workshop test code\n3. **Decompose query** into stages, validating each with #quick_evaluate\n4. **Create exercises** with scaffolding based on AST understanding\n5. **Validate solutions** ensure each stage produces correct results\n\n### Exercise Design Tips\n\nWhen creating exercise stubs from solutions:\n\n```ql\n// Use none() as placeholder in characteristic predicates\nclass MyPattern extends MethodCall {\n MyPattern() {\n // TODO: Implement - check for methods named "targetMethod"\n // Hint: Use this.getMethod().hasName(...)\n none()\n }\n}\n```\n\n- **Include TODO comments** with specific hints\n- **Reference AST class names** students should look for\n- **Build incrementally** - each exercise should build on the previous\n- **Test both exercises and solutions** to ensure expected files are accurate\n\nSee the `create-codeql-query-development-workshop` skill for complete workshop creation guidance.\n\n## Related Resources\n\n- **Basic TDD**: `codeql://prompts/ql-tdd-basic`\n- **AST Reference**: `codeql://languages/{language}/ast`\n- **Security Patterns**: `codeql://languages/{language}/security`\n- **Performance Guide**: `codeql://patterns/performance`\n- **Workshop Skill**: `.github/skills/create-codeql-query-development-workshop/SKILL.md`\n- **Tools Validation**: `.github/skills/validate-ql-mcp-server-tools-queries/SKILL.md`\n';
64272
+ var ql_tdd_advanced_prompt_default = '---\nagent: agent\n---\n\n# Advanced Test-Driven CodeQL Query Development\n\nThis advanced guide builds on the basic TDD methodology with powerful MCP server tools for deeper code analysis. Use this when developing complex queries that require understanding AST structure, control flow, and call relationships.\n\nFor basic TDD workflow, see: `codeql://prompts/ql-tdd-basic`\n\n## When to Use This Advanced Guide\n\n- **Complex AST patterns**: When you need to understand how CodeQL represents specific language constructs\n- **Control flow queries**: When analyzing program flow, branching, or loop structures\n- **Call graph analysis**: When tracing function calls or method invocations\n- **Iterative refinement**: When debugging queries that don\'t produce expected results\n- **Performance optimization**: When understanding query evaluation patterns\n\n## Core Advanced Tools\n\n### 1. AST/CFG Visualization with #codeql_query_run\n\nUse the bundled tools queries to visualize code structure:\n\n```typescript\n// Generate Abstract Syntax Tree for test code\ncodeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "java", // or "javascript", "python", "cpp", etc.\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast-output.txt"\n}\n\n// Generate Control Flow Graph\ncodeql_query_run: {\n queryName: "PrintCFG",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/cfg-output.txt"\n}\n\n// Analyze outbound calls from a function\ncodeql_query_run: {\n queryName: "CallGraphFrom",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n sourceFunction: "myFunction",\n format: "sarif-latest"\n}\n\n// Analyze inbound calls to a function\ncodeql_query_run: {\n queryName: "CallGraphTo",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n targetFunction: "targetMethod",\n format: "sarif-latest"\n}\n```\n\n**Critical**: Always verify that tools queries return **non-empty output** with actual nodes/edges, not just headers.\n\n### 2. Quick Evaluation with #quick_evaluate\n\nUse #quick_evaluate for rapid iteration on specific predicates or classes:\n\n```typescript\n// First, find the position of a predicate\nfind_predicate_position: {\n file: "/path/to/Query.ql",\n name: "isVulnerableSink"\n}\n\n// Then evaluate just that predicate\nquick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "isVulnerableSink",\n output_path: "/tmp/quickeval.bqrs"\n}\n\n// Or evaluate a specific class\n// NOTE: find_class_position finds `class` definitions only, not `module` definitions.\n// Use search_ql_code to find module definitions or other patterns across QL files.\nfind_class_position: {\n file: "/path/to/Query.ql",\n name: "ThrowingMethodCall"\n}\n\nquick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "ThrowingMethodCall"\n}\n```\n\n### 3. LSP-Powered Code Navigation\n\nUse the LSP tools for real-time code exploration during query development:\n\n```typescript\n// Discover available types after `import javascript`\ncodeql_lsp_completion: {\n file_path: "/path/to/Query.ql",\n line: 5, // 0-based line with `from` clause\n character: 5, // 0-based column position\n workspace_uri: "/path/to/pack-root" // REQUIRED: directory containing codeql-pack.yml\n}\n\n// Navigate to a class definition to see its predicates\ncodeql_lsp_definition: {\n file_path: "/path/to/Query.ql",\n line: 5, // 0-based line containing the class name\n character: 10, // 0-based column on the class name\n workspace_uri: "/path/to/pack-root"\n}\n\n// Find all usages of a predicate across the pack\ncodeql_lsp_references: {\n file_path: "/path/to/Query.ql",\n line: 8,\n character: 5,\n workspace_uri: "/path/to/pack-root"\n}\n```\n\n**Important LSP tool notes**:\n\n- `workspace_uri` must be a **plain directory path** (not a `file://` URI) pointing to the pack root containing `codeql-pack.yml`\n- All LSP tools use **0-based** line/character positions\n- #find_predicate_position and #find_class_position return **1-based** positions \u2014 subtract 1 before passing to LSP tools\n- Run #codeql_pack_install before using LSP tools \u2014 they require resolved dependencies\n- Request completions **after a dot** (e.g., `pw.`) to see all member predicates with full documentation\n\n### 4. Query File Discovery with #find_codeql_query_files\n\nUse this tool frequently to understand query dependencies and test structure:\n\n```typescript\nfind_codeql_query_files: {\n queryPath: \'/path/to/Query.ql\';\n}\n// Returns: query file, test directory, test files, metadata, dependencies\n```\n\n## Advanced TDD Workflow\n\n### Phase 0: Test Environment Setup (Critical for Java)\n\nFor Java tests that depend on external libraries (JUnit, etc.), create an `options` file in each test directory:\n\n```text\n//semmle-extractor-options: --javac-args -cp ${testdir}/../../stubs/junit-4.13:${testdir}/../../stubs/junit-jupiter-api-5.2.0\n```\n\n**Key points**:\n\n- `${testdir}` is relative to the test directory containing the `options` file\n- Use `:` (colon) to separate multiple classpath entries\n- Stub files must contain minimal class/interface definitions for compilation\n\n### Phase 1: Deep Code Analysis\n\nBefore writing any query logic:\n\n1. **Extract test database**:\n\n ```typescript\n codeql_test_extract: {\n testPath: "/path/to/test/QueryTest",\n searchPath: "/path/to/pack"\n }\n ```\n\n2. **Generate and study the AST**:\n\n ```typescript\n codeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast.txt"\n }\n ```\n\n3. **Identify key AST classes and predicates** from the output:\n - Note the class names (e.g., `MethodCall`, `TryStmt`, `LambdaExpr`)\n - Note parent-child relationships\n - Identify which nodes correspond to your test cases\n\n4. **Generate CFG if analyzing control flow**:\n\n ```typescript\n codeql_query_run: {\n queryName: "PrintCFG",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/cfg.txt"\n }\n ```\n\n### Phase 2: Iterative Predicate Development\n\nInstead of writing the full query at once:\n\n1. **Start with a single class or predicate**:\n\n ```ql\n class MyPattern extends MethodCall {\n MyPattern() {\n this.getMethod().hasName("targetMethod")\n }\n }\n ```\n\n2. **Use #quick_evaluate to test it**:\n\n ```typescript\n quick_evaluate: {\n file: "/path/to/Query.ql",\n db: "/path/to/test.testproj",\n symbol: "MyPattern"\n }\n ```\n\n3. **Refine based on results**:\n - Too many results? Add constraints\n - Too few results? Relax constraints\n - Wrong results? Study AST output again\n\n4. **Repeat for each component** before combining\n\n### Phase 3: Incremental Query Assembly\n\n1. **Combine validated predicates** into the main query\n2. **Run full tests** after each combination:\n\n ```typescript\n codeql_test_run: {\n testPath: "/path/to/test/QueryTest",\n searchPath: "/path/to/pack"\n }\n ```\n\n3. **Use #find_codeql_query_files** to track all related files:\n\n ```typescript\n find_codeql_query_files: {\n queryPath: \'/path/to/Query.ql\';\n }\n ```\n\n## Common Advanced Patterns\n\n### Pattern: Understanding Nested Structures\n\nWhen your query involves nested constructs (e.g., lambdas inside method calls):\n\n```ql\n// First, find the outer construct\nclass OuterPattern extends MethodCall {\n OuterPattern() {\n this.getMethod().hasName("assertThrows")\n }\n\n // Navigate to inner construct\n Expr getLambdaBody() {\n exists(LambdaExpr le |\n le = this.getAChildExpr() and\n result = le.getExprBody()\n )\n }\n}\n```\n\nUse `PrintAST` to understand the parent-child relationships.\n\n### Pattern: Control Flow Dependencies\n\nWhen your query needs to understand execution order:\n\n```ql\n// Use CFG to understand which statements precede others\npredicate precedesInBlock(Stmt s1, Stmt s2) {\n exists(BasicBlock bb |\n s1.getBasicBlock() = bb and\n s2.getBasicBlock() = bb and\n s1.getLocation().getStartLine() < s2.getLocation().getStartLine()\n )\n}\n```\n\nUse `PrintCFG` to verify the control flow structure.\n\n### Pattern: Call Chain Analysis\n\nWhen tracing calls through multiple functions:\n\n```typescript\n// First, understand the call graph from your entry point\ncodeql_query_run: {\n queryName: "CallGraphFrom",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n sourceFunction: "entryPoint"\n}\n\n// Then trace back from your target\ncodeql_query_run: {\n queryName: "CallGraphTo",\n queryLanguage: "java",\n database: "/path/to/test.testproj",\n targetFunction: "sensitiveOperation"\n}\n```\n\n## Debugging Tips\n\n### When Results Are Empty\n\n1. **Check AST first**: Run `PrintAST` to verify the code structure matches expectations\n2. **Simplify the query**: Remove constraints one by one using #quick_evaluate\n3. **Check enclosing callables**: Lambda bodies may have different `getEnclosingCallable()` than expected\n4. **Verify test database extraction**: Ensure the `.testproj` directory was created successfully\n\n### When Results Are Incorrect\n\n1. **Quick evaluate individual predicates**: Isolate which part is wrong\n2. **Compare with AST output**: Verify your understanding of the structure\n3. **Check for missing cases**: Your pattern may not cover all code variations\n\n### When Compilation Fails with "override" Error\n\nIf you see `annotation \'override\' missing on predicate`, you\'ve accidentally created a predicate with the same name as one in the parent class. **Rename your predicate** to avoid the conflict:\n\n```ql\n// BAD: Method already has getAThrownExceptionType()\nclass ThrowingMethod extends Method {\n RefType getAThrownExceptionType() { ... } // Error!\n}\n\n// GOOD: Use a distinct name\nclass ThrowingMethod extends Method {\n RefType getDeclaredExceptionType() { ... } // Works\n}\n```\n\n### When Query Is Slow\n\n1. **Enable evaluator logs**:\n\n ```typescript\n codeql_query_run: {\n query: "/path/to/Query.ql",\n database: "/path/to/db",\n "evaluator-log": "/path/to/log.json",\n "evaluator-log-level": 5\n }\n ```\n\n2. **Profile from evaluator logs** (primary tool \u2014 returns compact JSON metrics plus a line-indexed detail file for targeted `read_file` access to RA operations and tuple progressions):\n\n ```typescript\n profile_codeql_query_from_logs: {\n evaluatorLog: \'/path/to/log.json\';\n }\n ```\n\n## Checklist for Complex Queries\n\n### Before Starting\n\n- [ ] Test database extracted successfully\n- [ ] `PrintAST` output reviewed and understood\n- [ ] Key AST classes identified\n- [ ] Test cases cover positive, negative, and edge cases\n\n### During Development\n\n- [ ] Each predicate/class tested with #quick_evaluate\n- [ ] #find_codeql_query_files used to track dependencies\n- [ ] CFG consulted for control flow patterns\n- [ ] Call graphs generated for cross-function analysis\n\n### After Each Change\n\n- [ ] Query compiles with #codeql_query_compile\n- [ ] Quick evaluation shows expected results\n- [ ] Full tests pass with #codeql_test_run\n- [ ] No duplicate or missing results\n\n### Final Validation\n\n- [ ] All test cases pass\n- [ ] No false positives in results\n- [ ] No false negatives (all expected cases caught)\n- [ ] Query formatted with #codeql_query_format\n- [ ] Performance acceptable (check with #profile_codeql_query_from_logs)\n\n## Test Acceptance Workflow\n\nWhen your query produces correct results but differs from the `.expected` file:\n\n1. **Review the `.actual` file** to verify results are correct\n2. **Accept the results** to update the expected baseline:\n\n ```typescript\n codeql_test_accept: {\n tests: [\'/path/to/test/QueryTest\'];\n }\n ```\n\n3. **Re-run tests** to confirm they now pass\n\n**Warning**: Only accept results after careful review. Don\'t blindly accept to make tests pass.\n\n## Tool Reference\n\n| Tool | Purpose | When to Use |\n| ------------------------------- | --------------------------------- | ------------------------------- |\n| #codeql_query_run (PrintAST) | Visualize AST structure | Start of development, debugging |\n| #codeql_query_run (PrintCFG) | Visualize control flow | Control flow queries |\n| #codeql_query_run (CallGraph\\*) | Analyze call relationships | Cross-function queries |\n| #codeql_bqrs_interpret | Convert BQRS to readable format | After running graph queries |\n| #quick_evaluate | Test individual predicates | Iterative development |\n| #find_predicate_position | Locate predicate for quickeval | Before quick_evaluate |\n| #find_class_position | Locate class for quickeval | Before quick_evaluate |\n| #find_codeql_query_files | Discover related files | Planning, tracking changes |\n| #search_ql_code | Search QL files for patterns | Finding classes, predicates |\n| #codeql_resolve_files | Find QL files by name/extension | Discovering library pack files |\n| #codeql_test_accept | Accept actual results as expected | After verifying correct output |\n| #profile_codeql_query_from_logs | Performance analysis | Optimization |\n\n## Interpreting Graph Query Results\n\nWhen running `PrintAST` or `PrintCFG`, the results are stored in BQRS format. To convert to readable text:\n\n```typescript\n// After codeql_query_run produces results.bqrs\ncodeql_bqrs_interpret: {\n file: "/path/to/results.bqrs",\n format: "graphtext",\n output: "/path/to/output.txt",\n t: ["kind=graph", "id=java/tools/print-ast"]\n}\n```\n\n**Note**: The output may create a directory structure (e.g., `output.txt/java/tools/print-ast.txt`) rather than a single file.\n\n## Example: Workshop Development\n\nWhen creating CodeQL workshops, this advanced methodology is essential:\n\n1. **Analyze production query** with #find_codeql_query_files\n2. **Generate AST/CFG** for workshop test code\n3. **Decompose query** into stages, validating each with #quick_evaluate\n4. **Create exercises** with scaffolding based on AST understanding\n5. **Validate solutions** ensure each stage produces correct results\n\n### Exercise Design Tips\n\nWhen creating exercise stubs from solutions:\n\n```ql\n// Use none() as placeholder in characteristic predicates\nclass MyPattern extends MethodCall {\n MyPattern() {\n // TODO: Implement - check for methods named "targetMethod"\n // Hint: Use this.getMethod().hasName(...)\n none()\n }\n}\n```\n\n- **Include TODO comments** with specific hints\n- **Reference AST class names** students should look for\n- **Build incrementally** - each exercise should build on the previous\n- **Test both exercises and solutions** to ensure expected files are accurate\n\nSee the `create-codeql-query-development-workshop` skill for complete workshop creation guidance.\n\n## Related Resources\n\n- **Basic TDD**: `codeql://prompts/ql-tdd-basic`\n- **AST Reference**: `codeql://languages/{language}/ast`\n- **Security Patterns**: `codeql://languages/{language}/security`\n- **Performance Guide**: `codeql://patterns/performance`\n- **Workshop Skill**: `.github/skills/create-codeql-query-development-workshop/SKILL.md`\n- **Tools Validation**: `.github/skills/validate-ql-mcp-server-tools-queries/SKILL.md`\n';
63855
64273
 
63856
64274
  // src/prompts/ql-tdd-basic.prompt.md
63857
- var ql_tdd_basic_prompt_default = '---\nagent: agent\n---\n\n# Test-Driven CodeQL Query Development Checklist\n\nUse this checklist to guide test-driven development of CodeQL queries. Follow the TDD cycle: write tests first, implement query logic, and iterate until tests pass.\n\nFor advanced techniques including AST/CFG visualization, see: `codeql://prompts/ql-tdd-advanced`\nFor detailed guidance, reference the MCP resource: `codeql://learning/test-driven-development`\n\n## TDD Workflow Checklist\n\n### Phase 1: Project Setup\n\n- [ ] **Create Query Structure**\n - Tool: #create_codeql_query\n - Specify: basePath, queryName, language, description (optional)\n - Creates: src/QueryName/QueryName.ql, test/QueryName/QueryName.qlref, test/QueryName/test-code-file\n - The .qlref file will contain the relative path: `QueryName/QueryName.ql`\n - Verify: directory structure follows CodeQL conventions with intermediate directories\n\n- [ ] **Install Pack Dependencies**\n - Tool: #codeql_pack_install\n - Install src pack dependencies\n - Install test pack dependencies\n - Verify: imports resolve without errors\n\n### Phase 2: Test Design (Red Phase)\n\n- [ ] **Design Test Cases**\n - Create positive test cases (should match)\n - Create negative test cases (should not match)\n - Create edge case tests\n - Document expected behavior in comments\n\n- [ ] **Define Expected Results**\n - Create .expected file with anticipated matches\n - Specify exact match locations (file, line, column)\n - Include expected alert messages\n\n- [ ] **Extract Test Database**\n - Tool: #codeql_test_extract\n - Extract database from test code\n - Verify: .testproj directory created\n\n### Phase 3: Analysis and Understanding\n\n- [ ] **Analyze Test Code AST**\n - Tool: #codeql_query_run with queryName: "PrintAST"\n - Use format: "graphtext" for @kind graph queries\n - Review AST structure and identify relevant classes\n\n- [ ] **Explore Available Classes and Predicates**\n - Tool: #codeql_lsp_completion at the position in the `from` clause\n - Parameters: `file_path`, `line` (0-based), `character` (0-based)\n - Set `workspace_uri` to the pack root directory (containing `codeql-pack.yml`)\n - Request completions after a dot (e.g., `pw.`) to see member predicates with docs\n - Tip: Run #codeql_pack_install first \u2014 LSP tools require resolved dependencies\n\n- [ ] **Navigate to Type Definitions**\n - Tool: #codeql_lsp_definition on a class or predicate name\n - Parameters: `file_path`, `line` (0-based), `character` (0-based), `workspace_uri`\n - Returns file URI and line range \u2014 even into library pack files\n - Read the definition source to understand available member predicates\n - Tool: #codeql_lsp_references to find usage examples across the pack\n\n For the full iterative LSP workflow, see: `codeql://prompts/ql_lsp_iterative_development`\n\n- [ ] **Reference Language Documentation**\n - Resource: `codeql://languages/{language}/ast`\n - Resource: `codeql://languages/{language}/security` (if applicable)\n - Identify AST classes and predicates needed\n\n### Phase 4: Implementation (Green Phase)\n\n- [ ] **Write Query Metadata**\n - Add @name annotation\n - Add @description annotation\n - Add @kind annotation (problem, path-problem, graph, etc.)\n - Add @id and other required metadata\n\n- [ ] **Implement Query Logic**\n - Import required libraries\n - Define necessary classes (if any)\n - Define helper predicates\n - Implement main query clause\n\n- [ ] **Compile Query**\n - Tool: #codeql_query_compile\n - Fix any compilation errors\n - Verify: query compiles successfully\n\n- [ ] **Run Tests**\n - Tool: #codeql_test_run\n - Compare actual vs expected results\n - If tests fail: adjust query logic and recompile\n - If tests pass: proceed to validation\n\n### Phase 5: Validation and Acceptance\n\n- [ ] **Verify Test Results**\n - Review all test matches\n - Confirm no false positives\n - Confirm no false negatives\n - Check edge cases behave correctly\n\n- [ ] **Accept Test Results** (only when correct)\n - Tool: #codeql_test_accept\n - Update .expected files\n - Commit accepted results\n\n### Phase 6: Refactoring and Enhancement\n\n- [ ] **Refactor Query**\n - Improve code clarity\n - Extract common logic to predicates\n - Add code comments and documentation\n - Tool: #codeql_query_format for consistent formatting\n\n- [ ] **Optimize Performance** (if needed)\n - Run with evaluator-log enabled\n - Tool: #codeql_generate_log_summary\n - Resource: `codeql://patterns/performance`\n - Optimize expensive operations\n\n- [ ] **Generate Documentation**\n - Tool: #codeql_generate_query_help\n - Review and enhance QLDoc comments\n - Document query purpose and limitations\n\n### Phase 7: Additional Testing\n\n- [ ] **Add More Test Cases**\n - Identify additional scenarios\n - Add tests for new edge cases\n - Extract new test databases\n - Run expanded test suite\n\n- [ ] **Validate Against Real Code** (optional)\n - Tool: #codeql_database_create for real codebase\n - Tool: #codeql_query_run against real database\n - Review results for false positives/negatives\n\n## Quick Command Reference\n\n### Essential Tools\n\n```typescript\n// Create query structure\ncreate_codeql_query: {\n basePath: "/path/to/query/base",\n queryName: "MySecurityQuery",\n language: "javascript",\n description: "Detects security vulnerability X"\n}\n\n// Install dependencies\ncodeql_pack_install: {\n packPath: "/path/to/pack"\n}\n\n// Extract test database\ncodeql_test_extract: {\n testPath: "/path/to/test/QueryName",\n searchPath: "/path/to/base"\n}\n\n// Analyze AST (for @kind graph queries)\ncodeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "javascript",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast-output/"\n}\n\n// Compile query\ncodeql_query_compile: {\n query: "/path/to/Query.ql",\n searchPath: "/path/to/base",\n checkOnly: true\n}\n\n// Run tests\ncodeql_test_run: {\n testPath: "/path/to/test/Query.qlref",\n searchPath: "/path/to/base"\n}\n\n// Accept results\ncodeql_test_accept: {\n testPath: "/path/to/test/Query",\n searchPath: "/path/to/base"\n}\n```\n\n## TDD Principles to Remember\n\n1. **Red \u2192 Green \u2192 Refactor**: Always start with failing tests\n2. **Test First**: Write tests before implementation\n3. **Small Steps**: Make minimal changes to pass each test\n4. **Frequent Testing**: Run tests after each change\n5. **One Concept Per Test**: Each test should verify one behavior\n6. **Keep Tests Simple**: Test code should be easy to understand\n7. **Refactor Confidently**: Tests enable safe refactoring\n\n## Common Pitfalls to Avoid\n\n- \u274C Writing query before tests\n- \u274C Accepting test results without verification\n- \u274C Skipping compilation step\n- \u274C Not using PrintAST to understand test code\n- \u274C Not using #codeql_lsp_completion to discover available types\n- \u274C Not setting `workspace_uri` when using LSP tools (completions will be empty)\n- \u274C Creating tests that are too complex\n- \u274C Ignoring false positives in results\n- \u274C Not refactoring after tests pass\n\n## Success Criteria\n\nYour query development is complete when:\n\n- \u2705 All tests pass\n- \u2705 No false positives in test results\n- \u2705 No false negatives (all expected cases caught)\n- \u2705 Query compiles without errors or warnings\n- \u2705 Code is well-documented with QLDoc comments\n- \u2705 Performance is acceptable\n- \u2705 Edge cases are covered by tests\n- \u2705 Query follows CodeQL best practices\n\n## Next Steps After Completion\n\n1. **Integration Testing**: Test against real codebases\n2. **Peer Review**: Have another developer review the query\n3. **Documentation**: Update project documentation\n4. **Regression Testing**: Add to CI/CD pipeline\n5. **Monitor Performance**: Track query performance over time\n';
64275
+ var ql_tdd_basic_prompt_default = '---\nagent: agent\n---\n\n# Test-Driven CodeQL Query Development Checklist\n\nUse this checklist to guide test-driven development of CodeQL queries. Follow the TDD cycle: write tests first, implement query logic, and iterate until tests pass.\n\nFor advanced techniques including AST/CFG visualization, see: `codeql://prompts/ql-tdd-advanced`\nFor detailed guidance, reference the MCP resource: `codeql://learning/test-driven-development`\n\n## TDD Workflow Checklist\n\n### Phase 1: Project Setup\n\n- [ ] **Create Query Structure**\n - Tool: #create_codeql_query\n - Specify: basePath, queryName, language, description (optional)\n - Creates: src/QueryName/QueryName.ql, test/QueryName/QueryName.qlref, test/QueryName/test-code-file\n - The .qlref file will contain the relative path: `QueryName/QueryName.ql`\n - Verify: directory structure follows CodeQL conventions with intermediate directories\n\n- [ ] **Install Pack Dependencies**\n - Tool: #codeql_pack_install\n - Install src pack dependencies\n - Install test pack dependencies\n - Verify: imports resolve without errors\n\n### Phase 2: Test Design (Red Phase)\n\n- [ ] **Design Test Cases**\n - Create positive test cases (should match)\n - Create negative test cases (should not match)\n - Create edge case tests\n - Document expected behavior in comments\n\n- [ ] **Define Expected Results**\n - Create .expected file with anticipated matches\n - Specify exact match locations (file, line, column)\n - Include expected alert messages\n\n- [ ] **Extract Test Database**\n - Tool: #codeql_test_extract\n - Extract database from test code\n - Verify: .testproj directory created\n\n### Phase 3: Analysis and Understanding\n\n- [ ] **Analyze Test Code AST**\n - Tool: #codeql_query_run with queryName: "PrintAST"\n - Use format: "graphtext" for @kind graph queries\n - Review AST structure and identify relevant classes\n\n- [ ] **Explore Available Classes and Predicates**\n - Tool: #codeql_lsp_completion at the position in the `from` clause\n - Parameters: `file_path`, `line` (0-based), `character` (0-based)\n - Set `workspace_uri` to the pack root directory (containing `codeql-pack.yml`)\n - Request completions after a dot (e.g., `pw.`) to see member predicates with docs\n - Tip: Run #codeql_pack_install first \u2014 LSP tools require resolved dependencies\n\n- [ ] **Navigate to Type Definitions**\n - Tool: #codeql_lsp_definition on a class or predicate name\n - Parameters: `file_path`, `line` (0-based), `character` (0-based), `workspace_uri`\n - Returns file URI and line range \u2014 even into library pack files\n - Read the definition source to understand available member predicates\n - Tool: #codeql_lsp_references to find usage examples across the pack\n\n For the full iterative LSP workflow, see: `codeql://prompts/ql_lsp_iterative_development`\n\n- [ ] **Reference Language Documentation**\n - Resource: `codeql://languages/{language}/ast`\n - Resource: `codeql://languages/{language}/security` (if applicable)\n - Identify AST classes and predicates needed\n\n### Phase 4: Implementation (Green Phase)\n\n- [ ] **Write Query Metadata**\n - Add @name annotation\n - Add @description annotation\n - Add @kind annotation (problem, path-problem, graph, etc.)\n - Add @id and other required metadata\n\n- [ ] **Implement Query Logic**\n - Import required libraries\n - Define necessary classes (if any)\n - Define helper predicates\n - Implement main query clause\n\n- [ ] **Compile Query**\n - Tool: #codeql_query_compile\n - Fix any compilation errors\n - Verify: query compiles successfully\n\n- [ ] **Run Tests**\n - Tool: #codeql_test_run\n - Compare actual vs expected results\n - If tests fail: adjust query logic and recompile\n - If tests pass: proceed to validation\n\n### Phase 5: Validation and Acceptance\n\n- [ ] **Verify Test Results**\n - Review all test matches\n - Confirm no false positives\n - Confirm no false negatives\n - Check edge cases behave correctly\n\n- [ ] **Accept Test Results** (only when correct)\n - Tool: #codeql_test_accept\n - Update .expected files\n - Commit accepted results\n\n### Phase 6: Refactoring and Enhancement\n\n- [ ] **Refactor Query**\n - Improve code clarity\n - Extract common logic to predicates\n - Add code comments and documentation\n - Tool: #codeql_query_format for consistent formatting\n\n- [ ] **Optimize Performance** (if needed)\n - Run with evaluator-log enabled\n - Tool: #profile_codeql_query_from_logs\n - Resource: `codeql://patterns/performance`\n - Optimize expensive operations\n\n- [ ] **Generate Documentation**\n - Tool: #codeql_generate_query_help\n - Review and enhance QLDoc comments\n - Document query purpose and limitations\n\n### Phase 7: Additional Testing\n\n- [ ] **Add More Test Cases**\n - Identify additional scenarios\n - Add tests for new edge cases\n - Extract new test databases\n - Run expanded test suite\n\n- [ ] **Validate Against Real Code** (optional)\n - Tool: #codeql_database_create for real codebase\n - Tool: #codeql_query_run against real database\n - Review results for false positives/negatives\n\n## Quick Command Reference\n\n### Essential Tools\n\n```typescript\n// Create query structure\ncreate_codeql_query: {\n basePath: "/path/to/query/base",\n queryName: "MySecurityQuery",\n language: "javascript",\n description: "Detects security vulnerability X"\n}\n\n// Install dependencies\ncodeql_pack_install: {\n packPath: "/path/to/pack"\n}\n\n// Extract test database\ncodeql_test_extract: {\n testPath: "/path/to/test/QueryName",\n searchPath: "/path/to/base"\n}\n\n// Analyze AST (for @kind graph queries)\ncodeql_query_run: {\n queryName: "PrintAST",\n queryLanguage: "javascript",\n database: "/path/to/test.testproj",\n format: "graphtext",\n interpretedOutput: "/path/to/ast-output/"\n}\n\n// Compile query\ncodeql_query_compile: {\n query: "/path/to/Query.ql",\n searchPath: "/path/to/base",\n checkOnly: true\n}\n\n// Run tests\ncodeql_test_run: {\n testPath: "/path/to/test/Query.qlref",\n searchPath: "/path/to/base"\n}\n\n// Accept results\ncodeql_test_accept: {\n testPath: "/path/to/test/Query",\n searchPath: "/path/to/base"\n}\n```\n\n## TDD Principles to Remember\n\n1. **Red \u2192 Green \u2192 Refactor**: Always start with failing tests\n2. **Test First**: Write tests before implementation\n3. **Small Steps**: Make minimal changes to pass each test\n4. **Frequent Testing**: Run tests after each change\n5. **One Concept Per Test**: Each test should verify one behavior\n6. **Keep Tests Simple**: Test code should be easy to understand\n7. **Refactor Confidently**: Tests enable safe refactoring\n\n## Common Pitfalls to Avoid\n\n- \u274C Writing query before tests\n- \u274C Accepting test results without verification\n- \u274C Skipping compilation step\n- \u274C Not using PrintAST to understand test code\n- \u274C Not using #codeql_lsp_completion to discover available types\n- \u274C Not setting `workspace_uri` when using LSP tools (completions will be empty)\n- \u274C Creating tests that are too complex\n- \u274C Ignoring false positives in results\n- \u274C Not refactoring after tests pass\n\n## Success Criteria\n\nYour query development is complete when:\n\n- \u2705 All tests pass\n- \u2705 No false positives in test results\n- \u2705 No false negatives (all expected cases caught)\n- \u2705 Query compiles without errors or warnings\n- \u2705 Code is well-documented with QLDoc comments\n- \u2705 Performance is acceptable\n- \u2705 Edge cases are covered by tests\n- \u2705 Query follows CodeQL best practices\n\n## Next Steps After Completion\n\n1. **Integration Testing**: Test against real codebases\n2. **Peer Review**: Have another developer review the query\n3. **Documentation**: Update project documentation\n4. **Regression Testing**: Add to CI/CD pipeline\n5. **Monitor Performance**: Track query performance over time\n';
63858
64276
 
63859
64277
  // src/prompts/run-query-and-summarize-false-positives.prompt.md
63860
64278
  var run_query_and_summarize_false_positives_prompt_default = '---\nagent: agent\n---\n\n# Run a query and describe its false positives\n\n## Task\n\nHelp a developer discover what kinds of false positives are produced by their current CodeQL query, and which of those false positive cases are most common.\n\n### Task steps:\n\n1. Read the provided CodeQL query to understand what patterns it is designed to detect.\n2. Discover the results of this query on a real database, by:\n - Running the tool #list_query_run_results to find existing runs for this query\n - If no existing runs are found, run the query on a relevant database using #codeql_query_run tool\n3. Analyze and group the results into what appear to be similar types of results. This may mean:\n - Grouping results in the same file\n - Grouping results that reference the same elements\n - Grouping results with similar messages\n4. For each group, explore the actual code for a sample of alerts in that group, using the #read_database_source tool to triage the results and determine which groups appear to be false positives\n5. For each false positive case discovered in this exploration, group them into categories of similar root causes. For example, a query might not properly account for unreachable code, or there may be a commonly used library that violates the query\'s assumptions but is actually safe.\n6. Explain these results to the user in order of most common to least common, so they can understand where their query may need improvement to reduce false positives.\n\n## Input Context\n\nYou will be provided with:\n\n- **Query Path**: The path to the CodeQL query\n\n## Analysis Guidelines\n\n### Exploring code paths\n\nThe tool #read_database_source can be used to read the code of a particular finding. A good strategy to explore the code paths of a finding is:\n\n1. Read in the immediate context of the violation.\n - Some queries may depend on later context (e.g., an "unused variable" may only be used after its declaration)\n - Some queries may depend on earlier context (e.g., "mutex not initialized" requires observing code that ran before the violation)\n - Some queries may rely on exploring other function calls.\n2. Read the interprocedural context of the violation.\n - If understanding a violation requires checking other source locations, read the beginning of the file to find what it imports, and then read those imported files to find the relevant code.\n - Selectively scan interprocedural paths. A false positive that requires tremendous code exploration to verify is less problematic than a false positive that only requires checking a small amount of code to verify.\n3. Stop early.\n - Grouping the potential false positive cases is more important than exhaustively verifying every single finding.\n - A common false positive likely introduces some false positives that are very hard to verify, so it is usually better to focus on simple cases first.\n - Truly hard-to-verify false positive cases are often in code that users don\'t expect to be conducive to static analysis, and query authors often don\'t expect their queries to work well in those cases.\n - Suggest a chainsaw approach rather than a scalpel - if a result may be a false positive, identify some simple heuristics to eliminate all such complex cases, even if such a heuristic could introduce false negatives.\n\n### What Makes a Result Likely to be a False Positive?\n\n1. **Pattern Mismatches**\n - Query pattern doesn\'t accurately match the actual code behavior\n - Missing context that would show the code is safe\n - Overly broad query logic catching benign variations\n\n2. **Safe Code Patterns**\n - Code includes proper validation before the flagged operation\n - Results in test code, example code, or mock implementations\n - Variable/function names suggesting test/example context (e.g., `testFunc`, `exampleVar`, `mockData`)\n - Defensive programming patterns present but not recognized by query\n\n3. **Context Indicators**\n - File paths suggesting test/example files (e.g., `test/`, `examples/`, `mock/`)\n - Comments indicating intentional patterns or safe usage\n - Framework-specific patterns that are safe in context\n\n4. **Technical Factors**\n - Type mismatches that make the vulnerability impossible\n - Control flow that prevents exploitation\n - Data flow interrupted by sanitization not captured in query\n\n### Important Constraints\n\n- **Be objective**: Don\'t be influenced by variable/function naming suggesting importance (e.g., "prodOnly" vs "test")\n- **Require evidence**: Base conclusions on actual code patterns, not assumptions\n- **Mark uncertainty**: Use lower confidence scores when code snippets are missing\n- **Avoid false confidence**: If you cannot determine FP status, mark confidence as low\n\n## Output Format\n\nReturn a JSON array of false-positive _groups_, ordered by the estimated prevalence or importance of the false-positive pattern (highest first):\n\n```json\n[\n {\n "groupLabel": "Test and example code with safe validation",\n "patternSummary": "Results where the flagged operation occurs in test/example files and is always preceded by input validation.",\n "resultCount": 23,\n "estimatedFpProportion": 0.9,\n "confidence": 0.85,\n "commonRootCause": "The query does not recognize common test/example locations or custom validation helpers as making the pattern safe.",\n "sampleResults": [\n {\n "sourceFile": "results-1.sarif",\n "resultIndex": 42,\n "ruleId": "query-id",\n "message": { "text": "original result message" },\n "locations": []\n }\n ],\n "reasoning": "Based on manual inspection of several alerts in this group: (1) results are consistently located under \'test/\' or \'examples/\' directories, (2) there is clear validation before the flagged operation, and (3) the query does not model the custom validation helpers used in these files."\n }\n]\n```\n\n### Field Descriptions\n\n- **groupLabel**: Short human-readable name for the false-positive category.\n- **patternSummary**: One-sentence description of the common pattern shared by results in this group.\n- **resultCount**: Number of SARIF results that belong to this group.\n- **estimatedFpProportion**: Estimated proportion of results in this group that are false positives (0.0\u20131.0).\n- **confidence**: Confidence in the group-level assessment (see guidelines below).\n- **commonRootCause**: Why the query produces false positives for this pattern.\n- **sampleResults**: A small representative sample of results illustrating the pattern.\n- **reasoning**: Detailed explanation of how the FP determination was made.\n\n### Confidence Score Guidelines\n\n- **0.8-1.0**: Strong evidence of FP (e.g., test code with clear safety patterns)\n- **0.6-0.8**: Good evidence of FP (e.g., defensive patterns present)\n- **0.4-0.6**: Moderate evidence of FP (e.g., context suggests safety but not conclusive)\n- **0.2-0.4**: Weak evidence of FP (e.g., minor indicators, missing code snippets)\n- **0.0-0.2**: Minimal evidence (uncertain, need more information)\n\n## Examples\n\n### High-Confidence FP Group Example\n\n```json\n{\n "groupLabel": "Sanitised inputs in test harnesses",\n "patternSummary": "Results in test files where sanitizeInput() is called before the database query.",\n "resultCount": 15,\n "estimatedFpProportion": 0.95,\n "confidence": 0.9,\n "commonRootCause": "Query does not model sanitizeInput() as a sanitizer.",\n "sampleResults": [\n {\n "sourceFile": "results-1.sarif",\n "resultIndex": 7,\n "ruleId": "js/sql-injection",\n "message": { "text": "Potential SQL injection" },\n "locations": []\n }\n ],\n "reasoning": "False positive group: (1) File paths like \'test/unit/database-mock.test.js\' indicate test code, (2) Query doesn\'t recognize that \'sanitizeInput()\' is called before database query, (3) All 15 results share this pattern."\n}\n```\n\n### Low-Confidence FP Group Example\n\n```json\n{\n "groupLabel": "File utility handlers with unclear validation",\n "patternSummary": "Results in src/utils/ files where path validation may or may not be present.",\n "resultCount": 4,\n "estimatedFpProportion": 0.5,\n "confidence": 0.3,\n "commonRootCause": "Unclear whether custom path validation is sufficient.",\n "sampleResults": [\n {\n "sourceFile": "results-1.sarif",\n "resultIndex": 22,\n "ruleId": "js/path-injection",\n "message": { "text": "Potential path traversal" },\n "locations": []\n }\n ],\n "reasoning": "Possibly false positive: (1) No code snippets available in SARIF, (2) File path \'src/utils/fileHandler.js\' doesn\'t indicate test code, (3) Cannot verify if proper path validation exists. Low confidence due to missing context."\n}\n```\n\n## Processing Instructions\n\n1. **Review SARIF results** and group them by common patterns\n2. **Analyze available context** (code snippets, file paths, messages) for each group\n3. **Compare against query logic** to understand what pattern was detected\n4. **Identify FP indicators** based on guidelines above\n5. **Assign group-level confidence scores** reflecting evidence strength\n6. **Write clear reasoning** for each group explaining the assessment\n7. **Sort groups** by estimated prevalence / importance (descending)\n\n## Important Notes\n\n- A result should belong to at most one FP group\n- When in doubt, prefer lower confidence scores\n- Missing code snippets should always reduce confidence\n- Test/example code is more likely to be FP but not always\n- Focus on technical evidence, not code naming conventions\n';
@@ -63866,7 +64284,7 @@ var sarif_rank_false_positives_prompt_default = '---\nagent: agent\n---\n\n# Eva
63866
64284
  var sarif_rank_true_positives_prompt_default = '---\nagent: agent\n---\n\n# Evaluate SARIF Results for True Positives\n\n## Task\n\nAnalyze SARIF results from a CodeQL query and identify the most likely **True Positives (TPs)** - results that correctly identify real security vulnerabilities or code quality issues.\n\n## Input Context\n\nYou will be provided with:\n\n- **Query ID**: The CodeQL query/rule identifier\n- **Query Name**: Human-readable name of the query\n- **Query Content**: Full CodeQL query implementation\n- **SARIF Results**: Array of results to analyze\n- **Code Snippets**: When available, code snippets from SARIF physical locations\n\n## Analysis Guidelines\n\n### What Makes a Result Likely to be a True Positive?\n\n1. **Pattern Matches**\n - Query pattern accurately identifies the problematic code behavior\n - Result shows clear evidence of the vulnerability or issue\n - Code matches the exact pattern the query was designed to detect\n\n2. **Vulnerable Code Patterns**\n - User input flows to dangerous sink without proper sanitization\n - Missing security checks or validation\n - Incorrect use of security-sensitive APIs\n - Clear violation of security best practices\n\n3. **Production Code Context**\n - File paths suggesting production code (e.g., `src/`, `lib/`, `app/`)\n - NOT in test/example directories\n - Function/variable names suggesting real business logic\n - Code appears to be part of actual application functionality\n\n4. **Technical Factors**\n - Data flow from untrusted source to dangerous operation\n - Missing or insufficient sanitization\n - Exploitable control flow\n - Real security or quality implications\n\n### Important Constraints\n\n- **Be objective**: Don\'t be influenced by variable/function naming suggesting importance\n- **Require evidence**: Base conclusions on actual vulnerability patterns, not assumptions\n- **Mark uncertainty**: Use lower confidence scores when code snippets are missing\n- **Avoid false confidence**: If you cannot determine TP status, mark confidence as low\n- **Consider false positives**: Be skeptical - real vulnerabilities often have subtle mitigations\n\n### When Code Snippets Are Missing\n\nIf SARIF results lack `physicalLocation.region.snippet` or `contextRegion`:\n\n- **Lower confidence scores** (typically 0.3-0.5 instead of 0.6-0.9)\n- **Note the limitation** in reasoning\n- **Rely more on**:\n - Result message text\n - File path analysis\n - Query logic understanding\n\n## Output Format\n\nReturn a JSON array of ranked results, ordered by TP likelihood (highest first):\n\n```json\n[\n {\n "ruleId": "query-id",\n "message": { "text": "original result message" },\n "locations": [...],\n "confidence": 0.85,\n "reasoning": "This appears to be a true positive because: (1) the file path \'src/api/user-controller.js\' indicates production code, (2) user input from request parameter flows directly to SQL query without sanitization, (3) no validation or prepared statement usage detected.",\n "sourceFile": "results-1.sarif",\n "resultIndex": 15\n }\n]\n```\n\n### Confidence Score Guidelines\n\n- **0.8-1.0**: Strong evidence of TP (e.g., clear vulnerability with exploit path)\n- **0.6-0.8**: Good evidence of TP (e.g., production code with problematic pattern)\n- **0.4-0.6**: Moderate evidence of TP (e.g., pattern matches but context unclear)\n- **0.2-0.4**: Weak evidence of TP (e.g., possible issue but missing context)\n- **0.0-0.2**: Minimal evidence (uncertain, need more information)\n\n## Examples\n\n### High-Confidence TP Example\n\n```json\n{\n "ruleId": "js/sql-injection",\n "message": { "text": "Unsanitized user input in SQL query" },\n "confidence": 0.9,\n "reasoning": "True positive: (1) File path \'src/controllers/UserController.js\' indicates production code, (2) User input from req.query.userId flows directly to SQL query string concatenation, (3) No prepared statements or sanitization visible in code snippet, (4) Classic SQL injection pattern. Confidence is 0.9 not 1.0 due to possibility of sanitization elsewhere in call chain."\n}\n```\n\n### Moderate-Confidence TP Example\n\n```json\n{\n "ruleId": "js/path-injection",\n "message": { "text": "Potential path traversal vulnerability" },\n "confidence": 0.6,\n "reasoning": "Likely true positive: (1) File path \'src/utils/fileHandler.js\' suggests production utility code, (2) User-controlled filename parameter used in fs.readFile(), (3) No visible path validation, but code snippet is limited. Moderate confidence due to incomplete context - may have validation in calling code."\n}\n```\n\n### Low-Confidence TP Example (Missing Snippets)\n\n```json\n{\n "ruleId": "java/unsafe-deserialization",\n "message": { "text": "Unsafe deserialization of user data" },\n "confidence": 0.4,\n "reasoning": "Possibly a true positive: (1) File path \'src/main/java/com/app/handlers/DataHandler.java\' indicates production code, (2) Message suggests unsafe deserialization pattern, (3) No code snippets available in SARIF to verify actual vulnerability or confirm absence of mitigations. Confidence is low due to missing context."\n}\n```\n\n## Processing Instructions\n\n1. **Review each SARIF result** in the provided array\n2. **Analyze available context** (code snippets, file paths, messages)\n3. **Compare against query logic** to understand what pattern was detected\n4. **Identify TP indicators** based on guidelines above\n5. **Look for counter-evidence** (mitigations, safe patterns) that would make it an FP\n6. **Assign confidence score** reflecting evidence strength\n7. **Write clear reasoning** explaining your assessment\n8. **Sort results** by confidence score (descending)\n9. **Return top N results** as requested (or all if N not specified)\n\n## Important Notes\n\n- A result should never appear in both FP and TP rankings\n- When in doubt, prefer lower confidence scores\n- Missing code snippets should always reduce confidence\n- Production code location increases TP likelihood but is not conclusive\n- Focus on technical vulnerability evidence, not code naming conventions\n- Consider that even production code can have intentional patterns that look vulnerable but are safe\n';
63867
64285
 
63868
64286
  // src/prompts/tools-query-workflow.prompt.md
63869
- var tools_query_workflow_prompt_default = '---\nagent: agent\n---\n\n# Using CodeQL Development MCP Server Tools Queries\n\nThis guide helps you use the built-in "tools" queries (`PrintAST`, `PrintCFG`, `CallGraphFrom`, `CallGraphTo`) that ship with the CodeQL Development MCP Server to understand code structure before writing detection queries.\n\n## Why Use Tools Queries?\n\nTools queries provide essential insights into how CodeQL represents your source code:\n\n| Query | Purpose | Use When |\n| --------------- | ------------------------------------------------ | ----------------------------------------------- |\n| `PrintAST` | Visualize the Abstract Syntax Tree | Understanding code structure, finding AST nodes |\n| `PrintCFG` | Visualize Control Flow Graphs | Understanding execution paths, loop/branch flow |\n| `CallGraphFrom` | Find all functions called by a specific function | Tracing data flow through call chains |\n| `CallGraphTo` | Find all functions that call a specific function | Understanding function usage patterns |\n\n## Supported Languages\n\nTools queries are available for: `actions`, `cpp`, `csharp`, `go`, `java`, `javascript`, `python`, `ruby`, `swift`\n\n## Prerequisites\n\nBefore using tools queries, you need:\n\n1. **A CodeQL database** - Either create one or use an existing database\n2. **Source files to analyze** - The tools queries filter output to specific files\n\n## Workflow Checklist\n\n### Step 1: Identify or Create Database\n\n- [ ] **Option A: Use existing database**\n - Tool: #codeql_resolve_database\n - Verify database is valid and note the language\n\n- [ ] **Option B: Create new database**\n - Tool: #codeql_database_create\n - Parameters: `database`, `language`, `source-root`\n\n### Step 2: Run PrintAST Query\n\nThe PrintAST query outputs a hierarchical tree of AST nodes with labels.\n\n- [ ] **Execute PrintAST**\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: Your language (e.g., `"javascript"`, `"python"`, `"cpp"`)\n - `sourceFiles`: Comma-separated file names to analyze (e.g., `"main.js,utils.js"`)\n - `format`: `"graphtext"` (for human-readable output)\n\n- [ ] **Verify output contains AST nodes**\n - Look for hierarchical structure with indentation\n - Confirm nodes have `semmle.label` with class names\n - Identify relevant AST classes for your query\n\n**Example AST output structure:**\n\n```text\nTopLevelFunction\n\u251C\u2500\u2500 FunctionDeclarationEntry\n\u251C\u2500\u2500 Block\n\u2502 \u251C\u2500\u2500 DeclStmt\n\u2502 \u2502 \u2514\u2500\u2500 LocalVariable\n\u2502 \u251C\u2500\u2500 ExprStmt\n\u2502 \u2502 \u2514\u2500\u2500 FunctionCall\n\u2502 \u2514\u2500\u2500 ReturnStmt\n```\n\n### Step 3: Run PrintCFG Query (if needed)\n\nThe PrintCFG query outputs control flow nodes and edges.\n\n- [ ] **Execute PrintCFG**\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: Your language\n - `sourceFunction`: Function name to analyze (e.g., `"processData"`)\n - `format`: `"graphtext"`\n\n- [ ] **Verify output contains nodes and edges**\n - Look for `nodes` section with CFG nodes\n - Look for `edges` section with `\u2192` arrows showing flow\n - Identify control flow patterns (loops, branches)\n\n**Example CFG output structure:**\n\n```text\nnodes\n| node | semmle.label |\n| ... | entry: processData |\n| ... | if (...) |\n| ... | return |\n\nedges\n| from | to | semmle.label |\n| ... | ... | \u2192 |\n```\n\n### Step 4: Run CallGraph Queries (if needed)\n\nCall graph queries help trace function relationships.\n\n- [ ] **Execute CallGraphFrom** (to find what a function calls)\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"CallGraphFrom"`\n - `queryLanguage`: Your language\n - `sourceFunction`: Function name to trace from (e.g., `"main"`)\n - `format`: `"sarif-latest"` or `"csv"`\n\n- [ ] **Execute CallGraphTo** (to find what calls a function)\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"CallGraphTo"`\n - `queryLanguage`: Your language\n - `targetFunction`: Function name to find callers of (e.g., `"validate"`)\n - `format`: `"sarif-latest"` or `"csv"`\n\n- [ ] **Verify call relationships**\n - Confirm results show caller \u2192 callee relationships\n - Note function locations for further analysis\n\n### Step 5: Apply Insights to Query Development\n\nUse the gathered information to inform your query:\n\n- [ ] **From PrintAST**: Identify which AST classes to use in your `from` clause\n- [ ] **From PrintCFG**: Understand execution paths for control-flow-sensitive queries\n- [ ] **From CallGraph**: Map data flow paths through function boundaries\n\n## Common Patterns\n\n### Pattern 1: Finding All Function Calls\n\n```text\n1. Run PrintAST on your source file\n2. Look for FunctionCall, MethodAccess, or similar nodes\n3. Note the parent/child relationships\n4. Use those AST classes in your query\n```\n\n### Pattern 2: Tracing Data Through Functions\n\n```text\n1. Run CallGraphFrom on your entry point function\n2. Identify which functions are called\n3. Run CallGraphTo on sink functions\n4. Map the complete path from source to sink\n```\n\n### Pattern 3: Understanding Loop Structures\n\n```text\n1. Run PrintAST to find loop constructs (ForStmt, WhileStmt, etc.)\n2. Run PrintCFG on the containing function\n3. Identify back edges that represent loop iteration\n4. Use CFG analysis for loop-sensitive queries\n```\n\n## Troubleshooting\n\n| Issue | Likely Cause | Resolution |\n| --------------------- | ------------------------------------- | ------------------------------------------------------ |\n| Empty AST output | `sourceFiles` parameter not matching | Use just filenames, not full paths (e.g., `"test.js"`) |\n| Empty CFG output | `sourceFunction` not found | Check exact function name spelling |\n| Empty CallGraph | No calls exist or wrong function name | Verify function exists and has calls |\n| Query compilation err | Pack dependencies missing | Run #codeql_pack_install on the tools pack |\n\n## MCP Tools Reference\n\n| Tool | Purpose |\n| ------------------------ | ---------------------------------------------------- |\n| #codeql_query_run | Execute tools queries with parameters |\n| #codeql_resolve_database | Validate database before querying |\n| #codeql_database_create | Create database from source code |\n| #codeql_bqrs_interpret | Convert results to different formats |\n| #codeql_pack_install | Install pack dependencies if needed |\n| #codeql_lsp_completion | Explore available types after seeing AST class names |\n| #codeql_lsp_definition | Navigate to class definitions to see predicates |\n| #codeql_lsp_references | Find usage examples of a class or predicate |\n\n### Using LSP Tools After AST Analysis\n\nAfter running PrintAST and identifying relevant AST class names, use the LSP tools\nto explore those classes in your query file:\n\n1. **Write the class name** in your query\'s `from` clause and save the file\n2. **Run #codeql_lsp_completion** after the dot to see member predicates:\n - `file_path`: your query file, `line`/`character`: 0-based position after the dot\n - `workspace_uri`: the pack root directory (containing `codeql-pack.yml`)\n3. **Run #codeql_lsp_definition** on an AST class name to see its full API\n4. **Run #codeql_lsp_references** to find usage examples in the pack\n\n> **Note**: LSP tools use 0-based line/character positions. Run #codeql_pack_install\n> before using them \u2014 they require resolved dependencies. Set `workspace_uri` to\n> a plain directory path (not a `file://` URI).\n\nFor the full iterative LSP development workflow, see: `codeql://prompts/ql_lsp_iterative_development`\n';
64287
+ var tools_query_workflow_prompt_default = '---\nagent: agent\n---\n\n# Using CodeQL Development MCP Server Tools Queries\n\nThis guide helps you use the built-in "tools" queries (`PrintAST`, `PrintCFG`, `CallGraphFrom`, `CallGraphTo`) that ship with the CodeQL Development MCP Server to understand code structure before writing detection queries.\n\n## Why Use Tools Queries?\n\nTools queries provide essential insights into how CodeQL represents your source code:\n\n| Query | Purpose | Use When |\n| --------------- | ------------------------------------------------ | ----------------------------------------------- |\n| `PrintAST` | Visualize the Abstract Syntax Tree | Understanding code structure, finding AST nodes |\n| `PrintCFG` | Visualize Control Flow Graphs | Understanding execution paths, loop/branch flow |\n| `CallGraphFrom` | Find all functions called by a specific function | Tracing data flow through call chains |\n| `CallGraphTo` | Find all functions that call a specific function | Understanding function usage patterns |\n\n## Supported Languages\n\nTools queries are available for: `actions`, `cpp`, `csharp`, `go`, `java`, `javascript`, `python`, `ruby`, `swift`\n\n## Prerequisites\n\nBefore using tools queries, you need:\n\n1. **A CodeQL database** - Either create one or use an existing database\n2. **Source files to analyze** - The tools queries filter output to specific files\n\n## Workflow Checklist\n\n### Step 1: Identify or Create Database\n\n- [ ] **Option A: Use existing database**\n - Tool: #codeql_resolve_database\n - Verify database is valid and note the language\n\n- [ ] **Option B: Create new database**\n - Tool: #codeql_database_create\n - Parameters: `database`, `language`, `source-root`\n\n### Step 2: Run PrintAST Query\n\nThe PrintAST query outputs a hierarchical tree of AST nodes with labels.\n\n- [ ] **Execute PrintAST**\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: Your language (e.g., `"javascript"`, `"python"`, `"cpp"`)\n - `sourceFiles`: Comma-separated file names to analyze (e.g., `"main.js,utils.js"`)\n - `format`: `"graphtext"` (for human-readable output)\n\n- [ ] **Verify output contains AST nodes**\n - Look for hierarchical structure with indentation\n - Confirm nodes have `semmle.label` with class names\n - Identify relevant AST classes for your query\n\n**Example AST output structure:**\n\n```text\nTopLevelFunction\n\u251C\u2500\u2500 FunctionDeclarationEntry\n\u251C\u2500\u2500 Block\n\u2502 \u251C\u2500\u2500 DeclStmt\n\u2502 \u2502 \u2514\u2500\u2500 LocalVariable\n\u2502 \u251C\u2500\u2500 ExprStmt\n\u2502 \u2502 \u2514\u2500\u2500 FunctionCall\n\u2502 \u2514\u2500\u2500 ReturnStmt\n```\n\n### Step 3: Run PrintCFG Query (if needed)\n\nThe PrintCFG query outputs control flow nodes and edges.\n\n- [ ] **Execute PrintCFG**\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: Your language\n - `sourceFunction`: Function name to analyze (e.g., `"processData"`)\n - `format`: `"graphtext"`\n\n- [ ] **Verify output contains nodes and edges**\n - Look for `nodes` section with CFG nodes\n - Look for `edges` section with `\u2192` arrows showing flow\n - Identify control flow patterns (loops, branches)\n\n**Example CFG output structure:**\n\n```text\nnodes\n| node | semmle.label |\n| ... | entry: processData |\n| ... | if (...) |\n| ... | return |\n\nedges\n| from | to | semmle.label |\n| ... | ... | \u2192 |\n```\n\n### Step 4: Run CallGraph Queries (if needed)\n\nCall graph queries help trace function relationships.\n\n- [ ] **Execute CallGraphFrom** (to find what a function calls)\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"CallGraphFrom"`\n - `queryLanguage`: Your language\n - `sourceFunction`: Function name to trace from (e.g., `"main"`)\n - `format`: `"sarif-latest"` or `"csv"`\n\n- [ ] **Execute CallGraphTo** (to find what calls a function)\n - Tool: #codeql_query_run\n - Parameters:\n - `database`: Path to your CodeQL database\n - `queryName`: `"CallGraphTo"`\n - `queryLanguage`: Your language\n - `targetFunction`: Function name to find callers of (e.g., `"validate"`)\n - `format`: `"sarif-latest"` or `"csv"`\n\n- [ ] **Verify call relationships**\n - Confirm results show caller \u2192 callee relationships\n - Note function locations for further analysis\n\n### Step 5: Apply Insights to Query Development\n\nUse the gathered information to inform your query:\n\n- [ ] **From PrintAST**: Identify which AST classes to use in your `from` clause\n- [ ] **From PrintCFG**: Understand execution paths for control-flow-sensitive queries\n- [ ] **From CallGraph**: Map data flow paths through function boundaries\n\n## Common Patterns\n\n### Pattern 1: Finding All Function Calls\n\n```text\n1. Run PrintAST on your source file\n2. Look for FunctionCall, MethodAccess, or similar nodes\n3. Note the parent/child relationships\n4. Use those AST classes in your query\n```\n\n### Pattern 2: Tracing Data Through Functions\n\n```text\n1. Run CallGraphFrom on your entry point function\n2. Identify which functions are called\n3. Run CallGraphTo on sink functions\n4. Map the complete path from source to sink\n```\n\n### Pattern 3: Understanding Loop Structures\n\n```text\n1. Run PrintAST to find loop constructs (ForStmt, WhileStmt, etc.)\n2. Run PrintCFG on the containing function\n3. Identify back edges that represent loop iteration\n4. Use CFG analysis for loop-sensitive queries\n```\n\n## Troubleshooting\n\n| Issue | Likely Cause | Resolution |\n| --------------------- | ------------------------------------- | ------------------------------------------------------ |\n| Empty AST output | `sourceFiles` parameter not matching | Use just filenames, not full paths (e.g., `"test.js"`) |\n| Empty CFG output | `sourceFunction` not found | Check exact function name spelling |\n| Empty CallGraph | No calls exist or wrong function name | Verify function exists and has calls |\n| Query compilation err | Pack dependencies missing | Run #codeql_pack_install on the tools pack |\n\n## MCP Tools Reference\n\n| Tool | Purpose |\n| ------------------------ | ---------------------------------------------------- |\n| #codeql_query_run | Execute tools queries with parameters |\n| #codeql_resolve_database | Validate database before querying |\n| #codeql_database_create | Create database from source code |\n| #codeql_bqrs_interpret | Convert results to different formats |\n| #codeql_pack_install | Install pack dependencies if needed |\n| #codeql_lsp_completion | Explore available types after seeing AST class names |\n| #codeql_lsp_definition | Navigate to class definitions to see predicates |\n| #codeql_lsp_references | Find usage examples of a class or predicate |\n| #search_ql_code | Search QL source files for patterns (text or regex) |\n| #codeql_resolve_files | Find QL files by name, extension, or glob pattern |\n\n### Using LSP Tools After AST Analysis\n\nAfter running PrintAST and identifying relevant AST class names, use the LSP tools\nto explore those classes in your query file:\n\n1. **Write the class name** in your query\'s `from` clause and save the file\n2. **Run #codeql_lsp_completion** after the dot to see member predicates:\n - `file_path`: your query file, `line`/`character`: 0-based position after the dot\n - `workspace_uri`: the pack root directory (containing `codeql-pack.yml`)\n3. **Run #codeql_lsp_definition** on an AST class name to see its full API\n4. **Run #codeql_lsp_references** to find usage examples in the pack\n\n> **Note**: LSP tools use 0-based line/character positions. Run #codeql_pack_install\n> before using them \u2014 they require resolved dependencies. Set `workspace_uri` to\n> a plain directory path (not a `file://` URI).\n\nFor the full iterative LSP development workflow, see: `codeql://prompts/ql_lsp_iterative_development`\n';
63870
64288
 
63871
64289
  // src/prompts/workshop-creation-workflow.prompt.md
63872
64290
  var workshop_creation_workflow_prompt_default = '---\nagent: agent\n---\n\n# Creating CodeQL Query Development Workshops\n\nThis guide helps you create educational CodeQL query development workshops from existing production-grade queries. Workshops teach developers how to build queries incrementally through exercises and solutions.\n\n## Workshop Purpose\n\nA CodeQL workshop transforms a complex, production-ready query into a series of incremental learning stages:\n\n- **Exercises**: Incomplete query stubs with scaffolding and hints\n- **Solutions**: Complete working queries for each stage\n- **Tests**: Unit tests validating each stage works correctly\n- **Documentation**: README with learning objectives and instructions\n\n## Prerequisites\n\nBefore creating a workshop, ensure you have:\n\n1. **A production-grade CodeQL query** - The "target" query to decompose\n2. **Working unit tests** - Tests that pass for the target query\n3. **A CodeQL database** - For running tools queries and validating results\n\n## Workshop Creation Checklist\n\n### Phase 1: Analyze the Target Query\n\n- [ ] **Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` (path to the `.ql` or `.qlref` file)\n - Note: Returns query file, test files, expected results, and metadata\n\n- [ ] **Understand query logic for workshop content**\n - Prompt: `explain_codeql_query`\n - Parameters: `queryPath`, `language`, and optionally `databasePath`\n - Identify: sources, sinks, sanitizers, flow configuration\n - Generates: detailed explanation with mermaid evaluation diagram\n\n- [ ] **Verify existing tests pass**\n - Tool: #codeql_test_run\n - Parameters: `tests` (array of test directories)\n - Confirm: 100% pass rate before proceeding\n\n### Phase 2: Generate AST/CFG Understanding\n\n> **\u26A0\uFE0F CRITICAL**: Run tools queries to understand the test code structure.\n\n- [ ] **Run PrintAST on test code**\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: Your language (e.g., `"cpp"`, `"javascript"`)\n - `database`: Path to test database or extracted `.testproj`\n - `sourceFiles`: Test source file names\n - `format`: `"graphtext"`\n - Verify: Output contains hierarchical AST nodes (not empty)\n\n- [ ] **Run PrintCFG on key functions**\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: Your language\n - `database`: Path to database\n - `sourceFunction`: Key function names from test code\n - `format`: `"graphtext"`\n - Verify: Output contains nodes and edges\n\n- [ ] **Run CallGraph queries** (if query involves data flow)\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"CallGraphFrom"` or `"CallGraphTo"`\n - `database`: Path to database\n - `sourceFunction` / `targetFunction`: Relevant function names\n - Verify: Output shows call relationships\n\n### Phase 3: Plan Workshop Stages\n\nDecompose the query into 4-8 incremental stages using these strategies:\n\n#### Decomposition Strategies\n\n| Strategy | Description | Example Progression |\n| -------------------- | -------------------------------------------------------- | ------------------------------------- |\n| Syntactic \u2192 Semantic | Start with syntax, add type checking, then data flow | AST \u2192 Types \u2192 Local flow \u2192 Global |\n| Local \u2192 Global | Start with local analysis, expand to cross-procedural | Single function \u2192 Multiple functions |\n| Simple \u2192 Filtered | High recall first, then add precision filters | All calls \u2192 Specific calls \u2192 Filtered |\n| Building Blocks | Define helpers, combine into sources/sinks, connect flow | Predicates \u2192 Sources \u2192 Sinks \u2192 Config |\n\n- [ ] **Document stage progression**\n - Stage 1: Basic syntactic pattern (highest recall)\n - Stage 2-N: Add refinements (types, filters, flow)\n - Final Stage: Complete production query\n\n### Phase 4: Create Workshop Structure\n\nStandard workshop directory layout:\n\n```text\nworkshop-name/\n\u251C\u2500\u2500 codeql-workspace.yml # CodeQL workspace configuration\n\u251C\u2500\u2500 README.md # Workshop guide with instructions\n\u251C\u2500\u2500 build-databases.sh # Script to create test databases\n\u251C\u2500\u2500 exercises/ # Student exercise queries\n\u2502 \u251C\u2500\u2500 codeql-pack.yml\n\u2502 \u251C\u2500\u2500 Exercise1.ql\n\u2502 \u251C\u2500\u2500 Exercise2.ql\n\u2502 \u2514\u2500\u2500 ...\n\u251C\u2500\u2500 exercises-tests/ # Tests for exercises\n\u2502 \u251C\u2500\u2500 codeql-pack.yml\n\u2502 \u251C\u2500\u2500 Exercise1/\n\u2502 \u2502 \u251C\u2500\u2500 Exercise1.qlref\n\u2502 \u2502 \u251C\u2500\u2500 Exercise1.expected\n\u2502 \u2502 \u2514\u2500\u2500 test.ext\n\u2502 \u2514\u2500\u2500 ...\n\u251C\u2500\u2500 solutions/ # Complete solution queries\n\u2502 \u251C\u2500\u2500 codeql-pack.yml\n\u2502 \u251C\u2500\u2500 Exercise1.ql\n\u2502 \u251C\u2500\u2500 Exercise2.ql\n\u2502 \u2514\u2500\u2500 ...\n\u251C\u2500\u2500 solutions-tests/ # Tests for solutions\n\u2502 \u251C\u2500\u2500 codeql-pack.yml\n\u2502 \u2514\u2500\u2500 ...\n\u251C\u2500\u2500 tests-common/ # Shared test code\n\u2502 \u2514\u2500\u2500 test.ext\n\u2514\u2500\u2500 graphs/ # AST/CFG visualizations\n \u2514\u2500\u2500 ast-overview.txt\n```\n\n- [ ] **Create codeql-workspace.yml**\n\n ```yaml\n provide:\n - \'*/codeql-pack.yml\'\n ```\n\n- [ ] **Create pack files for each directory**\n - `exercises/codeql-pack.yml`: Query pack depending on language library\n - `exercises-tests/codeql-pack.yml`: Test pack depending on exercises\n - `solutions/codeql-pack.yml`: Query pack (same deps as exercises)\n - `solutions-tests/codeql-pack.yml`: Test pack depending on solutions\n\n### Phase 5: Create Solution Queries\n\nFor each stage, create a complete solution query. Use the iterative LSP tools\nfor efficient development (see `codeql://prompts/ql_lsp_iterative_development`):\n\n- Use #codeql_lsp_completion to explore types and member predicates while writing queries\n- Use #codeql_lsp_definition to navigate to library class definitions\n- Use #find_predicate_position + #quick_evaluate to test predicates in isolation\n- Set `workspace_uri` to the solutions pack root for dependency resolution\n\n- [ ] **Stage 1 Solution**: Simplest working version\n - Basic import statements\n - Minimal from/where/select clause\n - Should produce results (high recall, lower precision)\n\n- [ ] **Intermediate Stages**: Progressive refinements\n - Add type constraints\n - Add helper predicates\n - Filter out false positives\n - Add data flow (if applicable)\n\n- [ ] **Final Stage Solution**: Production-quality query\n - Complete metadata (@name, @description, @kind, @id)\n - Full data flow configuration (if applicable)\n - Proper sanitizers and barriers\n - Matches the original target query\n\n### Phase 6: Create Exercise Queries\n\nTransform solutions into exercises by removing implementation details:\n\n- [ ] **Add scaffolding structure**\n\n ```ql\n /**\n * @name Exercise N - [Topic]\n * @description TODO: Complete this exercise\n * @kind problem\n * @id workshop/exercise-n\n */\n\n import language\n\n // TODO: Define predicate to find [something]\n predicate findSomething(Type t) {\n // Your implementation here\n none()\n }\n\n from Type t\n where findSomething(t)\n select t, "Found something"\n ```\n\n- [ ] **Include helpful comments**\n - Hints about which AST classes to use\n - References to documentation\n - Expected behavior description\n\n- [ ] **Ensure exercises compile**\n - Tool: #codeql_query_compile\n - Exercises should compile (even if tests fail)\n\n### Phase 7: Create Tests\n\n- [ ] **Copy test code to test directories**\n - Use same test code for exercises and solutions\n - Consider `initialize-qltests.sh` script for shared test code\n\n- [ ] **Create .qlref files**\n - Point to query location: `../exercises/ExerciseN.ql`\n\n- [ ] **Create .expected files**\n - Run solution queries to generate expected output\n - Tool: #codeql_test_run with `--learn` flag\n - Or: #codeql_test_accept after running tests\n\n### Phase 8: Validate Workshop\n\n- [ ] **Run all solution tests**\n - Tool: #codeql_test_run\n - Parameters: `tests` pointing to `solutions-tests/`\n - Verify: 100% pass rate\n\n- [ ] **Verify exercise stubs compile**\n - Tool: #codeql_query_compile\n - Parameters: Each exercise query\n - Verify: No compilation errors\n\n- [ ] **Test pack dependencies**\n - Tool: #codeql_pack_install\n - Run in each pack directory\n - Verify: Dependencies resolve correctly\n\n### Phase 9: Create Documentation\n\n- [ ] **Write README.md**\n - Workshop overview and objectives\n - Setup instructions\n - Stage-by-stage learning guide\n - AST/CFG examples from Phase 2\n\n- [ ] **Include AST/CFG visualizations**\n - Save PrintAST output to `graphs/`\n - Reference in README for learning context\n\n## External Workshop Considerations\n\nWhen creating workshops outside the MCP server repository:\n\n- [ ] **Install pack dependencies first**\n\n ```bash\n codeql pack install solutions\n codeql pack install solutions-tests\n ```\n\n- [ ] **Check for initialization scripts**\n - Some workshops use `initialize-qltests.sh` to copy test files\n - Run before executing tests\n\n- [ ] **Use absolute paths with MCP tools**\n - External paths must be absolute\n\n## MCP Tools and Prompts Reference\n\n| Tool/Prompt | Type | Purpose |\n| ------------------------------- | ------ | ---------------------------------------------------------------------- |\n| #find_codeql_query_files | Tool | Locate query and related files |\n| `explain_codeql_query` | Prompt | Generate detailed explanations for workshop learning content |\n| `document_codeql_query` | Prompt | Create/update query documentation files |\n| `ql_lsp_iterative_development` | Prompt | Iterative query development with LSP tools |\n| #codeql_query_run | Tool | Run tools queries (PrintAST, PrintCFG, etc.) |\n| #codeql_test_run | Tool | Validate tests pass |\n| #codeql_test_accept | Tool | Accept test results as expected baseline |\n| #codeql_query_compile | Tool | Verify queries compile |\n| #codeql_pack_install | Tool | Install pack dependencies |\n| #codeql_resolve_metadata | Tool | Extract query metadata |\n| #codeql_lsp_completion | Tool | Explore types and member predicates during query writing |\n| #codeql_lsp_definition | Tool | Navigate to class/predicate definitions in library code |\n| #find_predicate_position | Tool | Locate predicate positions for quick_evaluate |\n| #quick_evaluate | Tool | Test individual predicates against a database |\n| #profile_codeql_query_from_logs | Tool | Parse evaluator logs from a prior query run into a performance profile |\n| #create_codeql_query | Tool | Scaffold new query structure |\n\n## Troubleshooting\n\n| Issue | Likely Cause | Resolution |\n| ------------------------ | ------------------------------- | --------------------------------------------------- |\n| "Nothing to extract" | Missing test source files | Run `initialize-qltests.sh` or copy from shared dir |\n| Pack not found | Older pack version not cached | Run `codeql pack install` in pack directory |\n| Empty AST/CFG output | Wrong sourceFiles/Function | Use just filenames, verify function name spelling |\n| Tests fail unexpectedly | Expected file outdated | Re-run solution and accept with #codeql_test_accept |\n| Exercise doesn\'t compile | Missing imports or syntax error | Ensure valid QL syntax with `none()` placeholder |\n';
@@ -64049,7 +64467,7 @@ ${content}`
64049
64467
  workshopCreationWorkflowSchema.shape,
64050
64468
  async ({ queryPath, language, workshopName, numStages }) => {
64051
64469
  const template = loadPromptTemplate("workshop-creation-workflow.prompt.md");
64052
- const derivedName = workshopName || basename6(queryPath).replace(/\.(ql|qlref)$/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-") || "codeql-workshop";
64470
+ const derivedName = workshopName || basename7(queryPath).replace(/\.(ql|qlref)$/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-") || "codeql-workshop";
64053
64471
  const contextSection = buildWorkshopContext(
64054
64472
  queryPath,
64055
64473
  language,
@@ -64409,7 +64827,7 @@ var Low = class {
64409
64827
  };
64410
64828
 
64411
64829
  // ../node_modules/lowdb/lib/adapters/node/TextFile.js
64412
- import { readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
64830
+ import { readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
64413
64831
  import path3 from "node:path";
64414
64832
  var TextFileSync = class {
64415
64833
  #tempFilename;
@@ -64422,7 +64840,7 @@ var TextFileSync = class {
64422
64840
  read() {
64423
64841
  let data;
64424
64842
  try {
64425
- data = readFileSync11(this.#filename, "utf-8");
64843
+ data = readFileSync10(this.#filename, "utf-8");
64426
64844
  } catch (e) {
64427
64845
  if (e.code === "ENOENT") {
64428
64846
  return null;
@@ -64473,7 +64891,7 @@ var JSONFileSync = class extends DataFileSync {
64473
64891
  // src/lib/session-data-manager.ts
64474
64892
  init_temp_dir();
64475
64893
  import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync7 } from "fs";
64476
- import { join as join17 } from "path";
64894
+ import { join as join18 } from "path";
64477
64895
  import { randomUUID as randomUUID2 } from "crypto";
64478
64896
 
64479
64897
  // src/types/monitoring.ts
@@ -64617,7 +65035,7 @@ var SessionDataManager = class {
64617
65035
  });
64618
65036
  this.storageDir = this.config.storageLocation;
64619
65037
  this.ensureStorageDirectory();
64620
- const adapter = new JSONFileSync(join17(this.storageDir, "sessions.json"));
65038
+ const adapter = new JSONFileSync(join18(this.storageDir, "sessions.json"));
64621
65039
  this.db = new Low(adapter, {
64622
65040
  sessions: []
64623
65041
  });
@@ -64649,9 +65067,9 @@ var SessionDataManager = class {
64649
65067
  mkdirSync9(this.storageDir, { recursive: true });
64650
65068
  const subdirs = ["sessions-archive", "exports"];
64651
65069
  for (const subdir of subdirs) {
64652
- mkdirSync9(join17(this.storageDir, subdir), { recursive: true });
65070
+ mkdirSync9(join18(this.storageDir, subdir), { recursive: true });
64653
65071
  }
64654
- const configPath = join17(this.storageDir, "config.json");
65072
+ const configPath = join18(this.storageDir, "config.json");
64655
65073
  try {
64656
65074
  writeFileSync7(configPath, JSON.stringify(this.config, null, 2), { flag: "wx" });
64657
65075
  } catch (e) {
@@ -64830,9 +65248,9 @@ var SessionDataManager = class {
64830
65248
  if (!session) return;
64831
65249
  const date3 = new Date(session.endTime || session.startTime);
64832
65250
  const monthDir = `${date3.getFullYear()}-${String(date3.getMonth() + 1).padStart(2, "0")}`;
64833
- const archiveDir = join17(this.storageDir, "sessions-archive", monthDir);
65251
+ const archiveDir = join18(this.storageDir, "sessions-archive", monthDir);
64834
65252
  mkdirSync9(archiveDir, { recursive: true });
64835
- const archiveFile = join17(archiveDir, `${sessionId}.json`);
65253
+ const archiveFile = join18(archiveDir, `${sessionId}.json`);
64836
65254
  writeFileSync7(archiveFile, JSON.stringify(session, null, 2));
64837
65255
  await this.db.read();
64838
65256
  this.db.data.sessions = this.db.data.sessions.filter((s) => s.sessionId !== sessionId);
@@ -64884,7 +65302,7 @@ var SessionDataManager = class {
64884
65302
  ...this.config,
64885
65303
  ...configUpdate
64886
65304
  });
64887
- const configPath = join17(this.storageDir, "config.json");
65305
+ const configPath = join18(this.storageDir, "config.json");
64888
65306
  writeFileSync7(configPath, JSON.stringify(this.config, null, 2));
64889
65307
  logger.info("Updated monitoring configuration");
64890
65308
  }
@@ -64894,7 +65312,7 @@ function parseBoolEnv(envVar, defaultValue) {
64894
65312
  return envVar.toLowerCase() === "true" || envVar === "1";
64895
65313
  }
64896
65314
  var sessionDataManager = new SessionDataManager({
64897
- storageLocation: process.env.MONITORING_STORAGE_LOCATION || join17(getProjectTmpBase(), ".ql-mcp-tracking"),
65315
+ storageLocation: process.env.MONITORING_STORAGE_LOCATION || join18(getProjectTmpBase(), ".ql-mcp-tracking"),
64898
65316
  enableMonitoringTools: parseBoolEnv(process.env.ENABLE_MONITORING_TOOLS, false)
64899
65317
  });
64900
65318
 
@@ -65768,9 +66186,9 @@ init_cli_executor();
65768
66186
  init_server_manager();
65769
66187
  init_package_paths();
65770
66188
  init_logger();
65771
- import_dotenv.default.config({ path: resolve12(packageRootDir, ".env"), quiet: true });
66189
+ import_dotenv.default.config({ path: resolve13(packageRootDir, ".env"), quiet: true });
65772
66190
  var PACKAGE_NAME = "codeql-development-mcp-server";
65773
- var VERSION = "2.24.3-rc1";
66191
+ var VERSION = "2.24.3-rc2";
65774
66192
  async function startServer(mode = "stdio") {
65775
66193
  logger.info(`Starting CodeQL Development MCP McpServer v${VERSION} in ${mode} mode`);
65776
66194
  const codeqlBinary = resolveCodeQLBinary();
@@ -65824,10 +66242,10 @@ async function startServer(mode = "stdio") {
65824
66242
  });
65825
66243
  const host = process.env.HTTP_HOST || "localhost";
65826
66244
  const port = Number(process.env.HTTP_PORT || process.env.PORT) || 3e3;
65827
- return new Promise((resolve13, reject) => {
66245
+ return new Promise((resolve14, reject) => {
65828
66246
  const httpServer = app.listen(port, host, () => {
65829
66247
  logger.info(`HTTP server listening on http://${host}:${port}/mcp`);
65830
- resolve13();
66248
+ resolve14();
65831
66249
  });
65832
66250
  httpServer.on("error", (error2) => {
65833
66251
  logger.error("HTTP server error:", error2);
@@ -65864,7 +66282,7 @@ async function main() {
65864
66282
  process.exit(1);
65865
66283
  }
65866
66284
  }
65867
- var scriptPath = process.argv[1] ? realpathSync(resolve12(process.argv[1])) : void 0;
66285
+ var scriptPath = process.argv[1] ? realpathSync2(resolve13(process.argv[1])) : void 0;
65868
66286
  if (scriptPath && import.meta.url === pathToFileURL5(scriptPath).href) {
65869
66287
  main();
65870
66288
  }