codeql-development-mcp-server 2.24.2 → 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
  }
@@ -31254,16 +31254,16 @@ var require_view = __commonJS({
31254
31254
  var debug = require_src()("express:view");
31255
31255
  var path4 = __require("node:path");
31256
31256
  var fs3 = __require("node:fs");
31257
- var dirname9 = path4.dirname;
31258
- var basename7 = path4.basename;
31259
- var extname2 = path4.extname;
31257
+ var dirname8 = path4.dirname;
31258
+ var basename8 = path4.basename;
31259
+ var extname3 = path4.extname;
31260
31260
  var join19 = path4.join;
31261
- var resolve13 = path4.resolve;
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);
31296
- var dir = dirname9(loc);
31297
- var file = basename7(loc);
31295
+ var loc = resolve14(root, name);
31296
+ var dir = dirname8(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
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 = join19(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;
34971
+ var extname3 = path4.extname;
34972
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) {
@@ -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);
@@ -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);
@@ -38159,12 +38159,14 @@ __export(cli_executor_exports, {
38159
38159
  buildCodeQLArgs: () => buildCodeQLArgs,
38160
38160
  buildQLTArgs: () => buildQLTArgs,
38161
38161
  disableTestCommands: () => disableTestCommands,
38162
+ discoverVsCodeCodeQLDistribution: () => discoverVsCodeCodeQLDistribution,
38162
38163
  enableTestCommands: () => enableTestCommands,
38163
38164
  executeCLICommand: () => executeCLICommand,
38164
38165
  executeCodeQLCommand: () => executeCodeQLCommand,
38165
38166
  executeQLTCommand: () => executeQLTCommand,
38166
38167
  getCommandHelp: () => getCommandHelp,
38167
38168
  getResolvedCodeQLDir: () => getResolvedCodeQLDir,
38169
+ getVsCodeGlobalStorageCandidates: () => getVsCodeGlobalStorageCandidates,
38168
38170
  resetResolvedCodeQLBinary: () => resetResolvedCodeQLBinary,
38169
38171
  resolveCodeQLBinary: () => resolveCodeQLBinary,
38170
38172
  sanitizeCLIArgument: () => sanitizeCLIArgument,
@@ -38173,8 +38175,9 @@ __export(cli_executor_exports, {
38173
38175
  validateCommandExists: () => validateCommandExists
38174
38176
  });
38175
38177
  import { execFile } from "child_process";
38176
- import { existsSync as existsSync2 } from "fs";
38177
- import { basename, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute2 } from "path";
38178
+ import { accessSync, constants as fsConstants, existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
38179
+ import { basename, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute2, join as join4 } from "path";
38180
+ import { homedir } from "os";
38178
38181
  import { promisify } from "util";
38179
38182
  function enableTestCommands() {
38180
38183
  testCommands = /* @__PURE__ */ new Set([
@@ -38191,12 +38194,103 @@ function disableTestCommands() {
38191
38194
  function isCommandAllowed(command) {
38192
38195
  return ALLOWED_COMMANDS.has(command) || testCommands !== null && testCommands.has(command);
38193
38196
  }
38194
- function resolveCodeQLBinary() {
38197
+ function getVsCodeGlobalStorageCandidates() {
38198
+ const home = homedir();
38199
+ const candidates = [];
38200
+ for (const appName of VSCODE_APP_NAMES) {
38201
+ if (process.platform === "darwin") {
38202
+ candidates.push(join4(home, "Library", "Application Support", appName, "User", "globalStorage"));
38203
+ } else if (process.platform === "win32") {
38204
+ const appData = process.env.APPDATA ?? join4(home, "AppData", "Roaming");
38205
+ candidates.push(join4(appData, appName, "User", "globalStorage"));
38206
+ } else {
38207
+ candidates.push(join4(home, ".config", appName, "User", "globalStorage"));
38208
+ }
38209
+ }
38210
+ return candidates;
38211
+ }
38212
+ function discoverVsCodeCodeQLDistribution(candidateStorageRoots) {
38213
+ const globalStorageCandidates = candidateStorageRoots ?? getVsCodeGlobalStorageCandidates();
38214
+ for (const gsRoot of globalStorageCandidates) {
38215
+ for (const dirName of VSCODE_CODEQL_STORAGE_DIR_NAMES) {
38216
+ const codeqlStorage = join4(gsRoot, dirName);
38217
+ if (!existsSync2(codeqlStorage)) continue;
38218
+ const hintResult = discoverFromDistributionJson(codeqlStorage);
38219
+ if (hintResult) return hintResult;
38220
+ const scanResult = discoverFromDistributionScan(codeqlStorage);
38221
+ if (scanResult) return scanResult;
38222
+ }
38223
+ }
38224
+ return void 0;
38225
+ }
38226
+ function discoverFromDistributionJson(codeqlStorage) {
38227
+ try {
38228
+ const jsonPath = join4(codeqlStorage, "distribution.json");
38229
+ if (!existsSync2(jsonPath)) return void 0;
38230
+ const content = readFileSync2(jsonPath, "utf-8");
38231
+ const data = JSON.parse(content);
38232
+ if (typeof data.folderIndex !== "number") return void 0;
38233
+ const binaryPath = join4(
38234
+ codeqlStorage,
38235
+ `distribution${data.folderIndex}`,
38236
+ "codeql",
38237
+ CODEQL_BINARY_NAME
38238
+ );
38239
+ if (isExecutableBinary(binaryPath)) {
38240
+ logger.debug(`Discovered CLI via distribution.json (folderIndex=${data.folderIndex})`);
38241
+ return binaryPath;
38242
+ }
38243
+ logger.debug(`distribution.json hint (folderIndex=${data.folderIndex}) exists but is not a usable executable; falling through to scan`);
38244
+ } catch {
38245
+ }
38246
+ return void 0;
38247
+ }
38248
+ function discoverFromDistributionScan(codeqlStorage) {
38249
+ try {
38250
+ const entries = readdirSync(codeqlStorage, { withFileTypes: true });
38251
+ const distDirs = entries.filter((e) => e.isDirectory() && /^distribution\d+$/.test(e.name)).map((e) => ({
38252
+ name: e.name,
38253
+ num: parseInt(e.name.replace("distribution", ""), 10)
38254
+ })).sort((a, b) => b.num - a.num);
38255
+ for (const dir of distDirs) {
38256
+ const binaryPath = join4(
38257
+ codeqlStorage,
38258
+ dir.name,
38259
+ "codeql",
38260
+ CODEQL_BINARY_NAME
38261
+ );
38262
+ if (isExecutableBinary(binaryPath)) {
38263
+ logger.debug(`Discovered CLI via distribution scan: ${dir.name}`);
38264
+ return binaryPath;
38265
+ }
38266
+ }
38267
+ } catch {
38268
+ }
38269
+ return void 0;
38270
+ }
38271
+ function isExecutableBinary(binaryPath) {
38272
+ try {
38273
+ const stat = statSync(binaryPath);
38274
+ if (!stat.isFile()) return false;
38275
+ accessSync(binaryPath, fsConstants.X_OK);
38276
+ return true;
38277
+ } catch {
38278
+ return false;
38279
+ }
38280
+ }
38281
+ function resolveCodeQLBinary(candidateStorageRoots) {
38195
38282
  if (resolvedBinaryResult !== void 0) {
38196
38283
  return resolvedBinaryResult;
38197
38284
  }
38198
38285
  const envPath = process.env.CODEQL_PATH;
38199
38286
  if (!envPath) {
38287
+ const discovered = discoverVsCodeCodeQLDistribution(candidateStorageRoots);
38288
+ if (discovered) {
38289
+ resolvedCodeQLDir = dirname2(discovered);
38290
+ resolvedBinaryResult = "codeql";
38291
+ logger.info(`CodeQL CLI auto-discovered via vscode-codeql distribution: ${discovered} (dir: ${resolvedCodeQLDir})`);
38292
+ return resolvedBinaryResult;
38293
+ }
38200
38294
  resolvedCodeQLDir = null;
38201
38295
  resolvedBinaryResult = "codeql";
38202
38296
  return resolvedBinaryResult;
@@ -38443,7 +38537,7 @@ async function validateCommandExists(command) {
38443
38537
  return false;
38444
38538
  }
38445
38539
  }
38446
- var execFileAsync, ALLOWED_COMMANDS, testCommands, SAFE_ENV_VARS, SAFE_ENV_PREFIXES, DANGEROUS_CONTROL_CHARS, resolvedCodeQLDir, resolvedBinaryResult, FRESH_PROCESS_SUBCOMMANDS;
38540
+ var execFileAsync, ALLOWED_COMMANDS, testCommands, SAFE_ENV_VARS, SAFE_ENV_PREFIXES, DANGEROUS_CONTROL_CHARS, resolvedCodeQLDir, resolvedBinaryResult, CODEQL_BINARY_NAME, VSCODE_APP_NAMES, VSCODE_CODEQL_STORAGE_DIR_NAMES, FRESH_PROCESS_SUBCOMMANDS;
38447
38541
  var init_cli_executor = __esm({
38448
38542
  "src/lib/cli-executor.ts"() {
38449
38543
  "use strict";
@@ -38492,6 +38586,9 @@ var init_cli_executor = __esm({
38492
38586
  ];
38493
38587
  DANGEROUS_CONTROL_CHARS = /[\x01-\x08\x0B\x0C\x0E-\x1F]/;
38494
38588
  resolvedCodeQLDir = null;
38589
+ CODEQL_BINARY_NAME = process.platform === "win32" ? "codeql.exe" : "codeql";
38590
+ VSCODE_APP_NAMES = ["Code", "Code - Insiders", "VSCodium"];
38591
+ VSCODE_CODEQL_STORAGE_DIR_NAMES = ["github.vscode-codeql", "GitHub.vscode-codeql"];
38495
38592
  FRESH_PROCESS_SUBCOMMANDS = /* @__PURE__ */ new Set([
38496
38593
  "database analyze",
38497
38594
  "database create",
@@ -40826,10 +40923,10 @@ var require_adm_zip = __commonJS({
40826
40923
  * @param {function|string} [props.namefix] - optional function to help fix filename
40827
40924
  */
40828
40925
  addLocalFolderPromise: function(localPath2, props) {
40829
- return new Promise((resolve13, reject) => {
40926
+ return new Promise((resolve14, reject) => {
40830
40927
  this.addLocalFolderAsync2(Object.assign({ localPath: localPath2 }, props), (err, done) => {
40831
40928
  if (err) reject(err);
40832
- if (done) resolve13(this);
40929
+ if (done) resolve14(this);
40833
40930
  });
40834
40931
  });
40835
40932
  },
@@ -41016,12 +41113,12 @@ var require_adm_zip = __commonJS({
41016
41113
  keepOriginalPermission = get_Bool(false, keepOriginalPermission);
41017
41114
  overwrite = get_Bool(false, overwrite);
41018
41115
  if (!callback) {
41019
- return new Promise((resolve13, reject) => {
41116
+ return new Promise((resolve14, reject) => {
41020
41117
  this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function(err) {
41021
41118
  if (err) {
41022
41119
  reject(err);
41023
41120
  } else {
41024
- resolve13(this);
41121
+ resolve14(this);
41025
41122
  }
41026
41123
  });
41027
41124
  });
@@ -41119,11 +41216,11 @@ var require_adm_zip = __commonJS({
41119
41216
  */
41120
41217
  writeZipPromise: function(targetFileName, props) {
41121
41218
  const { overwrite, perm } = Object.assign({ overwrite: true }, props);
41122
- return new Promise((resolve13, reject) => {
41219
+ return new Promise((resolve14, reject) => {
41123
41220
  if (!targetFileName && opts.filename) targetFileName = opts.filename;
41124
41221
  if (!targetFileName) reject("ADM-ZIP: ZIP File Name Missing");
41125
41222
  this.toBufferPromise().then((zipData) => {
41126
- 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");
41127
41224
  filetools.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);
41128
41225
  }, reject);
41129
41226
  });
@@ -41132,8 +41229,8 @@ var require_adm_zip = __commonJS({
41132
41229
  * @returns {Promise<Buffer>} A promise to the Buffer.
41133
41230
  */
41134
41231
  toBufferPromise: function() {
41135
- return new Promise((resolve13, reject) => {
41136
- _zip.toAsyncBuffer(resolve13, reject);
41232
+ return new Promise((resolve14, reject) => {
41233
+ _zip.toAsyncBuffer(resolve14, reject);
41137
41234
  });
41138
41235
  },
41139
41236
  /**
@@ -53231,7 +53328,7 @@ var Protocol = class {
53231
53328
  return;
53232
53329
  }
53233
53330
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
53234
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
53331
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
53235
53332
  options?.signal?.throwIfAborted();
53236
53333
  }
53237
53334
  } catch (error2) {
@@ -53248,7 +53345,7 @@ var Protocol = class {
53248
53345
  */
53249
53346
  request(request, resultSchema, options) {
53250
53347
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
53251
- return new Promise((resolve13, reject) => {
53348
+ return new Promise((resolve14, reject) => {
53252
53349
  const earlyReject = (error2) => {
53253
53350
  reject(error2);
53254
53351
  };
@@ -53326,7 +53423,7 @@ var Protocol = class {
53326
53423
  if (!parseResult.success) {
53327
53424
  reject(parseResult.error);
53328
53425
  } else {
53329
- resolve13(parseResult.data);
53426
+ resolve14(parseResult.data);
53330
53427
  }
53331
53428
  } catch (error2) {
53332
53429
  reject(error2);
@@ -53587,12 +53684,12 @@ var Protocol = class {
53587
53684
  }
53588
53685
  } catch {
53589
53686
  }
53590
- return new Promise((resolve13, reject) => {
53687
+ return new Promise((resolve14, reject) => {
53591
53688
  if (signal.aborted) {
53592
53689
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
53593
53690
  return;
53594
53691
  }
53595
- const timeoutId = setTimeout(resolve13, interval);
53692
+ const timeoutId = setTimeout(resolve14, interval);
53596
53693
  signal.addEventListener("abort", () => {
53597
53694
  clearTimeout(timeoutId);
53598
53695
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -53775,6 +53872,147 @@ var ExperimentalServerTasks = class {
53775
53872
  requestStream(request, resultSchema, options) {
53776
53873
  return this._server.requestStream(request, resultSchema, options);
53777
53874
  }
53875
+ /**
53876
+ * Sends a sampling request and returns an AsyncGenerator that yields response messages.
53877
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
53878
+ *
53879
+ * For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
53880
+ * before the final result.
53881
+ *
53882
+ * @example
53883
+ * ```typescript
53884
+ * const stream = server.experimental.tasks.createMessageStream({
53885
+ * messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
53886
+ * maxTokens: 100
53887
+ * }, {
53888
+ * onprogress: (progress) => {
53889
+ * // Handle streaming tokens via progress notifications
53890
+ * console.log('Progress:', progress.message);
53891
+ * }
53892
+ * });
53893
+ *
53894
+ * for await (const message of stream) {
53895
+ * switch (message.type) {
53896
+ * case 'taskCreated':
53897
+ * console.log('Task created:', message.task.taskId);
53898
+ * break;
53899
+ * case 'taskStatus':
53900
+ * console.log('Task status:', message.task.status);
53901
+ * break;
53902
+ * case 'result':
53903
+ * console.log('Final result:', message.result);
53904
+ * break;
53905
+ * case 'error':
53906
+ * console.error('Error:', message.error);
53907
+ * break;
53908
+ * }
53909
+ * }
53910
+ * ```
53911
+ *
53912
+ * @param params - The sampling request parameters
53913
+ * @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
53914
+ * @returns AsyncGenerator that yields ResponseMessage objects
53915
+ *
53916
+ * @experimental
53917
+ */
53918
+ createMessageStream(params, options) {
53919
+ const clientCapabilities = this._server.getClientCapabilities();
53920
+ if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
53921
+ throw new Error("Client does not support sampling tools capability.");
53922
+ }
53923
+ if (params.messages.length > 0) {
53924
+ const lastMessage = params.messages[params.messages.length - 1];
53925
+ const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
53926
+ const hasToolResults = lastContent.some((c) => c.type === "tool_result");
53927
+ const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
53928
+ const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
53929
+ const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
53930
+ if (hasToolResults) {
53931
+ if (lastContent.some((c) => c.type !== "tool_result")) {
53932
+ throw new Error("The last message must contain only tool_result content if any is present");
53933
+ }
53934
+ if (!hasPreviousToolUse) {
53935
+ throw new Error("tool_result blocks are not matching any tool_use from the previous message");
53936
+ }
53937
+ }
53938
+ if (hasPreviousToolUse) {
53939
+ const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
53940
+ const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
53941
+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
53942
+ throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
53943
+ }
53944
+ }
53945
+ }
53946
+ return this.requestStream({
53947
+ method: "sampling/createMessage",
53948
+ params
53949
+ }, CreateMessageResultSchema, options);
53950
+ }
53951
+ /**
53952
+ * Sends an elicitation request and returns an AsyncGenerator that yields response messages.
53953
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
53954
+ *
53955
+ * For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
53956
+ * and 'taskStatus' messages before the final result.
53957
+ *
53958
+ * @example
53959
+ * ```typescript
53960
+ * const stream = server.experimental.tasks.elicitInputStream({
53961
+ * mode: 'url',
53962
+ * message: 'Please authenticate',
53963
+ * elicitationId: 'auth-123',
53964
+ * url: 'https://example.com/auth'
53965
+ * }, {
53966
+ * task: { ttl: 300000 } // Task-augmented for long-running auth flow
53967
+ * });
53968
+ *
53969
+ * for await (const message of stream) {
53970
+ * switch (message.type) {
53971
+ * case 'taskCreated':
53972
+ * console.log('Task created:', message.task.taskId);
53973
+ * break;
53974
+ * case 'taskStatus':
53975
+ * console.log('Task status:', message.task.status);
53976
+ * break;
53977
+ * case 'result':
53978
+ * console.log('User action:', message.result.action);
53979
+ * break;
53980
+ * case 'error':
53981
+ * console.error('Error:', message.error);
53982
+ * break;
53983
+ * }
53984
+ * }
53985
+ * ```
53986
+ *
53987
+ * @param params - The elicitation request parameters
53988
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
53989
+ * @returns AsyncGenerator that yields ResponseMessage objects
53990
+ *
53991
+ * @experimental
53992
+ */
53993
+ elicitInputStream(params, options) {
53994
+ const clientCapabilities = this._server.getClientCapabilities();
53995
+ const mode = params.mode ?? "form";
53996
+ switch (mode) {
53997
+ case "url": {
53998
+ if (!clientCapabilities?.elicitation?.url) {
53999
+ throw new Error("Client does not support url elicitation.");
54000
+ }
54001
+ break;
54002
+ }
54003
+ case "form": {
54004
+ if (!clientCapabilities?.elicitation?.form) {
54005
+ throw new Error("Client does not support form elicitation.");
54006
+ }
54007
+ break;
54008
+ }
54009
+ }
54010
+ const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
54011
+ return this.requestStream({
54012
+ method: "elicitation/create",
54013
+ params: normalizedParams
54014
+ }, ElicitResultSchema, options);
54015
+ }
53778
54016
  /**
53779
54017
  * Gets the current status of a task.
53780
54018
  *
@@ -54551,7 +54789,7 @@ var McpServer = class {
54551
54789
  let task = createTaskResult.task;
54552
54790
  const pollInterval = task.pollInterval ?? 5e3;
54553
54791
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
54554
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
54792
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
54555
54793
  const updatedTask = await extra.taskStore.getTask(taskId);
54556
54794
  if (!updatedTask) {
54557
54795
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -55194,12 +55432,12 @@ var StdioServerTransport = class {
55194
55432
  this.onclose?.();
55195
55433
  }
55196
55434
  send(message) {
55197
- return new Promise((resolve13) => {
55435
+ return new Promise((resolve14) => {
55198
55436
  const json2 = serializeMessage(message);
55199
55437
  if (this._stdout.write(json2)) {
55200
- resolve13();
55438
+ resolve14();
55201
55439
  } else {
55202
- this._stdout.once("drain", resolve13);
55440
+ this._stdout.once("drain", resolve14);
55203
55441
  }
55204
55442
  });
55205
55443
  }
@@ -55420,15 +55658,17 @@ var Response2 = class _Response {
55420
55658
  this.#init = init;
55421
55659
  }
55422
55660
  if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) {
55423
- headers ||= init?.headers || { "content-type": "text/plain; charset=UTF-8" };
55424
- this[cacheKey] = [init?.status || 200, body, headers];
55661
+ ;
55662
+ this[cacheKey] = [init?.status || 200, body, headers || init?.headers];
55425
55663
  }
55426
55664
  }
55427
55665
  get headers() {
55428
55666
  const cache = this[cacheKey];
55429
55667
  if (cache) {
55430
55668
  if (!(cache[2] instanceof Headers)) {
55431
- cache[2] = new Headers(cache[2]);
55669
+ cache[2] = new Headers(
55670
+ cache[2] || { "content-type": "text/plain; charset=UTF-8" }
55671
+ );
55432
55672
  }
55433
55673
  return cache[2];
55434
55674
  }
@@ -55553,15 +55793,32 @@ var flushHeaders = (outgoing) => {
55553
55793
  };
55554
55794
  var responseViaCache = async (res, outgoing) => {
55555
55795
  let [status, body, header] = res[cacheKey];
55556
- if (header instanceof Headers) {
55796
+ let hasContentLength = false;
55797
+ if (!header) {
55798
+ header = { "content-type": "text/plain; charset=UTF-8" };
55799
+ } else if (header instanceof Headers) {
55800
+ hasContentLength = header.has("content-length");
55557
55801
  header = buildOutgoingHttpHeaders(header);
55802
+ } else if (Array.isArray(header)) {
55803
+ const headerObj = new Headers(header);
55804
+ hasContentLength = headerObj.has("content-length");
55805
+ header = buildOutgoingHttpHeaders(headerObj);
55806
+ } else {
55807
+ for (const key in header) {
55808
+ if (key.length === 14 && key.toLowerCase() === "content-length") {
55809
+ hasContentLength = true;
55810
+ break;
55811
+ }
55812
+ }
55558
55813
  }
55559
- if (typeof body === "string") {
55560
- header["Content-Length"] = Buffer.byteLength(body);
55561
- } else if (body instanceof Uint8Array) {
55562
- header["Content-Length"] = body.byteLength;
55563
- } else if (body instanceof Blob) {
55564
- header["Content-Length"] = body.size;
55814
+ if (!hasContentLength) {
55815
+ if (typeof body === "string") {
55816
+ header["Content-Length"] = Buffer.byteLength(body);
55817
+ } else if (body instanceof Uint8Array) {
55818
+ header["Content-Length"] = body.byteLength;
55819
+ } else if (body instanceof Blob) {
55820
+ header["Content-Length"] = body.size;
55821
+ }
55565
55822
  }
55566
55823
  outgoing.writeHead(status, header);
55567
55824
  if (typeof body === "string" || body instanceof Uint8Array) {
@@ -55613,7 +55870,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
55613
55870
  });
55614
55871
  if (!chunk) {
55615
55872
  if (i === 1) {
55616
- await new Promise((resolve13) => setTimeout(resolve13));
55873
+ await new Promise((resolve14) => setTimeout(resolve14));
55617
55874
  maxReadCount = 3;
55618
55875
  continue;
55619
55876
  }
@@ -55870,6 +56127,7 @@ data:
55870
56127
  async handleGetRequest(req) {
55871
56128
  const acceptHeader = req.headers.get("accept");
55872
56129
  if (!acceptHeader?.includes("text/event-stream")) {
56130
+ this.onerror?.(new Error("Not Acceptable: Client must accept text/event-stream"));
55873
56131
  return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept text/event-stream");
55874
56132
  }
55875
56133
  const sessionError = this.validateSession(req);
@@ -55887,6 +56145,7 @@ data:
55887
56145
  }
55888
56146
  }
55889
56147
  if (this._streamMapping.get(this._standaloneSseStreamId) !== void 0) {
56148
+ this.onerror?.(new Error("Conflict: Only one SSE stream is allowed per session"));
55890
56149
  return this.createJsonErrorResponse(409, -32e3, "Conflict: Only one SSE stream is allowed per session");
55891
56150
  }
55892
56151
  const encoder = new TextEncoder();
@@ -55926,6 +56185,7 @@ data:
55926
56185
  */
55927
56186
  async replayEvents(lastEventId) {
55928
56187
  if (!this._eventStore) {
56188
+ this.onerror?.(new Error("Event store not configured"));
55929
56189
  return this.createJsonErrorResponse(400, -32e3, "Event store not configured");
55930
56190
  }
55931
56191
  try {
@@ -55933,9 +56193,11 @@ data:
55933
56193
  if (this._eventStore.getStreamIdForEventId) {
55934
56194
  streamId = await this._eventStore.getStreamIdForEventId(lastEventId);
55935
56195
  if (!streamId) {
56196
+ this.onerror?.(new Error("Invalid event ID format"));
55936
56197
  return this.createJsonErrorResponse(400, -32e3, "Invalid event ID format");
55937
56198
  }
55938
56199
  if (this._streamMapping.get(streamId) !== void 0) {
56200
+ this.onerror?.(new Error("Conflict: Stream already has an active connection"));
55939
56201
  return this.createJsonErrorResponse(409, -32e3, "Conflict: Stream already has an active connection");
55940
56202
  }
55941
56203
  }
@@ -56001,7 +56263,8 @@ data:
56001
56263
  `;
56002
56264
  controller.enqueue(encoder.encode(eventData));
56003
56265
  return true;
56004
- } catch {
56266
+ } catch (error2) {
56267
+ this.onerror?.(error2);
56005
56268
  return false;
56006
56269
  }
56007
56270
  }
@@ -56009,6 +56272,7 @@ data:
56009
56272
  * Handles unsupported requests (PUT, PATCH, etc.)
56010
56273
  */
56011
56274
  handleUnsupportedRequest() {
56275
+ this.onerror?.(new Error("Method not allowed."));
56012
56276
  return new Response(JSON.stringify({
56013
56277
  jsonrpc: "2.0",
56014
56278
  error: {
@@ -56031,14 +56295,17 @@ data:
56031
56295
  try {
56032
56296
  const acceptHeader = req.headers.get("accept");
56033
56297
  if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
56298
+ this.onerror?.(new Error("Not Acceptable: Client must accept both application/json and text/event-stream"));
56034
56299
  return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept both application/json and text/event-stream");
56035
56300
  }
56036
56301
  const ct = req.headers.get("content-type");
56037
56302
  if (!ct || !ct.includes("application/json")) {
56303
+ this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json"));
56038
56304
  return this.createJsonErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
56039
56305
  }
56040
56306
  const requestInfo = {
56041
- headers: Object.fromEntries(req.headers.entries())
56307
+ headers: Object.fromEntries(req.headers.entries()),
56308
+ url: new URL(req.url)
56042
56309
  };
56043
56310
  let rawMessage;
56044
56311
  if (options?.parsedBody !== void 0) {
@@ -56047,6 +56314,7 @@ data:
56047
56314
  try {
56048
56315
  rawMessage = await req.json();
56049
56316
  } catch {
56317
+ this.onerror?.(new Error("Parse error: Invalid JSON"));
56050
56318
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
56051
56319
  }
56052
56320
  }
@@ -56058,14 +56326,17 @@ data:
56058
56326
  messages = [JSONRPCMessageSchema.parse(rawMessage)];
56059
56327
  }
56060
56328
  } catch {
56329
+ this.onerror?.(new Error("Parse error: Invalid JSON-RPC message"));
56061
56330
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
56062
56331
  }
56063
56332
  const isInitializationRequest = messages.some(isInitializeRequest);
56064
56333
  if (isInitializationRequest) {
56065
56334
  if (this._initialized && this.sessionId !== void 0) {
56335
+ this.onerror?.(new Error("Invalid Request: Server already initialized"));
56066
56336
  return this.createJsonErrorResponse(400, -32600, "Invalid Request: Server already initialized");
56067
56337
  }
56068
56338
  if (messages.length > 1) {
56339
+ this.onerror?.(new Error("Invalid Request: Only one initialization request is allowed"));
56069
56340
  return this.createJsonErrorResponse(400, -32600, "Invalid Request: Only one initialization request is allowed");
56070
56341
  }
56071
56342
  this.sessionId = this.sessionIdGenerator?.();
@@ -56095,9 +56366,9 @@ data:
56095
56366
  const initRequest = messages.find((m) => isInitializeRequest(m));
56096
56367
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
56097
56368
  if (this._enableJsonResponse) {
56098
- return new Promise((resolve13) => {
56369
+ return new Promise((resolve14) => {
56099
56370
  this._streamMapping.set(streamId, {
56100
- resolveJson: resolve13,
56371
+ resolveJson: resolve14,
56101
56372
  cleanup: () => {
56102
56373
  this._streamMapping.delete(streamId);
56103
56374
  }
@@ -56191,13 +56462,16 @@ data:
56191
56462
  return void 0;
56192
56463
  }
56193
56464
  if (!this._initialized) {
56465
+ this.onerror?.(new Error("Bad Request: Server not initialized"));
56194
56466
  return this.createJsonErrorResponse(400, -32e3, "Bad Request: Server not initialized");
56195
56467
  }
56196
56468
  const sessionId = req.headers.get("mcp-session-id");
56197
56469
  if (!sessionId) {
56470
+ this.onerror?.(new Error("Bad Request: Mcp-Session-Id header is required"));
56198
56471
  return this.createJsonErrorResponse(400, -32e3, "Bad Request: Mcp-Session-Id header is required");
56199
56472
  }
56200
56473
  if (sessionId !== this.sessionId) {
56474
+ this.onerror?.(new Error("Session not found"));
56201
56475
  return this.createJsonErrorResponse(404, -32001, "Session not found");
56202
56476
  }
56203
56477
  return void 0;
@@ -56218,6 +56492,7 @@ data:
56218
56492
  validateProtocolVersion(req) {
56219
56493
  const protocolVersion = req.headers.get("mcp-protocol-version");
56220
56494
  if (protocolVersion !== null && !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) {
56495
+ this.onerror?.(new Error(`Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`));
56221
56496
  return this.createJsonErrorResponse(400, -32e3, `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`);
56222
56497
  }
56223
56498
  return void 0;
@@ -56427,8 +56702,8 @@ var StreamableHTTPServerTransport = class {
56427
56702
  var import_express = __toESM(require_express2(), 1);
56428
56703
  var import_cors = __toESM(require_lib3(), 1);
56429
56704
  var import_dotenv = __toESM(require_main(), 1);
56430
- import { realpathSync } from "fs";
56431
- import { resolve as resolve12 } from "path";
56705
+ import { realpathSync as realpathSync2 } from "fs";
56706
+ import { resolve as resolve13 } from "path";
56432
56707
  import { pathToFileURL as pathToFileURL5 } from "url";
56433
56708
 
56434
56709
  // src/lib/cli-tool-registry.ts
@@ -56438,7 +56713,7 @@ init_logger();
56438
56713
  // src/lib/query-results-evaluator.ts
56439
56714
  init_cli_executor();
56440
56715
  init_logger();
56441
- import { writeFileSync, readFileSync as readFileSync2 } from "fs";
56716
+ import { writeFileSync, readFileSync as readFileSync3 } from "fs";
56442
56717
  import { dirname as dirname3, isAbsolute as isAbsolute3 } from "path";
56443
56718
  import { mkdirSync as mkdirSync3 } from "fs";
56444
56719
  var BUILT_IN_EVALUATORS = {
@@ -56448,7 +56723,7 @@ var BUILT_IN_EVALUATORS = {
56448
56723
  };
56449
56724
  async function extractQueryMetadata(queryPath) {
56450
56725
  try {
56451
- const queryContent = readFileSync2(queryPath, "utf-8");
56726
+ const queryContent = readFileSync3(queryPath, "utf-8");
56452
56727
  const metadata = {};
56453
56728
  const kindMatch = queryContent.match(/@kind\s+([^\s]+)/);
56454
56729
  if (kindMatch) metadata.kind = kindMatch[1];
@@ -56698,7 +56973,7 @@ async function evaluateWithCustomScript(_bqrsPath, _queryPath, _scriptPath, _out
56698
56973
  // src/lib/log-directory-manager.ts
56699
56974
  init_temp_dir();
56700
56975
  import { mkdirSync as mkdirSync4, existsSync as existsSync3 } from "fs";
56701
- import { join as join4, resolve as resolve3 } from "path";
56976
+ import { join as join5, resolve as resolve3 } from "path";
56702
56977
  import { randomBytes } from "crypto";
56703
56978
  function ensurePathWithinBase(baseDir, targetPath) {
56704
56979
  const absBase = resolve3(baseDir);
@@ -56722,7 +56997,7 @@ function getOrCreateLogDirectory(logDir) {
56722
56997
  }
56723
56998
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
56724
56999
  const uniqueId = randomBytes(4).toString("hex");
56725
- const uniqueLogDir = join4(baseLogDir, `query-run-${timestamp2}-${uniqueId}`);
57000
+ const uniqueLogDir = join5(baseLogDir, `query-run-${timestamp2}-${uniqueId}`);
56726
57001
  mkdirSync4(uniqueLogDir, { recursive: true });
56727
57002
  return uniqueLogDir;
56728
57003
  }
@@ -56730,8 +57005,41 @@ function getOrCreateLogDirectory(logDir) {
56730
57005
  // src/lib/cli-tool-registry.ts
56731
57006
  init_package_paths();
56732
57007
  init_temp_dir();
56733
- import { writeFileSync as writeFileSync2, rmSync, existsSync as existsSync4, mkdirSync as mkdirSync5 } from "fs";
56734
- import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute4, join as join5, resolve as resolve4 } from "path";
57008
+ import { writeFileSync as writeFileSync2, rmSync, existsSync as existsSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
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
+ }
56735
57043
  var defaultCLIResultProcessor = (result, _params) => {
56736
57044
  if (!result.success) {
56737
57045
  return `Command failed (exit code ${result.exitCode || "unknown"}):
@@ -56769,7 +57077,7 @@ function registerCLITool(server, definition) {
56769
57077
  const tempDirsToCleanup = [];
56770
57078
  try {
56771
57079
  logger.info(`Executing CLI tool: ${name}`, { command, subcommand, params });
56772
- 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";
56773
57081
  const extractedParams = formatShouldBePassedToCLI ? {
56774
57082
  _positional: params._positional || [],
56775
57083
  files: params.files,
@@ -56847,7 +57155,7 @@ function registerCLITool(server, definition) {
56847
57155
  positionalArgs = [...positionalArgs, qlref];
56848
57156
  }
56849
57157
  if (options.database && name === "codeql_resolve_database") {
56850
- positionalArgs = [...positionalArgs, options.database];
57158
+ positionalArgs = [...positionalArgs, resolveDatabasePath(options.database)];
56851
57159
  delete options.database;
56852
57160
  }
56853
57161
  if (options.database && name === "codeql_database_create") {
@@ -56856,7 +57164,7 @@ function registerCLITool(server, definition) {
56856
57164
  }
56857
57165
  if (name === "codeql_database_analyze") {
56858
57166
  if (options.database) {
56859
- positionalArgs = [...positionalArgs, options.database];
57167
+ positionalArgs = [...positionalArgs, resolveDatabasePath(options.database)];
56860
57168
  delete options.database;
56861
57169
  }
56862
57170
  if (options.queries) {
@@ -56887,6 +57195,9 @@ function registerCLITool(server, definition) {
56887
57195
  options.database = resolve4(getUserWorkspaceDir(), options.database);
56888
57196
  logger.info(`Resolved database path to: ${options.database}`);
56889
57197
  }
57198
+ if (options.database && typeof options.database === "string") {
57199
+ options.database = resolveDatabasePath(options.database);
57200
+ }
56890
57201
  const resolvedQuery = await resolveQueryPath(params, logger);
56891
57202
  if (resolvedQuery) {
56892
57203
  positionalArgs = [...positionalArgs, resolvedQuery];
@@ -56900,7 +57211,7 @@ function registerCLITool(server, definition) {
56900
57211
  try {
56901
57212
  tempDir = createProjectTempDir("codeql-external-");
56902
57213
  tempDirsToCleanup.push(tempDir);
56903
- csvPath = join5(tempDir, "selectedSourceFiles.csv");
57214
+ csvPath = join6(tempDir, "selectedSourceFiles.csv");
56904
57215
  const csvContent = filePaths.join("\n") + "\n";
56905
57216
  writeFileSync2(csvPath, csvContent, "utf8");
56906
57217
  } catch (err) {
@@ -56920,7 +57231,7 @@ function registerCLITool(server, definition) {
56920
57231
  try {
56921
57232
  tempDir = createProjectTempDir("codeql-external-");
56922
57233
  tempDirsToCleanup.push(tempDir);
56923
- csvPath = join5(tempDir, "sourceFunction.csv");
57234
+ csvPath = join6(tempDir, "sourceFunction.csv");
56924
57235
  const csvContent = functionNames.join("\n") + "\n";
56925
57236
  writeFileSync2(csvPath, csvContent, "utf8");
56926
57237
  } catch (err) {
@@ -56940,7 +57251,7 @@ function registerCLITool(server, definition) {
56940
57251
  try {
56941
57252
  tempDir = createProjectTempDir("codeql-external-");
56942
57253
  tempDirsToCleanup.push(tempDir);
56943
- csvPath = join5(tempDir, "targetFunction.csv");
57254
+ csvPath = join6(tempDir, "targetFunction.csv");
56944
57255
  const csvContent = functionNames.join("\n") + "\n";
56945
57256
  writeFileSync2(csvPath, csvContent, "utf8");
56946
57257
  } catch (err) {
@@ -56966,6 +57277,11 @@ function registerCLITool(server, definition) {
56966
57277
  positionalArgs = [...positionalArgs, directory];
56967
57278
  }
56968
57279
  break;
57280
+ case "codeql_resolve_files":
57281
+ if (dir) {
57282
+ positionalArgs = [...positionalArgs, dir];
57283
+ }
57284
+ break;
56969
57285
  default:
56970
57286
  break;
56971
57287
  }
@@ -56973,21 +57289,21 @@ function registerCLITool(server, definition) {
56973
57289
  if (name === "codeql_query_run" || name === "codeql_test_run" || name === "codeql_database_analyze") {
56974
57290
  queryLogDir = getOrCreateLogDirectory(customLogDir);
56975
57291
  logger.info(`Using log directory for ${name}: ${queryLogDir}`);
56976
- const timestampPath = join5(queryLogDir, "timestamp");
57292
+ const timestampPath = join6(queryLogDir, "timestamp");
56977
57293
  writeFileSync2(timestampPath, Date.now().toString(), "utf8");
56978
57294
  options.logdir = queryLogDir;
56979
57295
  if (!options.verbosity) {
56980
57296
  options.verbosity = "progress+";
56981
57297
  }
56982
57298
  if (!options["evaluator-log"]) {
56983
- options["evaluator-log"] = join5(queryLogDir, "evaluator-log.jsonl");
57299
+ options["evaluator-log"] = join6(queryLogDir, "evaluator-log.jsonl");
56984
57300
  }
56985
57301
  if (options["tuple-counting"] === void 0) {
56986
57302
  options["tuple-counting"] = true;
56987
57303
  }
56988
57304
  if (name === "codeql_query_run") {
56989
57305
  if (!options.output) {
56990
- options.output = join5(queryLogDir, "results.bqrs");
57306
+ options.output = join6(queryLogDir, "results.bqrs");
56991
57307
  }
56992
57308
  }
56993
57309
  if (options.output && typeof options.output === "string") {
@@ -57018,7 +57334,7 @@ function registerCLITool(server, definition) {
57018
57334
  }
57019
57335
  if (name === "codeql_query_run" && result.success && queryLogDir) {
57020
57336
  const bqrsPath = options.output;
57021
- const sarifPath = join5(queryLogDir, "results-interpreted.sarif");
57337
+ const sarifPath = join6(queryLogDir, "results-interpreted.sarif");
57022
57338
  const queryFilePath = positionalArgs.length > 0 ? positionalArgs[positionalArgs.length - 1] : void 0;
57023
57339
  if (existsSync4(bqrsPath) && queryFilePath) {
57024
57340
  try {
@@ -60439,6 +60755,18 @@ async function findCodeQLQueryFiles(queryFilePath, language, resolveMetadata = t
60439
60755
  }
60440
60756
  const testPackPath = findNearestQlpack(testDir);
60441
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
+ }
60442
60770
  return {
60443
60771
  queryName,
60444
60772
  language: detectedLanguage,
@@ -60461,6 +60789,7 @@ async function findCodeQLQueryFiles(queryFilePath, language, resolveMetadata = t
60461
60789
  testDatabaseDir: testDatabasePath.path
60462
60790
  }
60463
60791
  },
60792
+ hints,
60464
60793
  metadata,
60465
60794
  missingFiles,
60466
60795
  packMetadata,
@@ -60562,15 +60891,16 @@ var codeqlGenerateQueryHelpTool = {
60562
60891
  };
60563
60892
 
60564
60893
  // src/tools/codeql/list-databases.ts
60565
- import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
60566
- import { join as join7 } from "path";
60894
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
60895
+ import { join as join8 } from "path";
60567
60896
 
60568
60897
  // src/lib/discovery-config.ts
60898
+ import { delimiter as delimiter5 } from "path";
60569
60899
  function parsePathList(envValue) {
60570
60900
  if (!envValue) {
60571
60901
  return [];
60572
60902
  }
60573
- 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);
60574
60904
  }
60575
60905
  function getDatabaseBaseDirs() {
60576
60906
  return parsePathList(process.env.CODEQL_DATABASES_BASE_DIRS);
@@ -60586,7 +60916,7 @@ function getQueryRunResultsDirs() {
60586
60916
  init_logger();
60587
60917
  function parseDatabaseYml(ymlPath) {
60588
60918
  try {
60589
- const content = readFileSync4(ymlPath, "utf-8");
60919
+ const content = readFileSync5(ymlPath, "utf-8");
60590
60920
  const info = {};
60591
60921
  for (const line of content.split("\n")) {
60592
60922
  const trimmed = line.trim();
@@ -60619,20 +60949,20 @@ async function discoverDatabases(baseDirs, language) {
60619
60949
  }
60620
60950
  let entries;
60621
60951
  try {
60622
- entries = readdirSync2(baseDir);
60952
+ entries = readdirSync4(baseDir);
60623
60953
  } catch {
60624
60954
  continue;
60625
60955
  }
60626
60956
  for (const entry of entries) {
60627
- const entryPath = join7(baseDir, entry);
60957
+ const entryPath = join8(baseDir, entry);
60628
60958
  try {
60629
- if (!statSync2(entryPath).isDirectory()) {
60959
+ if (!statSync4(entryPath).isDirectory()) {
60630
60960
  continue;
60631
60961
  }
60632
60962
  } catch {
60633
60963
  continue;
60634
60964
  }
60635
- const ymlPath = join7(entryPath, "codeql-database.yml");
60965
+ const ymlPath = join8(entryPath, "codeql-database.yml");
60636
60966
  if (!existsSync6(ymlPath)) {
60637
60967
  continue;
60638
60968
  }
@@ -60715,8 +61045,8 @@ function registerListDatabasesTool(server) {
60715
61045
  }
60716
61046
 
60717
61047
  // src/tools/codeql/list-mrva-run-results.ts
60718
- import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
60719
- import { join as join8 } from "path";
61048
+ import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
61049
+ import { join as join9 } from "path";
60720
61050
  init_logger();
60721
61051
  var NUMERIC_DIR_PATTERN = /^\d+$/;
60722
61052
  var SKIP_DIRS = /* @__PURE__ */ new Set([".DS_Store", "exported-results"]);
@@ -60728,14 +61058,14 @@ async function discoverMrvaRunResults(resultsDirs, runId) {
60728
61058
  }
60729
61059
  let entries;
60730
61060
  try {
60731
- entries = readdirSync3(dir);
61061
+ entries = readdirSync5(dir);
60732
61062
  } catch {
60733
61063
  continue;
60734
61064
  }
60735
61065
  for (const entry of entries) {
60736
- const entryPath = join8(dir, entry);
61066
+ const entryPath = join9(dir, entry);
60737
61067
  try {
60738
- if (!statSync3(entryPath).isDirectory()) {
61068
+ if (!statSync5(entryPath).isDirectory()) {
60739
61069
  continue;
60740
61070
  }
60741
61071
  } catch {
@@ -60748,10 +61078,10 @@ async function discoverMrvaRunResults(resultsDirs, runId) {
60748
61078
  continue;
60749
61079
  }
60750
61080
  let timestamp2;
60751
- const timestampPath = join8(entryPath, "timestamp");
61081
+ const timestampPath = join9(entryPath, "timestamp");
60752
61082
  if (existsSync7(timestampPath)) {
60753
61083
  try {
60754
- timestamp2 = readFileSync5(timestampPath, "utf-8").trim();
61084
+ timestamp2 = readFileSync6(timestampPath, "utf-8").trim();
60755
61085
  } catch {
60756
61086
  }
60757
61087
  }
@@ -60770,7 +61100,7 @@ function discoverRepoResults(runPath) {
60770
61100
  const repos = [];
60771
61101
  let ownerEntries;
60772
61102
  try {
60773
- ownerEntries = readdirSync3(runPath);
61103
+ ownerEntries = readdirSync5(runPath);
60774
61104
  } catch {
60775
61105
  return repos;
60776
61106
  }
@@ -60778,9 +61108,9 @@ function discoverRepoResults(runPath) {
60778
61108
  if (SKIP_DIRS.has(ownerEntry)) {
60779
61109
  continue;
60780
61110
  }
60781
- const ownerPath = join8(runPath, ownerEntry);
61111
+ const ownerPath = join9(runPath, ownerEntry);
60782
61112
  try {
60783
- if (!statSync3(ownerPath).isDirectory()) {
61113
+ if (!statSync5(ownerPath).isDirectory()) {
60784
61114
  continue;
60785
61115
  }
60786
61116
  } catch {
@@ -60788,14 +61118,14 @@ function discoverRepoResults(runPath) {
60788
61118
  }
60789
61119
  let repoEntries;
60790
61120
  try {
60791
- repoEntries = readdirSync3(ownerPath);
61121
+ repoEntries = readdirSync5(ownerPath);
60792
61122
  } catch {
60793
61123
  continue;
60794
61124
  }
60795
61125
  for (const repoEntry of repoEntries) {
60796
- const repoPath = join8(ownerPath, repoEntry);
61126
+ const repoPath = join9(ownerPath, repoEntry);
60797
61127
  try {
60798
- if (!statSync3(repoPath).isDirectory()) {
61128
+ if (!statSync5(repoPath).isDirectory()) {
60799
61129
  continue;
60800
61130
  }
60801
61131
  } catch {
@@ -60804,10 +61134,10 @@ function discoverRepoResults(runPath) {
60804
61134
  const fullName = `${ownerEntry}/${repoEntry}`;
60805
61135
  let analysisStatus;
60806
61136
  let resultCount;
60807
- const repoTaskPath = join8(repoPath, "repo_task.json");
61137
+ const repoTaskPath = join9(repoPath, "repo_task.json");
60808
61138
  if (existsSync7(repoTaskPath)) {
60809
61139
  try {
60810
- const raw = readFileSync5(repoTaskPath, "utf-8");
61140
+ const raw = readFileSync6(repoTaskPath, "utf-8");
60811
61141
  const task = JSON.parse(raw);
60812
61142
  if (typeof task.analysisStatus === "string") {
60813
61143
  analysisStatus = task.analysisStatus;
@@ -60818,8 +61148,8 @@ function discoverRepoResults(runPath) {
60818
61148
  } catch {
60819
61149
  }
60820
61150
  }
60821
- const hasSarif = existsSync7(join8(repoPath, "results", "results.sarif"));
60822
- const hasBqrs = existsSync7(join8(repoPath, "results", "results.bqrs"));
61151
+ const hasSarif = existsSync7(join9(repoPath, "results", "results.sarif"));
61152
+ const hasBqrs = existsSync7(join9(repoPath, "results", "results.bqrs"));
60823
61153
  repos.push({
60824
61154
  analysisStatus,
60825
61155
  fullName,
@@ -60902,8 +61232,8 @@ function registerListMrvaRunResultsTool(server) {
60902
61232
  }
60903
61233
 
60904
61234
  // src/tools/codeql/list-query-run-results.ts
60905
- import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
60906
- import { join as join9 } from "path";
61235
+ import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
61236
+ import { join as join10 } from "path";
60907
61237
  init_logger();
60908
61238
  var QUERY_RUN_DIR_PATTERN = /^(.+\.ql)-(.+)$/;
60909
61239
  var RUN_QUERY_PATTERN = /runQuery called with\s+(\S+)/;
@@ -60944,14 +61274,14 @@ async function discoverQueryRunResults(resultsDirs, filter) {
60944
61274
  }
60945
61275
  let entries;
60946
61276
  try {
60947
- entries = readdirSync4(dir);
61277
+ entries = readdirSync6(dir);
60948
61278
  } catch {
60949
61279
  continue;
60950
61280
  }
60951
61281
  for (const entry of entries) {
60952
- const entryPath = join9(dir, entry);
61282
+ const entryPath = join10(dir, entry);
60953
61283
  try {
60954
- if (!statSync4(entryPath).isDirectory()) {
61284
+ if (!statSync6(entryPath).isDirectory()) {
60955
61285
  continue;
60956
61286
  }
60957
61287
  } catch {
@@ -60965,23 +61295,23 @@ async function discoverQueryRunResults(resultsDirs, filter) {
60965
61295
  if (normalizedFilter?.queryName && name !== normalizedFilter.queryName) {
60966
61296
  continue;
60967
61297
  }
60968
- const hasEvaluatorLog = existsSync8(join9(entryPath, "evaluator-log.jsonl"));
60969
- const hasBqrs = existsSync8(join9(entryPath, "results.bqrs"));
60970
- const hasSarif = existsSync8(join9(entryPath, "results-interpreted.sarif"));
60971
- const hasQueryLog = existsSync8(join9(entryPath, "query.log"));
60972
- const hasSummaryLog = existsSync8(join9(entryPath, "evaluator-log.summary.jsonl"));
61298
+ const hasEvaluatorLog = existsSync8(join10(entryPath, "evaluator-log.jsonl"));
61299
+ const hasBqrs = existsSync8(join10(entryPath, "results.bqrs"));
61300
+ const hasSarif = existsSync8(join10(entryPath, "results-interpreted.sarif"));
61301
+ const hasQueryLog = existsSync8(join10(entryPath, "query.log"));
61302
+ const hasSummaryLog = existsSync8(join10(entryPath, "evaluator-log.summary.jsonl"));
60973
61303
  let timestamp2;
60974
- const timestampPath = join9(entryPath, "timestamp");
61304
+ const timestampPath = join10(entryPath, "timestamp");
60975
61305
  if (existsSync8(timestampPath)) {
60976
61306
  try {
60977
- timestamp2 = readFileSync6(timestampPath, "utf-8").trim();
61307
+ timestamp2 = readFileSync7(timestampPath, "utf-8").trim();
60978
61308
  } catch {
60979
61309
  }
60980
61310
  }
60981
61311
  let metadata = {};
60982
61312
  if (hasQueryLog) {
60983
61313
  try {
60984
- const logContent = readFileSync6(join9(entryPath, "query.log"), "utf-8");
61314
+ const logContent = readFileSync7(join10(entryPath, "query.log"), "utf-8");
60985
61315
  metadata = parseQueryLogMetadata(logContent);
60986
61316
  } catch {
60987
61317
  }
@@ -61089,7 +61419,7 @@ function registerListQueryRunResultsTool(server) {
61089
61419
  if (run.queryPath) parts.push(` Query: ${run.queryPath}`);
61090
61420
  if (run.databasePath) parts.push(` Database: ${run.databasePath}`);
61091
61421
  parts.push(` Artifacts: ${artifacts.length > 0 ? artifacts.join(", ") : "none"}`);
61092
- if (run.hasBqrs) parts.push(` BQRS: ${join9(run.path, "results.bqrs")}`);
61422
+ if (run.hasBqrs) parts.push(` BQRS: ${join10(run.path, "results.bqrs")}`);
61093
61423
  return parts.join("\n");
61094
61424
  })
61095
61425
  ];
@@ -61155,61 +61485,91 @@ var codeqlPackLsTool = {
61155
61485
 
61156
61486
  // src/tools/codeql/profile-codeql-query-from-logs.ts
61157
61487
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, writeFileSync as writeFileSync3 } from "fs";
61158
- import { basename as basename4, dirname as dirname6, join as join10 } from "path";
61488
+ import { basename as basename4, dirname as dirname6, join as join11 } from "path";
61159
61489
 
61160
61490
  // src/lib/evaluator-log-parser.ts
61161
61491
  init_logger();
61162
- import { readFileSync as readFileSync7 } from "fs";
61492
+ import { createReadStream } from "fs";
61493
+ import { createInterface } from "readline";
61163
61494
  function detectLogFormat(firstEvent) {
61164
61495
  if (typeof firstEvent.type === "string") {
61165
61496
  return "raw";
61166
61497
  }
61167
61498
  return "summary";
61168
61499
  }
61169
- function splitJsonObjects(content) {
61170
- const trimmed = content.trim();
61171
- if (trimmed.length === 0) {
61172
- return [];
61173
- }
61174
- const parts = trimmed.split(/\n\}\s*\n\s*\{/);
61175
- if (parts.length === 1) {
61176
- return [trimmed];
61177
- }
61178
- return parts.map((part, idx) => {
61179
- if (idx === 0) {
61180
- return part + "\n}";
61181
- }
61182
- if (idx === parts.length - 1) {
61183
- return "{\n" + part;
61184
- }
61185
- return "{\n" + part + "\n}";
61500
+ async function* streamJsonObjects(logPath) {
61501
+ const rl = createInterface({
61502
+ input: createReadStream(logPath, { encoding: "utf-8" }),
61503
+ crlfDelay: Infinity
61186
61504
  });
61187
- }
61188
- function parseJsonObjects(logPath) {
61189
- const content = readFileSync7(logPath, "utf-8");
61190
- const objectStrings = splitJsonObjects(content);
61191
- const results = [];
61192
- for (const objStr of objectStrings) {
61193
- try {
61194
- results.push(JSON.parse(objStr));
61195
- } catch {
61196
- logger.warn(
61197
- `Failed to parse evaluator log object: ${objStr.substring(0, 120)}...`
61198
- );
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
+ }
61199
61557
  }
61200
61558
  }
61201
- return results;
61202
61559
  }
61203
- function parseRawEvaluatorLog(logPath) {
61204
- const events = parseJsonObjects(logPath);
61560
+ async function processRawEvents(events) {
61205
61561
  let codeqlVersion;
61206
61562
  const queryStartEvents = /* @__PURE__ */ new Map();
61207
61563
  const predicateStartEvents = /* @__PURE__ */ new Map();
61564
+ const pipelineStartNanoTimes = /* @__PURE__ */ new Map();
61565
+ const pipelineToPredicateMap = /* @__PURE__ */ new Map();
61208
61566
  const queryPredicates = /* @__PURE__ */ new Map();
61209
61567
  const queryEndNanoTimes = /* @__PURE__ */ new Map();
61210
61568
  const queryCacheHits = /* @__PURE__ */ new Map();
61211
61569
  let firstQueryEventId;
61212
- for (const event of events) {
61570
+ let totalEvents = 0;
61571
+ for await (const event of events) {
61572
+ totalEvents++;
61213
61573
  const eventType = event.type;
61214
61574
  switch (eventType) {
61215
61575
  case "LOG_HEADER": {
@@ -61238,6 +61598,11 @@ function parseRawEvaluatorLog(logPath) {
61238
61598
  case "PREDICATE_STARTED": {
61239
61599
  const eid = event.eventId;
61240
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
+ }
61241
61606
  predicateStartEvents.set(eid, {
61242
61607
  predicateName: event.predicateName || "unknown",
61243
61608
  position: event.position,
@@ -61245,20 +61610,34 @@ function parseRawEvaluatorLog(logPath) {
61245
61610
  dependencies: deps ? Object.keys(deps) : [],
61246
61611
  queryCausingWork: event.queryCausingWork,
61247
61612
  nanoTime: event.nanoTime,
61248
- pipelineCount: 0
61613
+ pipelineCount: 0,
61614
+ raSteps,
61615
+ pipelineStages: []
61249
61616
  });
61250
61617
  break;
61251
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
+ }
61252
61626
  case "PIPELINE_COMPLETED": {
61253
61627
  const pipelineStartEid = event.startEvent;
61254
- const pipelineStartEvt = events.find(
61255
- (e) => e.type === "PIPELINE_STARTED" && e.eventId === pipelineStartEid
61256
- );
61257
- if (pipelineStartEvt) {
61258
- const predEid = pipelineStartEvt.predicateStartEvent;
61628
+ const predEid = pipelineToPredicateMap.get(pipelineStartEid);
61629
+ const startNano = pipelineStartNanoTimes.get(pipelineStartEid);
61630
+ if (predEid !== void 0) {
61259
61631
  const predStart = predicateStartEvents.get(predEid);
61260
61632
  if (predStart) {
61261
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
+ });
61262
61641
  }
61263
61642
  }
61264
61643
  break;
@@ -61276,7 +61655,9 @@ function parseRawEvaluatorLog(logPath) {
61276
61655
  resultSize: event.resultSize,
61277
61656
  pipelineCount: predStart.pipelineCount > 0 ? predStart.pipelineCount : void 0,
61278
61657
  evaluationStrategy: predStart.predicateType,
61279
- dependencies: predStart.dependencies
61658
+ dependencies: predStart.dependencies,
61659
+ raSteps: predStart.raSteps,
61660
+ pipelineStages: predStart.pipelineStages.length > 0 ? predStart.pipelineStages : void 0
61280
61661
  };
61281
61662
  const qEid = predStart.queryCausingWork ?? firstQueryEventId;
61282
61663
  if (qEid !== void 0) {
@@ -61316,16 +61697,17 @@ function parseRawEvaluatorLog(logPath) {
61316
61697
  codeqlVersion,
61317
61698
  logFormat: "raw",
61318
61699
  queries,
61319
- totalEvents: events.length
61700
+ totalEvents
61320
61701
  };
61321
61702
  }
61322
- function parseSummaryLog(logPath) {
61323
- const events = parseJsonObjects(logPath);
61703
+ async function processSummaryEvents(events) {
61324
61704
  let codeqlVersion;
61325
61705
  const queryPredicatesMap = /* @__PURE__ */ new Map();
61326
61706
  const queryTotalMs = /* @__PURE__ */ new Map();
61327
61707
  const queryCacheHits = /* @__PURE__ */ new Map();
61328
- for (const event of events) {
61708
+ let totalEvents = 0;
61709
+ for await (const event of events) {
61710
+ totalEvents++;
61329
61711
  if (event.summaryLogVersion !== void 0) {
61330
61712
  codeqlVersion = event.codeqlVersion;
61331
61713
  continue;
@@ -61342,6 +61724,11 @@ function parseSummaryLog(logPath) {
61342
61724
  const queryName = event.queryCausingWork || "unknown";
61343
61725
  const deps = event.dependencies;
61344
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
+ }
61345
61732
  const profile = {
61346
61733
  predicateName,
61347
61734
  position: event.position,
@@ -61349,7 +61736,8 @@ function parseSummaryLog(logPath) {
61349
61736
  resultSize: event.resultSize,
61350
61737
  pipelineCount: pipelineRuns,
61351
61738
  evaluationStrategy: strategy,
61352
- dependencies: deps ? Object.keys(deps) : []
61739
+ dependencies: deps ? Object.keys(deps) : [],
61740
+ raSteps
61353
61741
  };
61354
61742
  if (event.isCached === true || strategy === "CACHEHIT") {
61355
61743
  queryCacheHits.set(
@@ -61382,143 +61770,142 @@ function parseSummaryLog(logPath) {
61382
61770
  codeqlVersion,
61383
61771
  logFormat: "summary",
61384
61772
  queries,
61385
- totalEvents: events.length
61773
+ totalEvents
61386
61774
  };
61387
61775
  }
61388
- function parseEvaluatorLog(logPath) {
61389
- const events = parseJsonObjects(logPath);
61390
- 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) {
61391
61781
  return {
61392
61782
  logFormat: "raw",
61393
61783
  queries: [],
61394
61784
  totalEvents: 0
61395
61785
  };
61396
61786
  }
61397
- 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
+ }
61398
61797
  if (format === "raw") {
61399
- return parseRawEvaluatorLog(logPath);
61798
+ return processRawEvents(prependFirst());
61400
61799
  }
61401
- return parseSummaryLog(logPath);
61800
+ return processSummaryEvents(prependFirst());
61402
61801
  }
61403
61802
 
61404
61803
  // src/tools/codeql/profile-codeql-query-from-logs.ts
61405
61804
  init_logger();
61406
- function formatAsJson(profile) {
61407
- return JSON.stringify(profile, null, 2);
61805
+ function getTopPredicates(predicates, topN) {
61806
+ return [...predicates].sort((a, b) => b.durationMs - a.durationMs).slice(0, topN);
61408
61807
  }
61409
- function formatAsMermaid(profile, topN) {
61808
+ function buildDetailFile(profile, topN) {
61410
61809
  const lines = [];
61411
- lines.push("```mermaid");
61412
- 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.`);
61413
61817
  lines.push("");
61414
- if (profile.queries.length <= 1) {
61415
- const query = profile.queries[0] ?? {
61416
- queryName: "unknown",
61417
- totalDurationMs: 0,
61418
- predicates: [],
61419
- predicateCount: 0,
61420
- cacheHits: 0
61421
- };
61422
- const qLabel = sanitizeMermaid(basename4(query.queryName));
61423
- lines.push(
61424
- ` QUERY["${qLabel}<br/>Total: ${query.totalDurationMs.toFixed(2)}ms<br/>Predicates: ${query.predicateCount}"]`
61425
- );
61426
- lines.push("");
61427
- const topPredicates = getTopPredicates(query.predicates, topN);
61428
- topPredicates.forEach((pred, idx) => {
61429
- const nodeId = `P${idx}`;
61430
- const name = sanitizeMermaid(pred.predicateName).substring(0, 50);
61431
- const dur = pred.durationMs.toFixed(2);
61432
- const size = pred.resultSize !== void 0 ? String(pred.resultSize) : "?";
61433
- lines.push(
61434
- ` ${nodeId}["${name}<br/>${dur}ms | ${size} results"]`
61435
- );
61436
- });
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}`);
61437
61823
  lines.push("");
61438
- topPredicates.forEach((_pred, idx) => {
61439
- lines.push(` QUERY --> P${idx}`);
61824
+ const evalOrderMap = /* @__PURE__ */ new Map();
61825
+ query.predicates.forEach((pred, idx) => {
61826
+ evalOrderMap.set(pred, idx + 1);
61440
61827
  });
61441
- } else {
61442
- lines.push(
61443
- ` ROOT["Evaluation Log<br/>${profile.queries.length} queries"]`
61444
- );
61445
- lines.push("");
61446
- profile.queries.forEach((query, qIdx) => {
61447
- const qNodeId = `Q${qIdx}`;
61448
- const qLabel = sanitizeMermaid(basename4(query.queryName));
61449
- lines.push(
61450
- ` ${qNodeId}["${qLabel}<br/>${query.totalDurationMs.toFixed(2)}ms<br/>Predicates: ${query.predicateCount}"]`
61451
- );
61452
- lines.push(` ROOT --> ${qNodeId}`);
61453
- const topPredicates = getTopPredicates(query.predicates, topN);
61454
- topPredicates.forEach((pred, pIdx) => {
61455
- const nodeId = `Q${qIdx}P${pIdx}`;
61456
- const name = sanitizeMermaid(pred.predicateName).substring(0, 50);
61457
- const dur = pred.durationMs.toFixed(2);
61458
- const size = pred.resultSize !== void 0 ? String(pred.resultSize) : "?";
61459
- lines.push(
61460
- ` ${nodeId}["${name}<br/>${dur}ms | ${size} results"]`
61461
- );
61462
- lines.push(` ${qNodeId} --> ${nodeId}`);
61463
- });
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
+ }
61464
61859
  lines.push("");
61465
- });
61860
+ const endLine = lines.length;
61861
+ const key = `${qIdx}:${pred.predicateName}`;
61862
+ lineIndex.set(key, { start: startLine, end: endLine });
61863
+ }
61466
61864
  }
61467
- lines.push("");
61468
- lines.push(
61469
- " classDef default fill:#e1f5ff,stroke:#333,stroke-width:2px"
61470
- );
61471
- lines.push(
61472
- " classDef query fill:#ffe1e1,stroke:#333,stroke-width:3px"
61473
- );
61474
- lines.push(" class QUERY query");
61475
- lines.push("```");
61476
- return lines.join("\n");
61477
- }
61478
- function sanitizeMermaid(text) {
61479
- return text.replace(/[<>"]/g, "");
61480
- }
61481
- function getTopPredicates(predicates, topN) {
61482
- return [...predicates].sort((a, b) => b.durationMs - a.durationMs).slice(0, topN);
61865
+ return { content: lines.join("\n"), lineIndex };
61483
61866
  }
61484
- function buildTextSummary(profile, topN, outputFiles) {
61485
- const sections = [];
61486
- sections.push("Query log profiling completed successfully!");
61487
- sections.push("");
61488
- sections.push("Output Files:");
61489
- for (const f of outputFiles) {
61490
- sections.push(` - ${f}`);
61491
- }
61492
- sections.push("");
61493
- sections.push(`Log Format: ${profile.logFormat}`);
61494
- if (profile.codeqlVersion) {
61495
- sections.push(`CodeQL Version: ${profile.codeqlVersion}`);
61496
- }
61497
- sections.push(`Total Events: ${profile.totalEvents}`);
61498
- sections.push(`Queries: ${profile.queries.length}`);
61499
- for (const query of profile.queries) {
61500
- sections.push("");
61501
- sections.push(`--- ${basename4(query.queryName)} ---`);
61502
- sections.push(` Total Duration: ${query.totalDurationMs.toFixed(2)} ms`);
61503
- sections.push(` Predicates Evaluated: ${query.predicateCount}`);
61504
- 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
+ });
61505
61873
  const top = getTopPredicates(query.predicates, topN);
61506
- if (top.length > 0) {
61507
- sections.push(` Top ${top.length} Most Expensive Predicates:`);
61508
- top.forEach((pred, idx) => {
61509
- const sizeStr = pred.resultSize !== void 0 ? `, ${pred.resultSize} results` : "";
61510
- sections.push(
61511
- ` ${idx + 1}. ${pred.predicateName} (${pred.durationMs.toFixed(2)} ms${sizeStr})`
61512
- );
61513
- });
61514
- }
61515
- }
61516
- 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
+ };
61517
61904
  }
61518
61905
  function registerProfileCodeQLQueryFromLogsTool(server) {
61519
61906
  server.tool(
61520
61907
  "profile_codeql_query_from_logs",
61521
- "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.",
61522
61909
  {
61523
61910
  evaluatorLog: external_exports.string().describe(
61524
61911
  "Path to evaluator-log.jsonl or evaluator-log.summary.jsonl"
@@ -61527,7 +61914,7 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61527
61914
  "Directory to write profile output files (defaults to same directory as log)"
61528
61915
  ),
61529
61916
  topN: external_exports.number().optional().describe(
61530
- "Number of most expensive predicates to highlight (default: 20)"
61917
+ "Number of slowest predicates to include per query (default: 20)"
61531
61918
  )
61532
61919
  },
61533
61920
  async (params) => {
@@ -61539,51 +61926,42 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61539
61926
  content: [
61540
61927
  {
61541
61928
  type: "text",
61542
- text: `Evaluator log not found at: ${evaluatorLog}`
61929
+ text: JSON.stringify({ error: `Evaluator log not found at: ${evaluatorLog}` })
61543
61930
  }
61544
61931
  ],
61545
61932
  isError: true
61546
61933
  };
61547
61934
  }
61548
61935
  logger.info(`Parsing evaluator log from: ${evaluatorLog}`);
61549
- const profile = parseEvaluatorLog(evaluatorLog);
61936
+ const profile = await parseEvaluatorLog(evaluatorLog);
61550
61937
  const profileOutputDir = outputDir ?? dirname6(evaluatorLog);
61551
61938
  mkdirSync6(profileOutputDir, { recursive: true });
61552
- const jsonPath = join10(
61553
- profileOutputDir,
61554
- "query-evaluation-profile.json"
61555
- );
61556
- writeFileSync3(jsonPath, formatAsJson(profile));
61557
- logger.info(`Profile JSON written to: ${jsonPath}`);
61558
- const mdPath = join10(
61559
- profileOutputDir,
61560
- "query-evaluation-profile.md"
61561
- );
61562
- writeFileSync3(mdPath, formatAsMermaid(profile, effectiveTopN));
61563
- logger.info(`Profile Mermaid diagram written to: ${mdPath}`);
61564
- const outputFilesList = [
61565
- `Profile JSON: ${jsonPath}`,
61566
- `Profile Mermaid: ${mdPath}`,
61567
- `Evaluator Log: ${evaluatorLog}`
61568
- ];
61569
- const responseText = buildTextSummary(
61570
- profile,
61571
- effectiveTopN,
61572
- outputFilesList
61573
- );
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
+ });
61574
61951
  return {
61575
- content: [{ type: "text", text: responseText }]
61952
+ content: [
61953
+ { type: "text", text: JSON.stringify(response) }
61954
+ ]
61576
61955
  };
61577
61956
  } catch (error2) {
61578
- logger.error(
61579
- "Error profiling CodeQL query from logs:",
61580
- error2
61581
- );
61957
+ logger.error("Error profiling CodeQL query from logs:", error2);
61582
61958
  return {
61583
61959
  content: [
61584
61960
  {
61585
61961
  type: "text",
61586
- 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
+ })
61587
61965
  }
61588
61966
  ],
61589
61967
  isError: true
@@ -61596,76 +61974,114 @@ function registerProfileCodeQLQueryFromLogsTool(server) {
61596
61974
  // src/tools/codeql/profile-codeql-query.ts
61597
61975
  init_cli_executor();
61598
61976
  init_logger();
61599
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
61600
- import { join as join11, dirname as dirname7, basename as basename5 } from "path";
61977
+ import { writeFileSync as writeFileSync4, existsSync as existsSync10 } from "fs";
61978
+ import { createReadStream as createReadStream2 } from "fs";
61979
+ import { join as join12, dirname as dirname7, basename as basename5 } from "path";
61601
61980
  import { mkdirSync as mkdirSync7 } from "fs";
61602
- function parseEvaluatorLog2(logPath) {
61603
- const logContent = readFileSync8(logPath, "utf-8");
61604
- const jsonObjects = logContent.split("\n\n").filter((s) => s.trim());
61605
- const events = jsonObjects.map((obj) => {
61606
- try {
61607
- return JSON.parse(obj);
61608
- } catch (_error) {
61609
- logger.warn(`Failed to parse evaluator log object: ${obj.substring(0, 100)}...`);
61610
- return null;
61611
- }
61612
- }).filter((event) => event !== null);
61981
+ import { createInterface as createInterface2 } from "readline";
61982
+ async function parseEvaluatorLog2(logPath) {
61613
61983
  const pipelineMap = /* @__PURE__ */ new Map();
61614
61984
  const predicateNameToEventId = /* @__PURE__ */ new Map();
61985
+ const predicateStartNanoTimes = /* @__PURE__ */ new Map();
61615
61986
  let queryName = "";
61616
61987
  let queryStartTime = 0;
61617
61988
  let queryEndTime = 0;
61618
- for (const event of events) {
61619
- switch (event.type) {
61620
- case "QUERY_STARTED":
61621
- queryName = event.queryName || "";
61622
- queryStartTime = event.nanoTime;
61623
- break;
61624
- case "QUERY_COMPLETED":
61625
- queryEndTime = event.nanoTime;
61626
- break;
61627
- case "PREDICATE_STARTED": {
61628
- const predicateName = event.predicateName;
61629
- const position = event.position;
61630
- const predicateType = event.predicateType;
61631
- const dependencies = event.dependencies;
61632
- predicateNameToEventId.set(predicateName, event.eventId);
61633
- const dependencyEventIds = [];
61634
- const dependencyNames = [];
61635
- if (dependencies) {
61636
- for (const depName of Object.keys(dependencies)) {
61637
- dependencyNames.push(depName);
61638
- const depEventId = predicateNameToEventId.get(depName);
61639
- if (depEventId !== void 0) {
61640
- 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
+ }
61641
62059
  }
61642
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;
61643
62071
  }
61644
- pipelineMap.set(event.eventId, {
61645
- eventId: event.eventId,
61646
- name: predicateName,
61647
- position,
61648
- type: predicateType,
61649
- startTime: event.nanoTime,
61650
- dependencies: dependencyNames,
61651
- dependencyEventIds
61652
- });
61653
- break;
61654
- }
61655
- case "PREDICATE_COMPLETED": {
61656
- const startEventId = event.startEvent;
61657
- const pipelineInfo = pipelineMap.get(startEventId);
61658
- if (pipelineInfo) {
61659
- const startEvent = events.find((e) => e.eventId === startEventId);
61660
- if (startEvent) {
61661
- 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;
61662
62078
  pipelineInfo.endTime = event.nanoTime;
61663
62079
  pipelineInfo.duration = duration3;
61664
62080
  pipelineInfo.resultSize = event.resultSize;
61665
62081
  pipelineInfo.tupleCount = event.tupleCount;
61666
62082
  }
62083
+ break;
61667
62084
  }
61668
- break;
61669
62085
  }
61670
62086
  }
61671
62087
  }
@@ -61674,14 +62090,14 @@ function parseEvaluatorLog2(logPath) {
61674
62090
  return {
61675
62091
  queryName,
61676
62092
  totalDuration,
61677
- totalEvents: events.length,
62093
+ totalEvents,
61678
62094
  pipelines
61679
62095
  };
61680
62096
  }
61681
- function formatAsJson2(profile) {
62097
+ function formatAsJson(profile) {
61682
62098
  return JSON.stringify(profile, null, 2);
61683
62099
  }
61684
- function formatAsMermaid2(profile) {
62100
+ function formatAsMermaid(profile) {
61685
62101
  const lines = [];
61686
62102
  lines.push("```mermaid");
61687
62103
  lines.push("graph TD");
@@ -61734,11 +62150,11 @@ function registerProfileCodeQLQueryTool(server) {
61734
62150
  let sarifPath;
61735
62151
  if (!logPath) {
61736
62152
  logger.info("No evaluator log provided, running query to generate one");
61737
- const defaultOutputDir = outputDir || join11(dirname7(query), "profile-output");
62153
+ const defaultOutputDir = outputDir || join12(dirname7(query), "profile-output");
61738
62154
  mkdirSync7(defaultOutputDir, { recursive: true });
61739
- logPath = join11(defaultOutputDir, "evaluator-log.jsonl");
61740
- bqrsPath = join11(defaultOutputDir, "query-results.bqrs");
61741
- sarifPath = join11(defaultOutputDir, "query-results.sarif");
62155
+ logPath = join12(defaultOutputDir, "evaluator-log.jsonl");
62156
+ bqrsPath = join12(defaultOutputDir, "query-results.bqrs");
62157
+ sarifPath = join12(defaultOutputDir, "query-results.sarif");
61742
62158
  const queryResult = await executeCodeQLCommand(
61743
62159
  "query run",
61744
62160
  {
@@ -61788,15 +62204,15 @@ function registerProfileCodeQLQueryTool(server) {
61788
62204
  };
61789
62205
  }
61790
62206
  logger.info(`Parsing evaluator log from: ${logPath}`);
61791
- const profile = parseEvaluatorLog2(logPath);
62207
+ const profile = await parseEvaluatorLog2(logPath);
61792
62208
  const profileOutputDir = outputDir || dirname7(logPath);
61793
62209
  mkdirSync7(profileOutputDir, { recursive: true });
61794
- const jsonPath = join11(profileOutputDir, "query-evaluation-profile.json");
61795
- const jsonContent = formatAsJson2(profile);
62210
+ const jsonPath = join12(profileOutputDir, "query-evaluation-profile.json");
62211
+ const jsonContent = formatAsJson(profile);
61796
62212
  writeFileSync4(jsonPath, jsonContent);
61797
62213
  logger.info(`Profile JSON written to: ${jsonPath}`);
61798
- const mdPath = join11(profileOutputDir, "query-evaluation-profile.md");
61799
- const mdContent = formatAsMermaid2(profile);
62214
+ const mdPath = join12(profileOutputDir, "query-evaluation-profile.md");
62215
+ const mdContent = formatAsMermaid(profile);
61800
62216
  writeFileSync4(mdPath, mdContent);
61801
62217
  logger.info(`Profile Mermaid diagram written to: ${mdPath}`);
61802
62218
  const outputFiles = [
@@ -61946,7 +62362,7 @@ var codeqlQueryRunTool = {
61946
62362
  };
61947
62363
 
61948
62364
  // src/tools/codeql/quick-evaluate.ts
61949
- import { join as join12, resolve as resolve6 } from "path";
62365
+ import { join as join13, resolve as resolve6 } from "path";
61950
62366
  init_logger();
61951
62367
  init_temp_dir();
61952
62368
  async function quickEvaluate({
@@ -61965,7 +62381,7 @@ async function quickEvaluate({
61965
62381
  throw new Error(`Symbol '${symbol}' not found as class or predicate in file: ${file}`);
61966
62382
  }
61967
62383
  }
61968
- const resolvedOutput = resolve6(output_path || join12(getProjectTmpDir("quickeval"), "quickeval.bqrs"));
62384
+ const resolvedOutput = resolve6(output_path || join13(getProjectTmpDir("quickeval"), "quickeval.bqrs"));
61969
62385
  return resolvedOutput;
61970
62386
  } catch (error2) {
61971
62387
  throw new Error(`CodeQL evaluation failed: ${error2 instanceof Error ? error2.message : "Unknown error"}`, { cause: error2 });
@@ -62005,8 +62421,8 @@ function registerQuickEvaluateTool(server) {
62005
62421
 
62006
62422
  // src/tools/codeql/read-database-source.ts
62007
62423
  var import_adm_zip = __toESM(require_adm_zip(), 1);
62008
- import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
62009
- import { join as join13, resolve as resolve7 } from "path";
62424
+ import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync8, statSync as statSync7 } from "fs";
62425
+ import { join as join14, resolve as resolve7 } from "path";
62010
62426
  import { fileURLToPath as fileURLToPath2 } from "url";
62011
62427
  init_logger();
62012
62428
  var DEFAULT_MAX_LISTING_ENTRIES = 1e3;
@@ -62022,9 +62438,9 @@ function toFilesystemPath(uri) {
62022
62438
  return uri;
62023
62439
  }
62024
62440
  function* walkDirectory(dir, base = dir) {
62025
- for (const entry of readdirSync5(dir)) {
62026
- const fullPath = join13(dir, entry);
62027
- if (statSync5(fullPath).isDirectory()) {
62441
+ for (const entry of readdirSync7(dir)) {
62442
+ const fullPath = join14(dir, entry);
62443
+ if (statSync7(fullPath).isDirectory()) {
62028
62444
  yield* walkDirectory(fullPath, base);
62029
62445
  } else {
62030
62446
  yield fullPath.slice(base.length).replace(/\\/g, "/").replace(/^\//, "");
@@ -62090,8 +62506,8 @@ async function readDatabaseSource(params) {
62090
62506
  if (!existsSync11(resolvedDbPath)) {
62091
62507
  throw new Error(`Database path does not exist: ${databasePath}`);
62092
62508
  }
62093
- const srcZipPath = join13(resolvedDbPath, "src.zip");
62094
- const srcDirPath = join13(resolvedDbPath, "src");
62509
+ const srcZipPath = join14(resolvedDbPath, "src.zip");
62510
+ const srcDirPath = join14(resolvedDbPath, "src");
62095
62511
  const hasSrcZip = existsSync11(srcZipPath);
62096
62512
  const hasSrcDir = existsSync11(srcDirPath);
62097
62513
  if (!hasSrcZip && !hasSrcDir) {
@@ -62166,8 +62582,8 @@ Archive contains ${availableEntries.length} entries. Use read_database_source wi
62166
62582
  Directory contains ${availableEntries.length} entries. Use read_database_source without filePath to list available entries.`
62167
62583
  );
62168
62584
  }
62169
- const fullPath = join13(srcDirPath, matchedRelative);
62170
- const rawContent = readFileSync9(fullPath, "utf-8");
62585
+ const fullPath = join14(srcDirPath, matchedRelative);
62586
+ const rawContent = readFileSync8(fullPath, "utf-8");
62171
62587
  const { content, effectiveEnd, effectiveStart, totalLines } = applyLineRange(
62172
62588
  rawContent,
62173
62589
  startLine,
@@ -62326,6 +62742,32 @@ var codeqlResolveDatabaseTool = {
62326
62742
  resultProcessor: defaultCLIResultProcessor
62327
62743
  };
62328
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
+
62329
62771
  // src/tools/codeql/resolve-languages.ts
62330
62772
  var codeqlResolveLanguagesTool = {
62331
62773
  name: "codeql_resolve_languages",
@@ -62470,6 +62912,255 @@ var codeqlResolveTestsTool = {
62470
62912
  resultProcessor: defaultCLIResultProcessor
62471
62913
  };
62472
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
+
62473
63164
  // src/tools/codeql/test-accept.ts
62474
63165
  var codeqlTestAcceptTool = {
62475
63166
  name: "codeql_test_accept",
@@ -62740,6 +63431,7 @@ function registerCodeQLTools(server) {
62740
63431
  registerCLITool(server, codeqlQueryFormatTool);
62741
63432
  registerCLITool(server, codeqlQueryRunTool);
62742
63433
  registerCLITool(server, codeqlResolveDatabaseTool);
63434
+ registerCLITool(server, codeqlResolveFilesTool);
62743
63435
  registerCLITool(server, codeqlResolveLanguagesTool);
62744
63436
  registerCLITool(server, codeqlResolveLibraryPathTool);
62745
63437
  registerCLITool(server, codeqlResolveMetadataTool);
@@ -62760,78 +63452,201 @@ function registerCodeQLTools(server) {
62760
63452
  registerQuickEvaluateTool(server);
62761
63453
  registerReadDatabaseSourceTool(server);
62762
63454
  registerRegisterDatabaseTool(server);
63455
+ registerSearchQlCodeTool(server);
62763
63456
  }
62764
63457
 
63458
+ // src/resources/dataflow-migration-v1-to-v2.md
63459
+ var dataflow_migration_v1_to_v2_default = '# Dataflow API Migration: v1 to v2\n\nGuide for migrating CodeQL queries from the legacy v1 (class-based) dataflow API to the modern v2 (module-based) shared dataflow API. This applies to all supported languages.\n\n## Why Migrate\n\nThe v1 `DataFlow::Configuration` class-based API is deprecated. The v2 `DataFlow::ConfigSig` module-based API is the current standard across all languages. Queries using v1 will eventually stop compiling as the legacy API is removed.\n\n## API Changes Summary\n\n| v1 (Legacy) | v2 (Modern) | Notes |\n| ------------------------------------------------ | ------------------------------------------------ | --------------------------------------- |\n| `class MyConfig extends DataFlow::Configuration` | `module MyConfig implements DataFlow::ConfigSig` | Module-based, not class-based |\n| `MyConfig() { this = "MyConfig" }` | _(removed)_ | No constructor needed |\n| `override predicate isSanitizer(...)` | `predicate isBarrier(...)` | Renamed |\n| `override predicate isAdditionalTaintStep(...)` | `predicate isAdditionalFlowStep(...)` | Renamed |\n| `config.hasFlowPath(source, sink)` | `MyFlow::flowPath(source, sink)` | Module-level predicate |\n| `DataFlow::PathNode` | `MyFlow::PathNode` | Path nodes scoped to flow module |\n| `isSanitizerGuard` | _(removed \u2014 use `isBarrier` with guard logic)_ | Fold guard into barrier |\n| `FlowLabel` (JS) | `FlowState` | Renamed; use `DataFlow::StateConfigSig` |\n\n## v1 Pattern\n\n```ql\nclass MyConfig extends DataFlow::Configuration {\n MyConfig() { this = "MyConfig" }\n override predicate isSource(DataFlow::Node source) { ... }\n override predicate isSink(DataFlow::Node sink) { ... }\n override predicate isSanitizer(DataFlow::Node node) { ... }\n override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { ... }\n}\n\nfrom MyConfig config, DataFlow::PathNode source, DataFlow::PathNode sink\nwhere config.hasFlowPath(source, sink)\nselect sink, source, sink, "Message"\n```\n\n## v2 Pattern\n\n```ql\nmodule MyConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) { ... }\n predicate isSink(DataFlow::Node sink) { ... }\n predicate isBarrier(DataFlow::Node node) { ... }\n predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { ... }\n}\n\nmodule MyFlow = TaintTracking::Global<MyConfig>;\nimport MyFlow::PathGraph\n\nfrom MyFlow::PathNode source, MyFlow::PathNode sink\nwhere MyFlow::flowPath(source, sink)\nselect sink.getNode(), source, sink, "Message"\n```\n\n## Migration Workflow\n\n1. **Capture baseline**: Run `codeql_test_run` on existing tests and save current `.expected` files\n2. **Rewrite config**: Replace the `class extends Configuration` with `module implements ConfigSig`, rename predicates per the table above\n3. **Instantiate module**: Add `module MyFlow = TaintTracking::Global<MyConfig>;` (or `DataFlow::Global<MyConfig>` for pure data flow)\n4. **Update select clause**: Replace `config.hasFlowPath(source, sink)` with `MyFlow::flowPath(source, sink)` and `DataFlow::PathNode` with `MyFlow::PathNode`\n5. **Handle flow state**: If the query uses `FlowLabel` (JS) or state-sensitive predicates, switch to `DataFlow::StateConfigSig` and `TaintTracking::GlobalWithState<MyConfig>`\n6. **Compile**: Run `codeql_query_compile` to catch syntax errors\n7. **Test**: Run `codeql_test_run` and verify results match the v1 baseline exactly\n8. **Accept**: Once equivalent, run `codeql_test_accept` to finalize\n\n## Language-Specific Notes\n\n### C/C++\n\n- Import paths stay the same (`semmle.code.cpp.dataflow.TaintTracking`); only the API usage changes.\n- Pointer indirection: use `asIndirectExpr()` in `isAdditionalFlowStep` to track through dereferences.\n- Track `std::move` operations as additional flow steps when relevant.\n- `IndirectParameterNode` usage is unchanged between v1 and v2.\n\n### C\\#\n\n- Use `semmle.code.csharp.dataflow.TaintTracking` (same import for v1 and v2).\n- `LibraryTypeDataFlow` extensions for custom library flow are unchanged.\n- Test LINQ, async/await, and property accessor patterns \u2014 these can surface subtle differences.\n- ASP.NET `[FromBody]`/`[FromQuery]` parameter annotations work identically.\n\n### Go\n\n- Node types (`ExprNode`, `ParameterNode`, `InstructionNode`) and AST/IR conversions (`asExpr()`, `asInstruction()`) are unchanged.\n- `RemoteFlowSource` and `UntrustedFlowSource` work identically in v2.\n- Channel send/receive and goroutine flow require `isAdditionalFlowStep`; these patterns are unchanged.\n- Error-handling tuples: use `ResultNode` with `hasResultIndex(0)` for the value element.\n- Interface type assertions (`TypeAssertExpr`) need explicit flow steps.\n\n### Java / Kotlin\n\n- `InstanceParameterNode` (implicit `this`) is unchanged.\n- Spring `@RequestParam`/`@PathVariable`/`@RequestBody` annotations work identically.\n- Stream/lambda/method-reference flows and boxing/unboxing steps carry over directly.\n- Kotlin `when` expressions and extension function receiver flow require explicit `isAdditionalFlowStep`.\n\n### JavaScript / TypeScript\n\n- **Flow labels \u2192 Flow states**: If the v1 query uses `FlowLabel`, switch to `DataFlow::StateConfigSig` with `class FlowState = string;` and `TaintTracking::GlobalWithState<MyConfig>`.\n- **Sanitizer guards \u2192 Barrier guards**: `isSanitizerGuard` becomes `isBarrierGuard` with `DataFlow::BarrierGuard`.\n- **Behavioral changes**: v2 taint steps propagate all flow states (not just `taint`). Jump steps across function boundaries (callbacks, Promises) may behave differently \u2014 watch for new or missing results.\n- Promise `.then()` and async/await flow, prototype pollution via `Object.assign`/spread, and module import/export flow are unchanged.\n\n### Python\n\n- Python has multiple dataflow nodes per expression due to CFG splitting. This behavior is identical in v2.\n- `CfgNode` / `CallCfgNode` / `getCfgNode()` conversions are unchanged.\n- API graph navigation (`API::moduleImport("pkg").getMember(...)`) is unchanged.\n- Django ORM, Flask routing, and FastAPI dependency injection patterns carry over directly.\n\n### Ruby\n\n- `asExpr()` returns `CfgNodes::ExprCfgNode` (CFG node, not AST). Use `.getExpr()` to get the AST node. This is unchanged between v1 and v2.\n- Rails `params`, ActiveRecord queries, and metaprogramming (`send`, `define_method`, `eval`) patterns carry over directly.\n- String interpolation and block/lambda flows are unchanged.\n\n### Swift\n\n- Import paths differ from other languages: `codeql.swift.dataflow.DataFlow`, `codeql.swift.dataflow.TaintTracking`, `codeql.swift.dataflow.FlowSources`.\n- Unique node types: `PatternNode`, `CaptureNode`, `InoutReturnNode`, `SsaDefinitionNode`.\n- `RemoteFlowSource` and `LocalFlowSource` from `codeql.swift.dataflow.FlowSources` work identically.\n- Requires macOS with Xcode for test extraction. Supports Swift 5.4\u20136.2.\n\n## Critical: Result Equivalence\n\nMigrated queries **must** produce identical results to the v1 version. Differences indicate a semantic change in the migration. Common causes:\n\n- **Barrier scope**: v2 barriers block all flow states; v1 sanitizers may have been state-specific\n- **Additional flow steps**: v2 uses `isAdditionalFlowStep` for both data flow and taint; v1 had separate `isAdditionalTaintStep`\n- **Jump steps** (JS): Taint propagation across function boundaries may differ\n';
63460
+
63461
+ // src/resources/learning-query-basics.md
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';
63463
+
63464
+ // src/resources/performance-patterns.md
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';
63466
+
63467
+ // src/resources/ql-test-driven-development.md
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";
63469
+
63470
+ // src/resources/codeql-query-unit-testing.md
63471
+ var codeql_query_unit_testing_default = '# CodeQL Query Unit Testing\n\nGuide for creating and running unit tests for CodeQL queries. For the broader TDD workflow (write tests, implement, iterate), see the `test_driven_development` resource and `ql_tdd_basic` / `ql_tdd_advanced` prompts.\n\n## Test Directory Layout\n\nThere is no one single way to arrange CodeQL unit tests, though there are some commonalities.\n\nFor a recommended setup that uses separate "qlpacks" for CodeQL queries versus tests, a given CodeQL query and associated unit test may be laid out on the filesystem like:\n\n```text\n<query-pack-root>/<optional-queries-subdir>/{QueryName}/\n\u251C\u2500\u2500 {QueryName}.{md,qhelp} # Recommended query documentation file\n\u251C\u2500\u2500 {QueryName}.ql # Required query implementation file\n\u2514\u2500\u2500 {QueryName}.qll # Optional query-specific library file\n<test-pack-root>/<optional-tests-subdir>/{QueryOrTestName}/\n\u251C\u2500\u2500 {QueryName}.qlref # qlref file contents point to the path of the query, relative to <query-pack-root>\n\u251C\u2500\u2500 Example1.{ext} # Test source code (positive + negative cases)\n\u251C\u2500\u2500 {QueryName}.actual # Actual test results; created dynamically via `codeql_test_run` tool\n\u251C\u2500\u2500 {QueryName}.expected # Expected query results; defined prior to calling `codeql_test_run` tool\n\u2514\u2500\u2500 {QueryName}.testproj/ # Test database; auto-created by `codeql_test_extract` or `codeql_test_run` tools\n```\n\n## File Extensions by Language\n\n| Language | Test source extension(s) | Notes |\n| ---------- | ------------------------ | ---------------------------------------- |\n| C/C++ | `.cpp`, `.c`, `.h` | Use header files for shared declarations |\n| C# | `.cs` | |\n| Go | `.go` | Must include `package` declaration |\n| Java | `.java` | Must include `class` matching filename |\n| JavaScript | `.js` | Use `.ts` for TypeScript |\n| Python | `.py` | |\n| Ruby | `.rb` | |\n| Swift | `.swift` | |\n\n## Creating a Test\n\n### 1. Query Reference File (`{QueryName}.qlref`)\n\nSingle line with the path to the query, relative to the query pack root:\n\n```sh\nsrc/{QueryName}/{QueryName}.ql\n```\n\n### 2. Test Source Code\n\nWrite test source files containing:\n\n- **Positive cases**: Code patterns the query **should** detect\n- **Negative cases**: Safe code the query **should not** flag\n- **Edge cases**: Boundary conditions and unusual but valid patterns\n\nAdd comments to describe what each section tests.\n\n### 3. Expected Results (`{QueryName}.expected`)\n\nTabular format matching the query\'s `select` clause columns:\n\n```text\n| file | line | col | endLine | endCol | message |\n| Example1.js | 5 | 1 | 7 | 2 | Function: myFunc |\n```\n\nLeave the file empty or create it with a placeholder initially \u2014 run the query to generate actual results, then baseline with `codeql_test_accept`.\n\n## Language-Specific Notes\n\n### C/C++\n\n- Use an `options` file in the test directory to set the C++ standard (e.g., `--std=c++17`).\n- Include header files with include guards when testing patterns that span headers.\n- Test pointer/reference, smart pointer, template instantiation, and STL container patterns as relevant.\n- Key AST nodes: `Function`, `MemberFunction`, `Constructor`, `Class`, `Struct`, `PointerDereferenceExpr`, `FunctionCall`, `NewExpr`, `DeleteExpr`, `TemplateClass`, `TemplateFunction`.\n\n### C\\#\n\n- Always include required `using` statements so test code compiles.\n- Test .NET-specific patterns: LINQ, async/await, properties, pattern matching, ASP.NET controllers, Entity Framework.\n- Key AST nodes: `Class`, `Method`, `Property`, `MethodCall`, `QueryExpr`, `AwaitExpr`, `Annotation`.\n\n### Go\n\n- Every test file must have a `package` declaration (typically `package main`).\n- Test goroutine, channel, interface assertion, and error-handling patterns as relevant.\n- Key AST nodes: `Function`, `CallExpr`, `SelectorExpr`, `GoStmt`, `SendStmt`, `TypeAssertExpr`.\n\n### Java\n\n- Each `.java` test file must contain a `public class` matching the filename.\n- Test annotations, generics, lambda expressions, streams, and try-with-resources as relevant.\n- Supports Spring, Servlet, and Jakarta EE framework patterns.\n- Key AST nodes: `Method`, `Constructor`, `Class`, `MethodCall`, `LambdaExpr`, `MethodReference`, `Annotation`, `TypeVariable`.\n\n### JavaScript / TypeScript\n\n- Both CommonJS (`require`) and ES modules (`import`) are supported.\n- Use `.ts` for TypeScript; JSX is supported in `.jsx`/`.tsx` files.\n- Test browser APIs (DOM, `document.write`), Node.js APIs (`child_process`, `fs`), and framework patterns (Express, React) as relevant.\n- Test async/await, Promises, and callback patterns.\n- Key AST nodes: `Function`, `ArrowFunctionExpr`, `CallExpr`, `MethodCallExpr`, `PropAccess`, `AwaitExpr`, `TemplateLiteral`.\n\n### Python\n\n- Supports both Python 2 and Python 3 syntax.\n- Test decorators, async/await, type hints, and dynamic code execution (`eval`, `exec`) as relevant.\n- Test framework patterns: Django (ORM, templates), Flask (request, routing), FastAPI (dependency injection).\n- Key AST nodes: `FunctionDef`, `ClassDef`, `Call`, `Attribute`, `Name`, `Lambda`, `Await`.\n\n### Ruby\n\n- Test metaprogramming (`send`, `define_method`, `eval`), blocks/lambdas, and string interpolation as relevant.\n- Test Rails patterns (params, ActiveRecord, ActionView) and gem-specific APIs (Sinatra, Grape).\n- Note: `asExpr()` in Ruby returns `CfgNodes::ExprCfgNode` (CFG node), not an AST node; use `.getExpr()` to get the AST node.\n- Key AST nodes: `MethodCall`, `Block`, `StringInterpolation`, `ConstantReadAccess`.\n\n### Swift\n\n- Requires macOS with Xcode installed for test extraction.\n- Supports Swift 5.4 through 6.2.\n- Test iOS/macOS framework patterns: Foundation, UIKit, Security, CryptoKit, WKWebView.\n- Test actors, property wrappers, async/await, and result builders as relevant.\n- Key AST nodes: `ClassDecl`, `StructDecl`, `FuncDecl`, `CallExpr`, `MemberRefExpr`, `ClosureExpr`, `GuardStmt`.\n\n## MCP Tool Workflow\n\n| Step | Tool | Purpose |\n| --------------------- | ----------------------------- | ----------------------------------------- |\n| Create test files | `create_codeql_query` | Scaffold query + test + `.qlref` |\n| Install dependencies | `codeql_pack_install` | Install pack dependencies |\n| Extract test database | `codeql_test_extract` | Build test DB from source files |\n| Inspect AST | `codeql_query_run` (PrintAST) | Understand how test code is represented |\n| Run tests | `codeql_test_run` | Compare actual vs. expected results |\n| Accept results | `codeql_test_accept` | Baseline correct results into `.expected` |\n';
63472
+
63473
+ // src/resources/security-templates.md
63474
+ var security_templates_default = '# Security Query Templates\n\nThis resource provides actionable security query templates for multiple languages and vulnerability classes. Each template shows the recommended query structure, explains how to adapt it, and references the MCP tools and TDD workflow to use during development.\n\n## General Workflow for Security Queries\n\n1. **Scaffold**: Use `create_codeql_query` to generate the query, test, and `.qlref` files\n2. **Write tests**: Create test source code with vulnerable (positive) and safe (negative) examples\n3. **Analyze AST**: Use `codeql_query_run` with `queryName="PrintAST"` to understand code representation\n4. **Implement**: Write the query using the taint tracking / data flow template below\n5. **Compile**: Use `codeql_query_compile` to validate syntax\n6. **Test**: Use `codeql_test_run` to run tests; iterate until all pass\n7. **Accept**: Use `codeql_test_accept` to baseline correct results\n\nSee the `test_driven_development` or `ql_tdd_basic` prompts for guided step-by-step workflows.\n\n## Taint Tracking Template (v2 API)\n\nMost security queries use taint tracking to find data flowing from untrusted sources to dangerous sinks. The standard template structure for all languages is:\n\n```ql\n/**\n * @name <Vulnerability Name>\n * @description <Description of the vulnerability>\n * @kind path-problem\n * @problem.severity error\n * @security-severity <CVSS score>\n * @precision high\n * @id <lang>/<vulnerability-id>\n * @tags security\n * external/cwe/cwe-<NNN>\n */\n\nimport <language>\n\nmodule MyFlowConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n // Define untrusted input sources\n }\n\n predicate isSink(DataFlow::Node sink) {\n // Define dangerous sinks\n }\n\n predicate isBarrier(DataFlow::Node node) {\n // Define sanitizers that make data safe (optional)\n }\n}\n\nmodule MyFlow = TaintTracking::Global<MyFlowConfig>;\n\nimport MyFlow::PathGraph\n\nfrom MyFlow::PathNode source, MyFlow::PathNode sink\nwhere MyFlow::flowPath(source, sink)\nselect sink.getNode(), source, sink, "Tainted data from $@ reaches this sink.",\n source.getNode(), "user-provided value"\n```\n\n### Adapting the Template\n\n1. **Choose sources**: Identify where untrusted data enters (HTTP parameters, file reads, environment variables)\n2. **Choose sinks**: Identify where data becomes dangerous (SQL queries, command execution, HTML output)\n3. **Add sanitizers**: Identify validation or encoding functions that neutralize the threat\n4. **Adjust metadata**: Set appropriate `@security-severity`, `@id`, and CWE tags\n\n## Source, Sink, and Sanitizer Patterns\n\n### Defining Sources\n\nSources represent entry points for untrusted data. The most common pattern uses `RemoteFlowSource`:\n\n```ql\npredicate isSource(DataFlow::Node source) {\n source instanceof RemoteFlowSource\n}\n```\n\n### Defining Sinks\n\nSinks are locations where untrusted data causes harm. Identify the dangerous API call and pin the taint to the relevant argument position:\n\n```ql\npredicate isSink(DataFlow::Node sink) {\n exists(CallExpr dangerousCall |\n dangerousCall.getTarget().hasName("vulnerableFunction") and\n sink.asExpr() = dangerousCall.getArgument(0)\n )\n}\n```\n\n### Defining Sanitizers (Barriers)\n\nSanitizers stop taint propagation when data is validated or encoded. Return `true` for nodes where the taint is neutralized:\n\n```ql\npredicate isBarrier(DataFlow::Node node) {\n exists(CallExpr validationCall |\n validationCall.getTarget().hasName("sanitize") and\n node.asExpr() = validationCall\n )\n}\n```\n\n## Language-Specific Guidance\n\nEach language has pre-built security libraries in the CodeQL standard library. Import these instead of writing source/sink definitions from scratch when possible.\n\n### Go\n\n- **SQL Injection**: Import `semmle.go.security.SqlInjection` \u2014 provides `SqlInjection::Flow` module with pre-defined sources and sinks. Tag with CWE-089, severity 8.8.\n- **Command Injection**: Import `semmle.go.security.CommandInjection`.\n- See `codeql://languages/go/security` for Go-specific framework modeling.\n\n### JavaScript / TypeScript\n\n- **DOM-based XSS**: Import `semmle.javascript.security.dataflow.DomBasedXss` \u2014 provides `DomBasedXss::Flow` module. Tag with CWE-079, severity 6.1.\n- **SQL Injection**: Import `semmle.javascript.security.dataflow.SqlInjection`.\n- See `codeql://languages/javascript/security` for JavaScript-specific patterns.\n\n### Python\n\n- **Command Injection**: Import `semmle.python.security.dataflow.CommandInjection`. Tag with CWE-078, severity 9.8.\n- **SQL Injection**: Import `semmle.python.security.dataflow.SqlInjection`.\n- See `codeql://languages/python/security` for Python-specific patterns.\n\n### Java / Kotlin\n\n- **SQL Injection**: Import `semmle.java.security.SqlInjectionQuery` \u2014 provides `SqlInjectionFlow` module. Tag with CWE-089, severity 8.8.\n- **SSRF**: Import `semmle.java.security.RequestForgery`.\n\n### C# (.NET)\n\n- **Path Traversal**: Import `semmle.csharp.security.dataflow.PathInjection`. Tag with CWE-022, severity 7.5.\n- **SQL Injection**: Import `semmle.csharp.security.dataflow.SqlInjection`.\n- See `codeql://languages/csharp/security` for C#-specific patterns.\n\n### C / C++\n\n- **Buffer Overflow**: Import `semmle.code.cpp.security.BufferAccess`. Tag with CWE-120, severity 9.8.\n- See `codeql://languages/cpp/security` for C/C++-specific patterns.\n\n## Vulnerability Classes Reference\n\n| Vulnerability | CWE | Typical Sources | Typical Sinks |\n| ----------------- | ------- | ---------------------------------- | ----------------------------- |\n| SQL Injection | CWE-089 | HTTP parameters, form data | Database query functions |\n| XSS | CWE-079 | HTTP parameters, URL data | HTML output, DOM writes |\n| Command Injection | CWE-078 | HTTP parameters, config files | `exec`, `system`, `popen` |\n| Path Traversal | CWE-022 | HTTP parameters, file names | File system access functions |\n| SSRF | CWE-918 | HTTP parameters, user URLs | HTTP client request functions |\n| Code Injection | CWE-094 | HTTP parameters, deserialized data | `eval`, template engines |\n| LDAP Injection | CWE-090 | HTTP parameters | LDAP query functions |\n| XML Injection | CWE-091 | HTTP parameters | XML parsers, XPath queries |\n\n## Related Resources\n\n- `codeql://learning/query-basics` \u2014 Query structure and metadata reference\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for developing queries\n- `codeql://patterns/performance` \u2014 Performance optimization guidance\n- `codeql://languages/{language}/security` \u2014 Language-specific security patterns and framework modeling\n';
63475
+
63476
+ // src/resources/server-overview.md
63477
+ var server_overview_default = '# CodeQL Development MCP Server \u2014 Getting Started\n\nThis resource is the primary onboarding guide for LLM clients connecting to the CodeQL Development MCP Server. It explains what the server provides, which tools and prompts are available, and how to orchestrate common workflows.\n\n## What This Server Does\n\nThe CodeQL Development MCP Server wraps the CodeQL CLI and supporting utilities behind the Model Context Protocol (MCP). It exposes **tools** (executable actions), **prompts** (reusable workflow templates), and **resources** (reference material) that enable an LLM to develop, test, and analyze CodeQL queries without direct shell access.\n\n## Available Resources\n\nRead these resources via `resources/read` to deepen your understanding:\n\n| URI | Purpose |\n| --------------------------------------------- | --------------------------------------------------- |\n| `codeql://server/overview` | This guide \u2014 MCP server orientation |\n| `codeql://server/queries` | Bundled tools queries (PrintAST, PrintCFG, etc.) |\n| `codeql://server/tools` | Complete default tool reference |\n| `codeql://server/prompts` | Complete prompt reference |\n| `codeql://learning/query-basics` | QL query writing reference (syntax, metadata, etc.) |\n| `codeql://learning/test-driven-development` | TDD theory and workflow for CodeQL |\n| `codeql://templates/security` | Security query templates (multi-language) |\n| `codeql://patterns/performance` | Performance profiling and optimization |\n| `codeql://guides/query-unit-testing` | Guide for creating and running CodeQL query tests |\n| `codeql://guides/dataflow-migration-v1-to-v2` | Migrating from v1 to v2 dataflow API |\n| `codeql://languages/{language}/ast` | Language-specific AST class reference |\n| `codeql://languages/{language}/security` | Language-specific security patterns |\n\n## Quick-Start Workflows\n\n### 1. Create a New Query (TDD Approach)\n\nUse the `test_driven_development` prompt (or `ql_tdd_basic` / `ql_tdd_advanced`):\n\n1. `create_codeql_query` \u2014 scaffold query, test files, and `.qlref`\n2. `codeql_pack_install` \u2014 install pack dependencies\n3. Write test code with positive and negative cases\n4. `codeql_test_run` \u2014 run tests (expect failure initially)\n5. Implement query logic\n6. `codeql_query_compile` \u2014 validate syntax\n7. `codeql_test_run` \u2014 iterate until tests pass\n8. `codeql_test_accept` \u2014 accept correct results as baseline\n\n### 2. Understand Code Structure\n\nUse the `tools_query_workflow` prompt:\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### 3. Analyze Query Quality\n\n1. `codeql_database_analyze` \u2014 run queries against a database\n2. `profile_codeql_query` or `profile_codeql_query_from_logs` \u2014 analyze performance\n3. `run_query_and_summarize_false_positives` prompt \u2014 assess precision\n4. `sarif_rank_false_positives` / `sarif_rank_true_positives` prompts \u2014 rank results\n\n### 4. Iterative Development with LSP\n\nUse the `ql_lsp_iterative_development` prompt:\n\n1. `codeql_lsp_completion` \u2014 get code completions while writing QL\n2. `codeql_lsp_definition` \u2014 navigate to symbol definitions\n3. `codeql_lsp_references` \u2014 find all references to a symbol\n4. `codeql_lsp_diagnostics` \u2014 real-time syntax and semantic validation\n\n## Tool Categories\n\nThe server provides default tools across these categories (see `codeql://server/tools` for the full reference):\n\n- **CodeQL CLI tools** \u2014 Database creation, query compilation, execution, result decoding, pack management\n- **LSP tools** \u2014 Code completion, go-to-definition, find references, diagnostics\n- **Query development tools** \u2014 Scaffolding, validation, profiling, quick evaluation, database registration\n\n## Prompt Categories\n\nThe server provides **11 prompts** (see `codeql://server/prompts` for the full reference):\n\n- **Test-driven development** \u2014 `test_driven_development`, `ql_tdd_basic`, `ql_tdd_advanced`\n- **Code understanding** \u2014 `tools_query_workflow`, `explain_codeql_query`\n- **Iterative development** \u2014 `ql_lsp_iterative_development`\n- **Documentation and quality** \u2014 `document_codeql_query`, `run_query_and_summarize_false_positives`, `sarif_rank_false_positives`, `sarif_rank_true_positives`\n- **Workshop creation** \u2014 `workshop_creation_workflow`\n\n## Key Concepts\n\n- **CodeQL database**: A relational representation of source code created by `codeql_database_create`. All queries execute against a database.\n- **QL pack**: A directory containing `codeql-pack.yml` with query or library code. Use `codeql_pack_install` to resolve dependencies.\n- **`.qlref` file**: A test reference that points from a test directory to the query being tested.\n- **`.expected` file**: The expected output of a query test. Use `codeql_test_accept` to update it when results are correct.\n- **BQRS**: Binary Query Result Sets \u2014 the native output format of `codeql_query_run`. Decode with `codeql_bqrs_decode` or interpret with `codeql_bqrs_interpret`.\n- **SARIF**: Static Analysis Results Interchange Format \u2014 the standard output format for `codeql_database_analyze`.\n\n## Supported Languages\n\nThe server supports CodeQL queries for: `actions`, `cpp`, `csharp`, `go`, `java`, `javascript`, `python`, `ruby`, `swift`.\n';
63478
+
63479
+ // src/resources/server-prompts.md
63480
+ var server_prompts_default = "# MCP Server Prompts\n\nThis resource provides a complete reference of the prompts exposed by the CodeQL Development MCP Server. Prompts are reusable workflow templates that guide the LLM through common CodeQL development tasks. Invoke a prompt via the MCP `prompts/get` protocol.\n\n## Prompt Reference\n\n| Prompt | Description |\n| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------- |\n| `document_codeql_query` | Create or update standardized markdown documentation for a CodeQL query |\n| `explain_codeql_query` | Generate a detailed explanation of a CodeQL query with Mermaid evaluation diagrams |\n| `ql_lsp_iterative_development` | Iterative CodeQL query development using LSP tools for completion, navigation, and validation |\n| `ql_tdd_advanced` | Advanced test-driven CodeQL development with AST visualization, control flow, and call graph analysis |\n| `ql_tdd_basic` | Test-driven CodeQL query development checklist \u2014 write tests first, implement query, iterate until tests pass |\n| `run_query_and_summarize_false_positives` | Run a CodeQL query and summarize its false positives by root cause |\n| `sarif_rank_false_positives` | Analyze SARIF results to identify and rank likely false positives |\n| `sarif_rank_true_positives` | Analyze SARIF results to identify and rank likely true positives |\n| `test_driven_development` | End-to-end test-driven development workflow for CodeQL queries using MCP tools |\n| `tools_query_workflow` | Guide for using PrintAST, PrintCFG, CallGraphFrom, and CallGraphTo tool queries to understand code structure |\n| `workshop_creation_workflow` | Guide for creating multi-exercise CodeQL query development workshops from production-grade queries |\n\n## Prompt Categories\n\n### Test-Driven Development\n\n- **`test_driven_development`** \u2014 The primary TDD prompt. Requires a `language` parameter and optionally accepts `queryName`. Loads the `ql-tdd-basic.prompt.md` template and walks through the complete TDD cycle: scaffold \u2192 write tests \u2192 implement \u2192 compile \u2192 test \u2192 iterate.\n- **`ql_tdd_basic`** \u2014 A standalone TDD checklist. All parameters are optional. Covers the core loop: write test cases, implement the query, run tests, iterate.\n- **`ql_tdd_advanced`** \u2014 Extends basic TDD with AST visualization (`PrintAST`), control flow graph analysis (`PrintCFG`), and call graph exploration (`CallGraphFrom`, `CallGraphTo`). Optionally accepts a `database` path for immediate analysis.\n\n### Code Understanding\n\n- **`tools_query_workflow`** \u2014 Orchestrates the four built-in tool queries (PrintAST, PrintCFG, CallGraphFrom, CallGraphTo) to explore how source code is represented in a CodeQL database. Requires `language` and `database` parameters.\n- **`explain_codeql_query`** \u2014 Produces a verbal explanation of a query's logic and generates Mermaid diagrams showing the evaluation flow. Requires `queryPath` and `language`.\n\n### Iterative Development\n\n- **`ql_lsp_iterative_development`** \u2014 Combines LSP-based code completions (`codeql_lsp_completion`), go-to-definition (`codeql_lsp_definition`), find-references (`codeql_lsp_references`), and diagnostics (`codeql_lsp_diagnostics`) for an interactive development loop.\n\n### Documentation and Quality\n\n- **`document_codeql_query`** \u2014 Generates standardized markdown documentation as a sibling `.md` file to a query. Requires `queryPath` and `language`.\n- **`run_query_and_summarize_false_positives`** \u2014 Runs a CodeQL query on a database and groups results into false-positive categories by root cause.\n- **`sarif_rank_false_positives`** / **`sarif_rank_true_positives`** \u2014 Analyze SARIF output to assess query precision by ranking results as likely true or false positives.\n\n### Workshop Creation\n\n- **`workshop_creation_workflow`** \u2014 Guides the creation of multi-exercise workshops that teach CodeQL query development. Requires `queryPath` and `language`, optionally accepts `workshopName` and `numStages`.\n\n## Related Resources\n\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 theory and workflow overview\n";
63481
+
63482
+ // src/resources/server-queries.md
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';
63484
+
63485
+ // src/resources/server-tools.md
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';
63487
+
62765
63488
  // src/lib/resources.ts
62766
- import { readFileSync as readFileSync10 } from "fs";
62767
- import { join as join15, dirname as dirname8 } from "path";
62768
- import { fileURLToPath as fileURLToPath3 } from "url";
62769
- var __filename2 = fileURLToPath3(import.meta.url);
62770
- var __dirname2 = dirname8(__filename2);
62771
- function getGettingStartedGuide() {
62772
- try {
62773
- return readFileSync10(join15(__dirname2, "../resources/getting-started.md"), "utf-8");
62774
- } catch {
62775
- return "Getting started guide not available";
62776
- }
63489
+ function getLearningQueryBasics() {
63490
+ return learning_query_basics_default;
62777
63491
  }
62778
- function getQueryBasicsGuide() {
62779
- try {
62780
- return readFileSync10(join15(__dirname2, "../resources/query-basics.md"), "utf-8");
62781
- } catch {
62782
- return "Query basics guide not available";
62783
- }
63492
+ function getPerformancePatterns() {
63493
+ return performance_patterns_default;
62784
63494
  }
62785
63495
  function getSecurityTemplates() {
62786
- try {
62787
- return readFileSync10(join15(__dirname2, "../resources/security-templates.md"), "utf-8");
62788
- } catch {
62789
- return "Security templates not available";
62790
- }
63496
+ return security_templates_default;
62791
63497
  }
62792
- function getPerformancePatterns() {
62793
- try {
62794
- return readFileSync10(join15(__dirname2, "../resources/performance-patterns.md"), "utf-8");
62795
- } catch {
62796
- return "Performance patterns not available";
62797
- }
63498
+ function getServerOverview() {
63499
+ return server_overview_default;
63500
+ }
63501
+ function getServerPrompts() {
63502
+ return server_prompts_default;
63503
+ }
63504
+ function getServerQueries() {
63505
+ return server_queries_default;
63506
+ }
63507
+ function getServerTools() {
63508
+ return server_tools_default;
63509
+ }
63510
+ function getTestDrivenDevelopment() {
63511
+ return ql_test_driven_development_default;
63512
+ }
63513
+ function getQueryUnitTesting() {
63514
+ return codeql_query_unit_testing_default;
63515
+ }
63516
+ function getDataflowMigration() {
63517
+ return dataflow_migration_v1_to_v2_default;
62798
63518
  }
62799
63519
 
62800
63520
  // src/tools/codeql-resources.ts
62801
63521
  function registerCodeQLResources(server) {
62802
63522
  server.resource(
62803
- "CodeQL Getting Started",
62804
- "codeql://learning/getting-started",
63523
+ "CodeQL Query Basics",
63524
+ "codeql://learning/query-basics",
62805
63525
  {
62806
- description: "Comprehensive introduction to CodeQL for beginners",
63526
+ description: "QL query writing reference: syntax, metadata, from/where/select, common patterns, testing conventions",
62807
63527
  mimeType: "text/markdown"
62808
63528
  },
62809
63529
  async () => {
62810
63530
  return {
62811
63531
  contents: [
62812
63532
  {
62813
- uri: "codeql://learning/getting-started",
63533
+ uri: "codeql://learning/query-basics",
62814
63534
  mimeType: "text/markdown",
62815
- text: getGettingStartedGuide()
63535
+ text: getLearningQueryBasics()
62816
63536
  }
62817
63537
  ]
62818
63538
  };
62819
63539
  }
62820
63540
  );
62821
63541
  server.resource(
62822
- "CodeQL Query Basics",
62823
- "codeql://learning/query-basics",
63542
+ "CodeQL Test-Driven Development",
63543
+ "codeql://learning/test-driven-development",
62824
63544
  {
62825
- description: "Learn the fundamentals of writing CodeQL queries",
63545
+ description: "TDD theory and workflow for developing CodeQL queries with MCP tools",
62826
63546
  mimeType: "text/markdown"
62827
63547
  },
62828
63548
  async () => {
62829
63549
  return {
62830
63550
  contents: [
62831
63551
  {
62832
- uri: "codeql://learning/query-basics",
63552
+ uri: "codeql://learning/test-driven-development",
62833
63553
  mimeType: "text/markdown",
62834
- text: getQueryBasicsGuide()
63554
+ text: getTestDrivenDevelopment()
63555
+ }
63556
+ ]
63557
+ };
63558
+ }
63559
+ );
63560
+ server.resource(
63561
+ "CodeQL Performance Patterns",
63562
+ "codeql://patterns/performance",
63563
+ {
63564
+ description: "Performance profiling and optimization for CodeQL queries",
63565
+ mimeType: "text/markdown"
63566
+ },
63567
+ async () => {
63568
+ return {
63569
+ contents: [
63570
+ {
63571
+ uri: "codeql://patterns/performance",
63572
+ mimeType: "text/markdown",
63573
+ text: getPerformancePatterns()
63574
+ }
63575
+ ]
63576
+ };
63577
+ }
63578
+ );
63579
+ server.resource(
63580
+ "CodeQL Server Overview",
63581
+ "codeql://server/overview",
63582
+ {
63583
+ description: "MCP server orientation guide: available tools, prompts, resources, and workflows",
63584
+ mimeType: "text/markdown"
63585
+ },
63586
+ async () => {
63587
+ return {
63588
+ contents: [
63589
+ {
63590
+ uri: "codeql://server/overview",
63591
+ mimeType: "text/markdown",
63592
+ text: getServerOverview()
63593
+ }
63594
+ ]
63595
+ };
63596
+ }
63597
+ );
63598
+ server.resource(
63599
+ "CodeQL Server Prompts",
63600
+ "codeql://server/prompts",
63601
+ {
63602
+ description: "Complete reference of MCP prompts for CodeQL development workflows",
63603
+ mimeType: "text/markdown"
63604
+ },
63605
+ async () => {
63606
+ return {
63607
+ contents: [
63608
+ {
63609
+ uri: "codeql://server/prompts",
63610
+ mimeType: "text/markdown",
63611
+ text: getServerPrompts()
63612
+ }
63613
+ ]
63614
+ };
63615
+ }
63616
+ );
63617
+ server.resource(
63618
+ "CodeQL Server Queries",
63619
+ "codeql://server/queries",
63620
+ {
63621
+ description: "Overview of bundled tools queries: PrintAST, PrintCFG, CallGraphFrom, CallGraphTo",
63622
+ mimeType: "text/markdown"
63623
+ },
63624
+ async () => {
63625
+ return {
63626
+ contents: [
63627
+ {
63628
+ uri: "codeql://server/queries",
63629
+ mimeType: "text/markdown",
63630
+ text: getServerQueries()
63631
+ }
63632
+ ]
63633
+ };
63634
+ }
63635
+ );
63636
+ server.resource(
63637
+ "CodeQL Server Tools",
63638
+ "codeql://server/tools",
63639
+ {
63640
+ description: "Complete reference of default MCP tools for CodeQL development",
63641
+ mimeType: "text/markdown"
63642
+ },
63643
+ async () => {
63644
+ return {
63645
+ contents: [
63646
+ {
63647
+ uri: "codeql://server/tools",
63648
+ mimeType: "text/markdown",
63649
+ text: getServerTools()
62835
63650
  }
62836
63651
  ]
62837
63652
  };
@@ -62841,7 +63656,7 @@ function registerCodeQLResources(server) {
62841
63656
  "CodeQL Security Templates",
62842
63657
  "codeql://templates/security",
62843
63658
  {
62844
- description: "Ready-to-use security query templates",
63659
+ description: "Security query templates for multiple languages and vulnerability classes",
62845
63660
  mimeType: "text/markdown"
62846
63661
  },
62847
63662
  async () => {
@@ -62857,19 +63672,38 @@ function registerCodeQLResources(server) {
62857
63672
  }
62858
63673
  );
62859
63674
  server.resource(
62860
- "CodeQL Performance Patterns",
62861
- "codeql://patterns/performance",
63675
+ "CodeQL Query Unit Testing",
63676
+ "codeql://guides/query-unit-testing",
62862
63677
  {
62863
- description: "Best practices for writing efficient CodeQL queries",
63678
+ description: "Guide for creating and running CodeQL query unit tests across all supported languages",
62864
63679
  mimeType: "text/markdown"
62865
63680
  },
62866
63681
  async () => {
62867
63682
  return {
62868
63683
  contents: [
62869
63684
  {
62870
- uri: "codeql://patterns/performance",
63685
+ uri: "codeql://guides/query-unit-testing",
62871
63686
  mimeType: "text/markdown",
62872
- text: getPerformancePatterns()
63687
+ text: getQueryUnitTesting()
63688
+ }
63689
+ ]
63690
+ };
63691
+ }
63692
+ );
63693
+ server.resource(
63694
+ "CodeQL Dataflow Migration v1 to v2",
63695
+ "codeql://guides/dataflow-migration-v1-to-v2",
63696
+ {
63697
+ description: "Guide for migrating CodeQL queries from legacy v1 dataflow API to modern v2 module-based API",
63698
+ mimeType: "text/markdown"
63699
+ },
63700
+ async () => {
63701
+ return {
63702
+ contents: [
63703
+ {
63704
+ uri: "codeql://guides/dataflow-migration-v1-to-v2",
63705
+ mimeType: "text/markdown",
63706
+ text: getDataflowMigration()
62873
63707
  }
62874
63708
  ]
62875
63709
  };
@@ -62880,13 +63714,13 @@ function registerCodeQLResources(server) {
62880
63714
  // src/tools/lsp/lsp-diagnostics.ts
62881
63715
  init_logger();
62882
63716
  init_temp_dir();
62883
- import { join as join16 } from "path";
63717
+ import { join as join17 } from "path";
62884
63718
  import { pathToFileURL as pathToFileURL3 } from "url";
62885
63719
 
62886
63720
  // src/tools/lsp/lsp-server-helper.ts
62887
63721
  init_server_manager();
62888
63722
  init_logger();
62889
- import { isAbsolute as isAbsolute5, resolve as resolve10 } from "path";
63723
+ import { isAbsolute as isAbsolute5, resolve as resolve11 } from "path";
62890
63724
  import { pathToFileURL as pathToFileURL2 } from "url";
62891
63725
  async function getInitializedLanguageServer(opts = {}) {
62892
63726
  const { packageRootDir: pkgRoot, getUserWorkspaceDir: getUserWorkspaceDir2 } = await Promise.resolve().then(() => (init_package_paths(), package_paths_exports));
@@ -62894,7 +63728,7 @@ async function getInitializedLanguageServer(opts = {}) {
62894
63728
  const config2 = {
62895
63729
  checkErrors: "ON_CHANGE",
62896
63730
  loglevel: options.loglevel ?? "WARN",
62897
- searchPath: options.searchPath ?? resolve10(pkgRoot, "ql"),
63731
+ searchPath: options.searchPath ?? resolve11(pkgRoot, "ql"),
62898
63732
  synchronous: options.synchronous,
62899
63733
  verbosity: options.verbosity
62900
63734
  };
@@ -62902,10 +63736,10 @@ async function getInitializedLanguageServer(opts = {}) {
62902
63736
  const server = await manager.getLanguageServer(config2);
62903
63737
  let effectiveUri = opts.workspaceUri;
62904
63738
  if (effectiveUri && !effectiveUri.startsWith("file://")) {
62905
- const absWorkspace = isAbsolute5(effectiveUri) ? effectiveUri : resolve10(getUserWorkspaceDir2(), effectiveUri);
63739
+ const absWorkspace = isAbsolute5(effectiveUri) ? effectiveUri : resolve11(getUserWorkspaceDir2(), effectiveUri);
62906
63740
  effectiveUri = pathToFileURL2(absWorkspace).href;
62907
63741
  }
62908
- effectiveUri = effectiveUri ?? pathToFileURL2(resolve10(pkgRoot, "ql")).href;
63742
+ effectiveUri = effectiveUri ?? pathToFileURL2(resolve11(pkgRoot, "ql")).href;
62909
63743
  await server.initialize(effectiveUri);
62910
63744
  logger.debug(`Language server initialized with workspace: ${effectiveUri}`);
62911
63745
  return server;
@@ -62978,7 +63812,7 @@ async function lspDiagnostics({
62978
63812
  serverOptions,
62979
63813
  workspaceUri
62980
63814
  });
62981
- 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;
62982
63816
  const diagnostics = await languageServer.evaluateQL(qlCode, evalUri);
62983
63817
  const summary = {
62984
63818
  errorCount: diagnostics.filter((d) => d.severity === 1).length,
@@ -63067,7 +63901,7 @@ function registerLspDiagnosticsTool(server) {
63067
63901
  init_logger();
63068
63902
  init_package_paths();
63069
63903
  import { readFile as readFile3 } from "fs/promises";
63070
- import { isAbsolute as isAbsolute6, resolve as resolve11 } from "path";
63904
+ import { isAbsolute as isAbsolute6, resolve as resolve12 } from "path";
63071
63905
  import { pathToFileURL as pathToFileURL4 } from "url";
63072
63906
  async function getInitializedServer(params) {
63073
63907
  return getInitializedLanguageServer({
@@ -63076,7 +63910,7 @@ async function getInitializedServer(params) {
63076
63910
  });
63077
63911
  }
63078
63912
  function prepareDocumentPosition(params) {
63079
- const absPath = isAbsolute6(params.filePath) ? params.filePath : resolve11(getUserWorkspaceDir(), params.filePath);
63913
+ const absPath = isAbsolute6(params.filePath) ? params.filePath : resolve12(getUserWorkspaceDir(), params.filePath);
63080
63914
  const docUri = pathToFileURL4(absPath).href;
63081
63915
  return { absPath, docUri };
63082
63916
  }
@@ -63251,83 +64085,107 @@ function registerLSPTools(server) {
63251
64085
  );
63252
64086
  }
63253
64087
 
63254
- // src/resources/language-resources.ts
63255
- import { readFileSync as readFileSync11, existsSync as existsSync12 } from "fs";
63256
- import { join as join17 } from "path";
64088
+ // src/resources/languages/actions_ast.md
64089
+ var actions_ast_default = '# CodeQL AST nodes for `actions` language\n\n## CodeQL\'s core AST classes for `actions` language\n\nBased on analysis of CodeQL\'s Actions AST test results from local test files, here are the core AST classes for GitHub Actions analysis:\n\n### Top-Level Action and Workflow Structures\n\n**Action Files (action.yml):**\n\n- `CompositeActionImpl` - Root composite action declaration (e.g., `name: "Hello World"`)\n- Action metadata including name, description, and runtime configuration\n\n**Workflow Files (.github/workflows/\\*.yml):**\n\n- `WorkflowImpl` - Root workflow declaration (e.g., `name: Reusable workflow example`)\n- Complete workflow structure with events, jobs, and steps\n\n### Event Handling\n\n**Event Triggers:**\n\n- `OnImpl` - Event trigger definitions (e.g., `workflow_call:`)\n- `EventImpl` - Specific event types (e.g., `workflow_call`)\n- Event configuration with inputs, outputs, and secrets\n\n### Input and Output Management\n\n**Input Structures:**\n\n- `InputsImpl` - Input containers for actions and workflows\n- `InputImpl` - Individual input definitions (e.g., `who-to-greet`, `config-path`)\n- Input properties: description, required, type, default values\n\n**Output Structures:**\n\n- `OutputsImpl` - Output containers for workflows and jobs\n- Output value expressions and job output references\n\n### Job Management\n\n**Job Structure:**\n\n- `JobImpl` - Job definitions (e.g., `Job: job1`)\n- Job configuration including runner, outputs, and steps\n- Job-level environment and dependency management\n\n**Job Execution Environment:**\n\n- Runner specifications (e.g., `ubuntu-latest`)\n- Job outputs and step output references\n\n### Step Execution\n\n**Step Types:**\n\n- `StepImpl` - Generic step containers\n- `Run Step` - Steps with shell commands and scripts\n- `Uses Step` - Steps using external actions\n\n**Step Components:**\n\n- Step identification and naming\n- Shell command execution\n- External action usage (e.g., `tj-actions/changed-files@v40`)\n\n### Environment and Variable Management\n\n**Environment Variables:**\n\n- `EnvImpl` - Environment variable definitions\n- Environment variable scoping (step-level, job-level)\n- Variable interpolation and expression evaluation\n\n### Expression System\n\n**Expression Handling:**\n\n- `ExpressionImpl` - GitHub Actions expressions (e.g., `inputs.who-to-greet`, `jobs.job1.outputs.job-output1`)\n- Expression contexts: inputs, steps, jobs, github, env\n- Complex expression evaluation and context access\n\n**Expression Contexts:**\n\n- Input references: `inputs.config-path`, `inputs.who-to-greet`\n- Step output references: `steps.step1.outputs.step-output`, `steps.step2.outputs.all_changed_files`\n- Job output references: `jobs.job1.outputs.job-output1`\n\n### Value and Data Types\n\n**Scalar Values:**\n\n- `ScalarValueImpl` - String literals, booleans, and scalar data\n- Configuration values (e.g., `"Hello World"`, `"composite"`, `true`)\n- Command strings and action references\n\n**Value Types:**\n\n- String values for names, descriptions, commands\n- Boolean values for required flags and conditions\n- Action references and version specifications\n\n### Action Runtime Configuration\n\n**Composite Actions:**\n\n- `using: "composite"` runtime specification\n- Step sequence execution within composite actions\n- Input parameter passing and environment setup\n\n**Action Metadata:**\n\n- Action names and descriptions\n- Input/output specifications\n- Runtime environment configuration\n\n### Shell and Command Execution\n\n**Command Execution:**\n\n- Shell command strings (e.g., `echo "Hello $INPUT_WHO_TO_GREET."`)\n- Shell specification (e.g., `bash`)\n- Multi-line command support\n\n**Environment Integration:**\n\n- Environment variable usage in commands\n- Variable substitution and expansion\n- Input-to-environment variable mapping\n\n### External Action Integration\n\n**Action Usage:**\n\n- External action references (e.g., `tj-actions/changed-files@v40`)\n- Version pinning and action marketplace integration\n- Action parameter passing and configuration\n\n### Workflow Reusability\n\n**Reusable Workflows:**\n\n- Workflow call triggers and parameters\n- Input/output parameter definitions\n- Secret management and passing\n\n**Workflow Composition:**\n\n- Job dependencies and sequencing\n- Output propagation between jobs\n- Workflow-level input and output management\n\n### Security and Secrets\n\n**Secret Management:**\n\n- Secret declarations and requirements\n- Secret passing in reusable workflows\n- Secure environment variable handling\n\n### Example AST Hierarchy\n\nBased on CodeQL\'s GitHub Actions analysis capabilities:\n\n```\nWorkflowImpl (root workflow)\n\u251C\u2500\u2500 OnImpl (event triggers)\n\u2502 \u2514\u2500\u2500 EventImpl (specific events like workflow_call)\n\u251C\u2500\u2500 InputsImpl (workflow inputs)\n\u2502 \u2514\u2500\u2500 InputImpl (individual inputs)\n\u251C\u2500\u2500 OutputsImpl (workflow outputs)\n\u251C\u2500\u2500 JobImpl (job definitions)\n\u2502 \u251C\u2500\u2500 OutputsImpl (job outputs)\n\u2502 \u2514\u2500\u2500 StepImpl (job steps)\n\u2502 \u251C\u2500\u2500 EnvImpl (step environment)\n\u2502 \u2514\u2500\u2500 ScalarValueImpl (step commands/actions)\n\u2514\u2500\u2500 ScalarValueImpl (scalar values throughout)\n\nCompositeActionImpl (root action)\n\u251C\u2500\u2500 InputsImpl (action inputs)\n\u251C\u2500\u2500 RunsImpl (execution configuration)\n\u2514\u2500\u2500 StepImpl (action steps)\n \u251C\u2500\u2500 EnvImpl (step environment)\n \u2514\u2500\u2500 ScalarValueImpl (commands and values)\n\nExpressionImpl (expressions like ${{ inputs.name }})\n\u2514\u2500\u2500 Context access (inputs, steps, jobs, github, env)\n```\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `actions` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="actions"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n';
64090
+
64091
+ // src/resources/languages/cpp_ast.md
64092
+ var cpp_ast_default = '# CodeQL AST nodes for `cpp` language\n\n## CodeQL\'s core AST classes for `cpp` language\n\nBased on comprehensive analysis of CodeQL\'s C++ AST test results from both local and GitHub test files, here are the core AST classes for C/C++ analysis:\n\n### Function and Method Declarations\n\n**Function Types:**\n\n- `TopLevelFunction` - Global functions (e.g., `void fun3(someClass*)`, `int main()`)\n- `MemberFunction` - Class member functions (e.g., `void someClass::f()`, `int someClass::g(int, int)`)\n- `VirtualFunction` - Virtual functions with dynamic dispatch (e.g., `virtual void Base::v()`)\n- `ConstMemberFunction` - Const member functions (e.g., `char const* std::type_info::name() const`)\n- `FormattingFunction` - Functions with format string checking (e.g., `int printf(char const*)`)\n- `TemplateFunction` - Template function declarations\n\n**Constructors and Destructors:**\n\n- `Constructor` - Class constructors (e.g., `void C::C(int)`)\n- `CopyConstructor` - Copy constructors (e.g., `void C::C(C const&)`)\n- `CopyAssignmentOperator` - Copy assignment operators (e.g., `C& C::operator=(C const&)`)\n- `MoveAssignmentOperator` - Move assignment operators (e.g., `C& C::operator=(C&&)`)\n- `Destructor` - Destructor declarations\n- `DestructorCall` - Explicit and implicit destructor calls (e.g., `call to ~C`)\n\n**Operator Functions:**\n\n- `Operator` - Operator overloads (e.g., `void operator delete(void*)`, `void* operator new(unsigned long)`)\n\n### Statements\n\n**Control Flow Statements:**\n\n- `BlockStmt` - Block statements containing multiple statements (e.g., `{ ... }`)\n- `IfStmt` - Conditional statements with condition and branches\n- `ForStmt` - For loops with initialization, condition, and increment\n- `ReturnStmt` - Return statements with optional expressions\n- `GotoStmt` - Goto statements for jumping to labels\n- `LabelStmt` - Label statements for goto targets\n\n**Declaration Statements:**\n\n- `DeclStmt` - Declaration statements containing variable and type declarations\n- `VariableDeclarationEntry` - Individual variable declarations (e.g., `definition of i`)\n- `TypeDeclarationEntry` - Type declarations (e.g., `definition of u`)\n\n**Expression Statements:**\n\n- `ExprStmt` - Statement wrappers for expressions\n\n**Variable Length Array Support:**\n\n- `VlaDimensionStmt` - VLA dimension size statements\n- `VlaDeclStmt` - VLA declaration statements\n\n### Expressions\n\n**Primary Expressions:**\n\n- `Literal` - Literal values (e.g., `1`, `2`, `42`, `"hello"`)\n- `StringLiteral` - String literals (e.g., `"int"`, `"string"`)\n- `VariableAccess` - Variable references (e.g., `sc`, `i`, `args`)\n- `ThisExpr` - The `this` keyword in member functions\n\n**Function Calls:**\n\n- `FunctionCall` - Function calls (e.g., `call to f`, `call to printf`)\n- `FormattingFunctionCall` - Calls to format string functions with type checking\n- `MethodCall` - Method calls on objects\n- `ConstructorCall` - Constructor calls (e.g., `call to C`)\n\n**Operators and Assignments:**\n\n- `AssignExpr` - Assignment expressions (e.g., `... = ...`)\n- `AddExpr` - Addition expressions (e.g., `... + ...`)\n- `MulExpr` - Multiplication expressions (e.g., `... * ...`)\n- `SubExpr` - Subtraction expressions\n\n**Object Creation and Destruction:**\n\n- `ClassInstanceExpr` - Object instantiation expressions\n- `NewExpr` - Dynamic memory allocation with `new`\n- `DeleteExpr` - Dynamic memory deallocation with `delete`\n- `VacuousDestructorCall` - Vacuous destructor calls for trivial types\n\n**Array and Pointer Operations:**\n\n- `ArrayExpr` - Array access expressions (e.g., `access to array`)\n- `PointerDereferenceExpr` - Pointer dereference (e.g., `* ...`)\n- `AddressOfExpr` - Address-of operator (e.g., `& ...`)\n- `ArrayToPointerConversion` - Implicit array to pointer conversions\n\n**Field Access:**\n\n- `ValueFieldAccess` - Value-based field access (e.g., `obj.field`)\n- `PointerFieldAccess` - Pointer-based field access (e.g., `ptr->field`)\n\n**Type Casting:**\n\n- `CStyleCast` - C-style casts (e.g., `(int)...`, `(char)...`)\n- `StaticCast` - Static casts for safe conversions\n- `DynamicCast` - Dynamic casts for runtime type checking (e.g., `dynamic_cast<Derived *>...`)\n- `ConstCast` - Const casts (e.g., `const_cast<T *>...`)\n- `ReinterpretCast` - Reinterpret casts (e.g., `reinterpret_cast<S *>...`)\n\n**Reference Operations:**\n\n- `ReferenceToExpr` - Reference creation (e.g., `(reference to)`)\n- `ReferenceDereferenceExpr` - Reference dereference (e.g., `(reference dereference)`)\n\n**Type Information:**\n\n- `TypeidOperator` - Runtime type information (e.g., `typeid ...`)\n\n**Modern C++ Features:**\n\n- `ParenthesizedExpr` - Parenthesized expressions for grouping\n\n### Type System\n\n**Basic Types:**\n\n- `IntType` - Integer types (e.g., `int`)\n- `VoidType` - Void type\n- `FloatType` - Floating-point types\n- `LongType` - Long integer types (e.g., `unsigned long`)\n- `PlainCharType` - Plain char type\n- `CharType` - Character types\n\n**Pointer Types:**\n\n- `PointerType` - Pointer types (e.g., `someClass *`, `Base *`)\n- `IntPointerType` - Integer pointer types (e.g., `int *`)\n- `CharPointerType` - Character pointer types (e.g., `char *`)\n- `VoidPointerType` - Void pointer types (e.g., `void *`)\n- `FunctionPointerType` - Function pointer types\n\n**Reference Types:**\n\n- `LValueReferenceType` - L-value references (e.g., `const someClass &`)\n- `RValueReferenceType` - R-value references (e.g., `someClass &&`)\n\n**Array Types:**\n\n- `ArrayType` - Array types (e.g., `char[]`, `char[4]`)\n\n**Class and Struct Types:**\n\n- `Class` - Class types (e.g., `Base`, `Derived`)\n- `Struct` - Struct types\n- `NestedClass` - Nested class types\n- `LocalUnion` - Local union types\n\n**Template Types:**\n\n- `TypeTemplateParameter` - Template type parameters (e.g., `T`)\n\n**Advanced Types:**\n\n- `SpecifiedType` - Type qualifiers (e.g., `const type_info`)\n- `CTypedefType` - C typedef types (e.g., `va_list`, `MYINT`)\n\n### C11 Generic Support\n\n**Generic Expressions:**\n\n- `C11GenericExpr` - C11 \\_Generic expressions for type-based selection\n- `ReuseExpr` - Expression reuse in generic contexts\n- `TypeName` - Type names in generic associations\n\n### Parameters and Initializers\n\n**Parameter Handling:**\n\n- `Parameter` - Function parameters with types (e.g., `i`, `j`, `sc`)\n- Support for unnamed parameters and default arguments\n\n**Initialization:**\n\n- `Initializer` - Variable initializers (e.g., `initializer for i`)\n- Constructor initialization lists\n- Field initialization\n\n### Built-in Functions\n\n**Variable Arguments:**\n\n- `BuiltInVarArgsStart` - `__builtin_va_start` for variadic functions\n- `BuiltInVarArgsEnd` - `__builtin_va_end` for cleanup\n\n### Type Conversions\n\n**Implicit Conversions:**\n\n- `IntegralConversion` - Integer type conversions\n- `PointerConversion` - Pointer type conversions\n- `BaseClassConversion` - Base class conversions for inheritance\n- `GlvalueConversion` - Glvalue conversions\n\n**Explicit Conversions:**\n\n- Support for all cast types with conversion tracking\n- Value category preservation through conversions\n\n### Value Categories and Properties\n\n**Value Categories:**\n\n- `prvalue` - Pure r-values (temporary values)\n- `lvalue` - L-values (addressable values)\n- `prvalue(load)` - Loaded values from memory\n\n**Type Properties:**\n\n- Type information preservation through all expressions\n- Conversion tracking for type safety analysis\n\n### Example AST Hierarchy\n\nBased on CodeQL\'s comprehensive C++ analysis capabilities:\n\n```\nTopLevelFunction (global functions)\n\u251C\u2500\u2500 Parameter (function parameters)\n\u251C\u2500\u2500 BlockStmt (function body)\n\u2502 \u251C\u2500\u2500 DeclStmt (declarations)\n\u2502 \u2502 \u2514\u2500\u2500 VariableDeclarationEntry (variable definitions)\n\u2502 \u251C\u2500\u2500 ExprStmt (expression statements)\n\u2502 \u2502 \u251C\u2500\u2500 FunctionCall (function calls)\n\u2502 \u2502 \u251C\u2500\u2500 AssignExpr (assignments)\n\u2502 \u2502 \u2514\u2500\u2500 VariableAccess (variable references)\n\u2502 \u2514\u2500\u2500 ReturnStmt (return statements)\n\u2514\u2500\u2500 Type information (IntType, PointerType, etc.)\n\nClass (class declarations)\n\u251C\u2500\u2500 Constructor/Destructor (special members)\n\u251C\u2500\u2500 MemberFunction (methods)\n\u251C\u2500\u2500 CopyAssignmentOperator (copy operations)\n\u2514\u2500\u2500 MoveAssignmentOperator (move operations)\n\nExpression hierarchy with full type and conversion tracking\n\u251C\u2500\u2500 Primary expressions (literals, variables)\n\u251C\u2500\u2500 Operators (arithmetic, logical, comparison)\n\u251C\u2500\u2500 Casts (static, dynamic, const, reinterpret)\n\u251C\u2500\u2500 Object operations (new, delete, field access)\n\u2514\u2500\u2500 Type operations (sizeof, typeid, alignof)\n```\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `cpp` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="cpp"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `cpp` language:\n\n- [library-tests/destructors/PrintAST.expected](https://github.com/github/codeql/blob/main/cpp/ql/test/library-tests/destructors/PrintAST.expected)\n- [library-tests/c11_generic/PrintAST.expected](https://github.com/github/codeql/blob/main/cpp/ql/test/library-tests/c11_generic/PrintAST.expected)\n- [library-tests/ir/ir/PrintAST.expected](https://github.com/github/codeql/blob/main/cpp/ql/test/library-tests/ir/ir/PrintAST.expected)\n- [library-tests/ir/no-function-calls/PrintAST.expected](https://github.com/github/codeql/blob/main/cpp/ql/test/library-tests/ir/no-function-calls/PrintAST.expected)\n- [examples/expressions/PrintAST.expected](https://github.com/github/codeql/blob/main/cpp/ql/test/examples/expressions/PrintAST.expected)\n';
64093
+
64094
+ // src/resources/languages/cpp_security_query_guide.md
64095
+ var cpp_security_query_guide_default = "# C++ Security Query Guide\n\nLanguage-specific notes for writing C++ security queries in CodeQL. For the general taint-tracking template and workflow, see the `security_templates` resource.\n\n## Imports\n\n```ql\nimport cpp\nimport semmle.code.cpp.dataflow.new.DataFlow\nimport semmle.code.cpp.dataflow.new.TaintTracking\n```\n\nFor path-problem queries add `import MyFlow::PathGraph` after defining your flow module.\n\n## Sources and Sinks\n\n- **Sources**: Use the `RemoteFlowSource` class from `semmle.code.cpp.security.FlowSources`, or model custom sources as `DataFlow::Node` subclasses.\n- **Sinks**: Model as `DataFlow::Node` subclasses matching the dangerous API (e.g., buffer writes, system calls, SQL execution).\n- **Barriers**: Use `semmle.code.cpp.controlflow.Guards` to model guard conditions that sanitize tainted data.\n\n## Key Library Modules\n\n| Module | Purpose |\n| -------------------------------------------- | ------------------------------------- |\n| `semmle.code.cpp.dataflow.new.DataFlow` | Data flow nodes and global analysis |\n| `semmle.code.cpp.dataflow.new.TaintTracking` | Taint tracking analysis |\n| `semmle.code.cpp.controlflow.Guards` | Guard-condition analysis for barriers |\n| `semmle.code.cpp.security.BufferWrite` | Buffer-write sink modeling |\n| `semmle.code.cpp.security.FlowSources` | Remote and local flow sources |\n";
64096
+
64097
+ // src/resources/languages/csharp_ast.md
64098
+ var csharp_ast_default = '# CodeQL AST nodes for `csharp` language\n\n## CodeQL\'s core AST classes for `csharp` language\n\nBased on the C# PrintAst.expected test results, here are the core CodeQL AST classes for the C# language:\n\n### Declarations and Members\n\n- **`Class`** - Class declaration\n- **`NamespaceDeclaration`** - Namespace declaration\n- **`Method`** - Method declaration\n- **`Property`** - Property declaration\n- **`Field`** - Field declaration\n- **`Parameter`** - Method parameter\n- **`DelegateType`** - Delegate type declaration\n- **`InstanceConstructor`** - Instance constructor\n- **`StaticConstructor`** - Static constructor\n- **`Destructor`** - Destructor/finalizer\n\n### Type System\n\n- **`TypeMention`** - Reference to a type\n- **`TypeParameter`** - Generic type parameter\n- **`TypeAccess`** - Access to a type\n- **`TypeAccessPatternExpr`** - Type access in pattern expressions\n\n### Statements\n\n- **`BlockStmt`** - Block statement `{...}`\n- **`ExprStmt`** - Expression statement\n- **`LocalVariableDeclStmt`** - Local variable declaration statement\n- **`ReturnStmt`** - Return statement\n- **`IfStmt`** - If statement\n- **`TryStmt`** - Try statement\n- **`ThrowStmt`** - Throw statement\n- **`UsingBlockStmt`** - Using statement with block\n- **`FixedStmt`** - Fixed statement (for unsafe code)\n- **`LabelStmt`** - Label statement\n- **`EmptyStmt`** - Empty statement `;`\n\n### Expressions\n\n- **`LocalVariableDeclAndInitExpr`** - Local variable declaration and initialization\n- **`LocalVariableAccess`** - Access to local variable\n- **`ParameterAccess`** - Access to parameter\n- **`FieldAccess`** - Access to field\n- **`PropertyCall`** - Property access/call\n- **`MethodCall`** - Method call\n- **`MethodAccess`** - Method access\n- **`ObjectCreation`** - Object creation expression `new T()`\n- **`AnonymousObjectCreation`** - Anonymous object creation\n- **`ArrayCreation`** - Array creation expression\n- **`ArrayAccess`** - Array element access\n- **`AssignExpr`** - Assignment expression `=`\n- **`AssignAddExpr`** - Addition assignment `+=`\n- **`AssignSubExpr`** - Subtraction assignment `-=`\n- **`ThisAccess`** - `this` access\n- **`CastExpr`** - Type cast expression\n- **`IsExpr`** - Type check expression `is`\n- **`DefaultValueExpr`** - Default value expression `default(...)`\n\n### Arithmetic and Logical Expressions\n\n- **`AddExpr`** - Addition expression `+`\n- **`SubExpr`** - Subtraction expression `-`\n- **`DivExpr`** - Division expression `/`\n- **`BitwiseAndExpr`** - Bitwise AND expression `&`\n- **`LogicalOrExpr`** - Logical OR expression `||`\n- **`LTExpr`** - Less than expression `<`\n- **`GEExpr`** - Greater than or equal expression `>=`\n- **`PostIncrExpr`** - Post-increment expression `++`\n- **`OperatorCall`** - Operator call\n\n### Literals\n\n- **`IntLiteral`** - Integer literal\n- **`StringLiteralUtf16`** - String literal\n- **`BoolLiteral`** - Boolean literal (`true`/`false`)\n- **`DoubleLiteral`** - Double literal\n- **`CharLiteral`** - Character literal\n- **`NullLiteral`** - Null literal\n\n### Object and Collection Initialization\n\n- **`ObjectInitializer`** - Object initializer `{ ... }`\n- **`MemberInitializer`** - Member initializer in object initializer\n- **`CollectionInitializer`** - Collection initializer `{ ..., ... }`\n- **`ElementInitializer`** - Element initializer in collection\n- **`ArrayInitializer`** - Array initializer `{ ..., ... }`\n\n### Delegates and Events\n\n- **`DelegateCall`** - Delegate call\n- **`ImplicitDelegateCreation`** - Implicit delegate creation\n- **`ExplicitDelegateCreation`** - Explicit delegate creation\n- **`EventAccess`** - Event access\n- **`EventCall`** - Event call\n- **`AddEventExpr`** - Event subscription `+=`\n- **`RemoveEventExpr`** - Event unsubscription `-=`\n\n### Properties and Accessors\n\n- **`Getter`** - Property getter\n- **`Setter`** - Property setter\n\n### Special Members and Access\n\n- **`MemberConstantAccess`** - Access to member constant\n- **`LocalFunctionAccess`** - Access to local function\n- **`AddressOfExpr`** - Address-of expression `&` (unsafe code)\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `csharp` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="csharp"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `csharp` language:\n\n- [library-tests/arguments/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/arguments/PrintAst.expected)\n- [library-tests/assignments/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/assignments/PrintAst.expected)\n- [library-tests/attributes/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/attributes/PrintAst.expected)\n- [library-tests/comments/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/comments/PrintAst.expected)\n- [library-tests/constructors/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/constructors/PrintAst.expected)\n- [library-tests/conversion/operator/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/conversion/operator/PrintAst.expected)\n- [library-tests/csharp6/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp6/PrintAst.expected)\n- [library-tests/csharp7/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp7/PrintAst.expected)\n- [library-tests/csharp7.1/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp7.1/PrintAst.expected)\n- [library-tests/csharp7.2/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp7.2/PrintAst.expected)\n- [library-tests/csharp7.3/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected)\n- [library-tests/csharp8/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp8/PrintAst.expected)\n- [library-tests/csharp9/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp9/PrintAst.expected)\n- [library-tests/csharp11/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/csharp11/PrintAst.expected)\n- [library-tests/dataflow/implicittostring/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected)\n- [library-tests/dataflow/tuples/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected)\n- [library-tests/definitions/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/definitions/PrintAst.expected)\n- [library-tests/delegates/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/delegates/PrintAst.expected)\n- [library-tests/dynamic/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/dynamic/PrintAst.expected)\n- [library-tests/enums/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/enums/PrintAst.expected)\n- [library-tests/exceptions/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/exceptions/PrintAst.expected)\n- [library-tests/expressions/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/expressions/PrintAst.expected)\n- [library-tests/events/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/events/PrintAst.expected)\n- [library-tests/fields/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/fields/PrintAst.expected)\n- [library-tests/generics/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/generics/PrintAst.expected)\n- [library-tests/goto/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/goto/PrintAst.expected)\n- [library-tests/indexers/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/indexers/PrintAst.expected)\n- [library-tests/initializers/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/initializers/PrintAst.expected)\n- [library-tests/linq/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/linq/PrintAst.expected)\n- [library-tests/members/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/members/PrintAst.expected)\n- [library-tests/methods/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/methods/PrintAst.expected)\n- [library-tests/namespaces/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/namespaces/PrintAst.expected)\n- [library-tests/nestedtypes/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/nestedtypes/PrintAst.expected)\n- [library-tests/operators/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/operators/PrintAst.expected)\n- [library-tests/partial/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/partial/PrintAst.expected)\n- [library-tests/properties/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/properties/PrintAst.expected)\n- [library-tests/statements/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/statements/PrintAst.expected)\n- [library-tests/stringinterpolation/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/stringinterpolation/PrintAst.expected)\n- [library-tests/types/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/types/PrintAst.expected)\n- [library-tests/unsafe/PrintAst.expected](https://github.com/github/codeql/blob/main/csharp/ql/test/library-tests/unsafe/PrintAst.expected)\n';
64099
+
64100
+ // src/resources/languages/csharp_security_query_guide.md
64101
+ var csharp_security_query_guide_default = "# C# Security Query Guide\n\nLanguage-specific notes for writing C# security queries in CodeQL. For the general taint-tracking template and workflow, see the `security_templates` resource.\n\n## Imports\n\n```ql\nimport csharp\nimport semmle.code.csharp.dataflow.DataFlow\nimport semmle.code.csharp.dataflow.TaintTracking\n```\n\nFor path-problem queries add `import MyFlow::PathGraph` after defining your flow module.\n\n## Sources and Sinks\n\n- **Sources**: Use `RemoteFlowSource` from `semmle.code.csharp.security.dataflow.flowsources.Remote`, or model custom sources as `DataFlow::Node` subclasses.\n- **Sinks**: Use or extend existing sink libraries under `semmle.code.csharp.security.dataflow` (e.g., `SqlInjectionQuery`, `flowsinks.Html`, `UrlRedirectQuery`), or model custom sinks as `DataFlow::Node` subclasses.\n- **Sanitizers**: Use `semmle.code.csharp.security.Sanitizers` for common encoding and validation barriers.\n\n## Key Library Modules\n\n| Module | Purpose |\n| ------------------------------------------- | ---------------------------------------- |\n| `semmle.code.csharp.dataflow.DataFlow` | Data flow nodes and global analysis |\n| `semmle.code.csharp.dataflow.TaintTracking` | Taint tracking analysis |\n| `semmle.code.csharp.security.Sanitizers` | Common sanitizer predicates |\n| `semmle.code.csharp.security.dataflow.*` | Pre-built vulnerability-specific configs |\n| `semmle.code.csharp.frameworks.system.*` | .NET framework API models |\n";
64102
+
64103
+ // src/resources/languages/go_ast.md
64104
+ var go_ast_default = '# CodeQL AST Classes for Go Programs\n\n## Purpose\n\nWrite CodeQL queries over Go by navigating the Go AST classes. Model: Syntax \u2192 CodeQL class hierarchy; use predicates to access parts (condition, body, operands). Pattern: `get<Part>()`, `getA<Part>()`, `get<Left/Right>Operand>()`, `getAnArgument()`, `getCallee()`.\n\n## Core Namespaces\n\n- **Statements**: subclasses of `Stmt`\n- **Expressions**: subclasses of `Expr` (literals, unary, binary, calls, selectors, etc.)\n- **Declarations**: `FuncDecl`, `GenDecl` (+ `ImportSpec`, `TypeSpec`, `ValueSpec`)\n- **Types**: `TypeExpr` nodes (`ArrayTypeExpr`, `StructTypeExpr`, `FuncTypeExpr`, `InterfaceTypeExpr`, `MapTypeExpr`, `ChanTypeExpr` variants)\n- **Names/Selectors**: `SimpleName`, `SelectorExpr`; Name hierarchy: `PackageName`, `TypeName`, `ValueName`, `LabelName`\n\n## Statements (Stmt)\n\n### Basic Statements\n\n- **`EmptyStmt`** - Empty statement ";"\n- **`ExprStmt`** - Expression used as statement\n- **`BlockStmt`** - Block statement "{\u2026}"\n- **`DeclStmt`** - Declaration statement\n\n### Control Flow Statements\n\n- **`IfStmt`** - if condition then [else]; supports init; Then/Else are blocks or statements\n - `getCondition()`, `getThen()`, `getElse()`, `getInit()`\n- **`ForStmt`** - Classic init/cond/post; `LoopStmt` superclass\n - `getInit()`, `getCondition()`, `getPost()`, `getBody()`\n- **`RangeStmt`** - "for k,v := range expr { \u2026 }"\n - `getKey()`, `getValue()`, `getDomain()`, `getBody()`\n\n### Switch and Select Statements\n\n- **`SwitchStmt`/`ExpressionSwitchStmt`** - Expression-based switch\n- **`TypeSwitchStmt`** - Type-based switch\n- **`CaseClause`** - Case clause inside switch statements\n - `getExpr(i)`, `getStmt(i)`\n- **`SelectStmt`** - Select statement for channel operations\n- **`CommClause`** - Communication clause in select statement\n\n### Channel and Concurrency Statements\n\n- **`SendStmt`** - Channel send "ch <- x"\n- **`RecvStmt`** - Channel receive "x = <-ch"\n- **`GoStmt`** - Goroutine launch "go f()"\n- **`DeferStmt`** - Deferred function call "defer f()"\n\n### Assignment and Increment Statements\n\n- **`SimpleAssignStmt`** - Simple assignment "="\n- **`DefineStmt`** - Short variable declaration ":="\n- **`CompoundAssignStmt`** - Compound assignment (+=, -=, \\*=, /=, %=, &=, |=, ^=, <<=, >>=, &^=)\n- **`IncStmt`** - Increment "x++"\n- **`DecStmt`** - Decrement "x--"\n\n### Jump Statements\n\n- **`LabeledStmt`** - Labeled statement\n- **`BreakStmt`** - Break statement\n- **`ContinueStmt`** - Continue statement\n- **`GotoStmt`** - Goto statement\n- **`FallthroughStmt`** - Fallthrough statement\n- **`ReturnStmt`** - Return statement\n - `getResult(i)` to access return values\n\n## Expressions (Expr)\n\n### Literals\n\n- **`BasicLit`** subclasses:\n - **`IntLit`** - Integer literal\n - **`FloatLit`** - Floating point literal\n - **`ImagLit`** - Imaginary literal\n - **`CharLit`/`RuneLit`** - Character/rune literal\n - **`StringLit`** - String literal\n- **`CompositeLit`** - Composite literals:\n - **`StructLit`** - Struct literal "T{\u2026}"\n - **`MapLit`** - Map literal "map[K]V{\u2026}"\n- **`FuncLit`** - Function literal (anonymous function)\n\n### Unary Expressions\n\n- **`PlusExpr`** - Unary plus "+x"\n- **`MinusExpr`** - Unary minus "-x"\n- **`NotExpr`** - Logical not "!x"\n- **`ComplementExpr`** - Bitwise complement "^x"\n- **`AddressExpr`** - Address-of "&x"\n- **`RecvExpr`** - Channel receive "<-x"\n\n### Binary Expressions\n\n- **Arithmetic**: `MulExpr`, `QuoExpr`, `RemExpr`, `AddExpr`, `SubExpr`\n- **Shift**: `ShlExpr` "<<", `ShrExpr` ">>"\n- **Logical**: `LandExpr` "&&", `LorExpr` "||"\n- **Relational**: `LssExpr` "<", `GtrExpr` ">", `LeqExpr` "<=", `GeqExpr` ">="\n- **Equality**: `EqlExpr` "==", `NeqExpr` "!="\n- **Bitwise**: `AndExpr` "&", `OrExpr` "|", `XorExpr` "^", `AndNotExpr` "&^"\n\n### Access and Call Expressions\n\n- **`SelectorExpr`** - Field/method access "X.Y"\n - `getBase()`, `getSelector()`\n- **`CallExpr`** - Function/method call\n - `getCallee()`, `getAnArgument()`, `getArgument(i)`\n- **`IndexExpr`** - Array/slice/map index "a[i]"\n- **`SliceExpr`** - Slice expression "a[i:j:k]"\n- **`KeyValueExpr`** - Key-value pair in composite literals\n\n### Type-related Expressions\n\n- **`ParenExpr`** - Parenthesized expression\n- **`StarExpr`** - Pointer dereference/type\n- **`TypeAssertExpr`** - Type assertion "x.(T)"\n- **`Conversion`** - Type conversion "T(x)"\n\n## Type Expressions (no common superclass)\n\n- **`ArrayTypeExpr`** - Array type "[N]T" or slice type "[]T"\n- **`StructTypeExpr`** - Struct type "struct{\u2026}"\n- **`FuncTypeExpr`** - Function type "func(\u2026) \u2026"\n- **`InterfaceTypeExpr`** - Interface type\n- **`MapTypeExpr`** - Map type\n- **`ChanTypeExpr`** variants:\n - **`SendChanTypeExpr`** - Send-only channel\n - **`RecvChanTypeExpr`** - Receive-only channel\n - **`SendRecvChanTypeExpr`** - Bidirectional channel\n\n## Names and Identifiers\n\n### Name Hierarchy\n\n- **`Name`** subclasses:\n - **`SimpleName`** - Simple identifier\n - **`QualifiedName`** - Package-qualified name\n- **`ValueName`** subclasses:\n - **`ConstantName`** - Constant identifier\n - **`VariableName`** - Variable identifier\n - **`FunctionName`** - Function identifier\n\n### Specialized Names\n\n- **`PackageName`** - Package name identifier\n- **`TypeName`** - Type name identifier\n- **`LabelName`** - Label identifier\n\n## Declarations\n\n### Function Declarations\n\n- **`FuncDecl`/`FuncLit`** via **`FuncDef`**:\n - `getBody()`, `getName()`, `getParameter(i)`, `getResultVar(i)`, `getACall()`\n\n### General Declarations\n\n- **`GenDecl`** with:\n - **`ImportSpec`** - Import specification\n - **`TypeSpec`** - Type specification\n - **`ValueSpec`** - Variable/constant specification\n- **`Field`/`FieldList`** - For parameters, results, struct/interface fields\n\n## Navigation Idioms and Patterns\n\n### Control Flow Navigation\n\n- **If statements**: `getCondition()`, `getThen()`, `getElse()`\n- **For/Range loops**: inspect `getInit()`/`getCondition()`/`getPost()` or range expression\n- **Switch statements**: use `CaseClause`, `getExpr(i)`/`getStmt(i)`\n- **Select statements**: use `CommClause`\n\n### Function and Method Calls\n\n```ql\n// Method calls by name\nfrom CallExpr call, SelectorExpr sel\nwhere call.getCallee() = sel and sel.getMemberName() = "Close"\nselect call\n\n// Method vs function calls\n// SelectorExpr callee = method call\n// SimpleName callee = function call\n```\n\n### Assignment Operations\n\n- **Assignment**: match `AssignStmt` subclasses\n- **Short variable declaration**: `DefineStmt` for ":="\n- **Compound assignment**: `CompoundAssignStmt` for "+=", etc.\n\n### Binary and Unary Operations\n\n- Use specific subclasses or operator accessors\n- Access operands via `getLeftOperand()`, `getRightOperand()`\n\n### Literals and Composite Expressions\n\n- **Basic literals**: filter `BasicLit` subclasses\n- **Composite literals**: `CompositeLit` elements via keys/values\n- **Struct literals**: `StructLit` with type information\n\n## Common Query Patterns\n\n### Finding Specific Constructs\n\n```ql\n// Range over map/slice\nfrom RangeStmt r select r\n\n// Defer calls\nfrom DeferStmt d, CallExpr c\nwhere d.getExpr() = c\nselect d, c\n\n// Struct literal of specific type\nfrom StructLit lit\nwhere lit.getType().getName() = "Point"\nselect lit\n\n// Channel operations\nfrom SendStmt s select s // ch <- x\nfrom RecvStmt r select r // x = <-ch\n```\n\n### Method Resolution\n\n```ql\n// Find method calls on specific receiver types\nfrom CallExpr call, SelectorExpr sel\nwhere call.getCallee() = sel and\n sel.getBase().getType().toString() = "MyType"\nselect call\n```\n\n## File and Module Navigation\n\n- **`GoFile`** - Represents a Go source file\n- **`GoModFile`** - Represents a go.mod file\n- **`GoModModuleLine`** - Module declaration in go.mod\n- **`GoModGoLine`** - Go version declaration in go.mod\n\n## Comments and Documentation\n\n- **`CommentGroup`** - Group of related comments\n- **`DocComment`** - Documentation comment group (typically for functions/types)\n- **`SlashSlashComment`** - Single-line comment (//) within comment groups\n\n## Advanced Features\n\n### Generics Support\n\n- **`TypeParamDecl`** - Type parameter declaration with constraints\n- Generic type parameters and constraints for Go generics\n- Support for type inference and constraint satisfaction\n\n### Concurrency Constructs\n\n- **Goroutines**: `GoStmt` for "go f()" patterns\n- **Channels**: `SendStmt`, `RecvStmt`, `RecvExpr` for channel operations\n- **Select**: `SelectStmt` with `CommClause` for channel multiplexing\n- **Defer**: `DeferStmt` for cleanup patterns\n\n## Tips and Best Practices\n\n### Preferred Patterns\n\n- **Class tests over string parsing**: Use specific AST classes rather than string matching\n- **Type conversion disambiguation**: `CallExpr` callee is a `TypeExpr` for type conversions\n- **Statement vs expression**: Inc/Dec are statements, not expressions\n- **Assignment variants**: Handle ":=" vs "=" separately with `DefineStmt` vs `SimpleAssignStmt`\n- **Error handling**: Exclude `BadStmt`/`BadExpr` from analysis\n\n### Syntax to Class Mapping Cheatsheet\n\n- **Control Flow**: If\u2192`IfStmt`, For\u2192`ForStmt`, Range\u2192`RangeStmt`, Switch\u2192`SwitchStmt`/`ExpressionSwitchStmt`, Type switch\u2192`TypeSwitchStmt`, Select\u2192`SelectStmt`\n- **Cases**: Case\u2192`CaseClause`, Select case\u2192`CommClause`\n- **Assignment**: `=`\u2192`SimpleAssignStmt`, `:=`\u2192`DefineStmt`, `+=` etc.\u2192`CompoundAssignStmt`\n- **Increment**: `++`\u2192`IncStmt`, `--`\u2192`DecStmt`\n- **Access**: Call\u2192`CallExpr`, Selector\u2192`SelectorExpr`, Index\u2192`IndexExpr`, Slice\u2192`SliceExpr`\n- **Type operations**: Type assert\u2192`TypeAssertExpr`, Conversion\u2192`Conversion`\n- **Unary/Binary**: Specific subclasses of `UnaryExpr`/`BinaryExpr`\n- **Literals**: `IntLit`, `FloatLit`, `StringLit`, `StructLit`, `MapLit`, `FuncLit`\n- **Types**: `ArrayTypeExpr`, `StructTypeExpr`, `FuncTypeExpr`, `InterfaceTypeExpr`, `MapTypeExpr`, `ChanTypeExpr`\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `go` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="go"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `go` language:\n\n- [library-tests/semmle/go/PrintAst/PrintAst.expected](https://github.com/github/codeql/blob/main/go/ql/test/library-tests/semmle/go/PrintAst/PrintAst.expected)\n- [library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected](https://github.com/github/codeql/blob/main/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.expected)\n- [library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected](https://github.com/github/codeql/blob/main/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.expected)\n- [library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected](https://github.com/github/codeql/blob/main/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.expected)\n- [library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected](https://github.com/github/codeql/blob/main/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.expected)\n';
64105
+
64106
+ // src/resources/languages/go_basic_queries.md
64107
+ var go_basic_queries_default = '# Basic CodeQL Query Examples for Go\n\n## Purpose\n\nMinimal Go query examples in VS Code; variables, constraints, and results for concrete bug patterns. Demonstrates query structure and common Go programming pattern detection.\n\n## Basic Query Structure\n\n### Query Components (SQL-like analogy)\n\n- **`import`**: Include standard Go library (`import go`)\n- **`from`**: Declare typed variables to range over (`Method`, `Variable`, `Write`, `Field`)\n- **`where`**: Constrain relationships among variables with predicates\n- **`select`**: Emit results; message can concatenate strings and AST entities\n\n### Template Structure\n\n```ql\nimport go\n\nfrom <Type1> var1, <Type2> var2, ...\nwhere <conditions and relationships>\nselect <results>, "<message with " + var1 + " references>"\n```\n\n## Example 1: Value Receiver Method Modifications\n\n### Target Pattern\n\nMethods defined on value receivers that write to a field have no effect (receiver is copied). Should use pointer receiver instead.\n\n### Query\n\n```ql\nimport go\n\nfrom Method m, Variable recv, Write w, Field f\nwhere recv = m.getReceiver() and\n w.writesField(recv.getARead(), f, _) and\n not recv.getType() instanceof PointerType\nselect w, "This update to " + f + " has no effect, because " + recv + " is not a pointer."\n```\n\n### Key Predicates\n\n- **`Method.getReceiver()`**: Receiver variable of a method\n- **`Write.writesField(baseRead, field, idx)`**: Write whose LHS writes field of base expression\n- **`Variable.getARead()`**: Read expression of the variable\n- **`PointerType`**: Type test to exclude pointer receivers\n\n## Example 2: Missing Error Handling\n\n### Target Pattern\n\nFunction calls that return errors but the error is ignored.\n\n### Query\n\n```ql\nimport go\n\nfrom CallExpr call, AssignStmt assign\nwhere call.getType().toString().matches("%error%") and\n assign.getRhs() = call and\n assign.getLhs().(Ident).getName() = "_"\nselect call, "Error from " + call.getTarget().getName() + " is ignored"\n```\n\n## Example 3: Nil Pointer Dereference Risk\n\n### Target Pattern\n\nPointer dereference without nil check.\n\n### Query\n\n```ql\nimport go\n\nfrom StarExpr deref, Variable ptr\nwhere deref.getExpr() = ptr.getARead() and\n not exists(IfStmt guard, NeqExpr check |\n check.getLeftOperand() = ptr.getARead() and\n check.getRightOperand().(Ident).getName() = "nil" and\n guard.getCondition() = check and\n deref.getParent*() = guard.getThen()\n )\nselect deref, "Potential nil pointer dereference of " + ptr\n```\n\n## Example 4: Goroutine Without Context\n\n### Target Pattern\n\nGoroutines launched without context cancellation mechanism.\n\n### Query\n\n```ql\nimport go\n\nfrom GoStmt goStmt, FuncLit funcLit\nwhere goStmt.getExpr() = funcLit and\n not exists(Parameter ctx |\n ctx = funcLit.getParameter(0) and\n ctx.getType().toString().matches("%context.Context%")\n )\nselect goStmt, "Goroutine launched without context parameter"\n```\n\n## Example 5: Unsafe Type Assertion\n\n### Target Pattern\n\nType assertions without the "ok" idiom to check success.\n\n### Query\n\n```ql\nimport go\n\nfrom TypeAssertExpr assert\nwhere not exists(TupleExpr tuple, VariableName ok |\n tuple = assert.getParent() and\n tuple.getElement(1) = ok.getARead() and\n ok.getName() = "ok"\n )\nselect assert, "Type assertion without ok check: " + assert.toString()\n```\n\n## Example 6: Resource Leak - Missing Close\n\n### Target Pattern\n\nFiles opened without corresponding defer close.\n\n### Query\n\n```ql\nimport go\n\nfrom CallExpr open, VariableName file\nwhere open.getTarget().hasQualifiedName("os", "Open") and\n open.getARead() = file.getARead() and\n not exists(DeferStmt defer, CallExpr close |\n close.getTarget().getName() = "Close" and\n close.getReceiver() = file.getARead() and\n defer.getExpr() = close\n )\nselect open, "File opened without defer close: " + file\n```\n\n## Example 7: SQL Injection Risk\n\n### Target Pattern\n\nString concatenation used to build SQL queries.\n\n### Query\n\n```ql\nimport go\n\nfrom CallExpr dbCall, AddExpr concat, StringLit sqlPart\nwhere dbCall.getTarget().hasQualifiedName("database/sql", ["Query", "Exec"]) and\n dbCall.getArgument(0) = concat and\n concat.getAnOperand() = sqlPart and\n sqlPart.getValue().matches("%SELECT%")\nselect concat, "SQL query built by concatenation, potential injection risk"\n```\n\n## Example 8: Command Injection Risk\n\n### Target Pattern\n\nUser input used directly in command execution.\n\n### Query\n\n```ql\nimport go\n\nfrom CallExpr execCall, CallExpr inputCall\nwhere execCall.getTarget().hasQualifiedName("os/exec", "Command") and\n inputCall.getTarget().hasQualifiedName("os", "Getenv") and\n DataFlow::localFlow(DataFlow::exprNode(inputCall), DataFlow::exprNode(execCall.getAnArgument()))\nselect execCall, "Environment variable flows to command execution"\n```\n\n## Example 9: Range Over Map in Goroutine\n\n### Target Pattern\n\nRange over map in goroutine without copying the value (race condition risk).\n\n### Query\n\n```ql\nimport go\n\nfrom GoStmt goStmt, RangeStmt rangeStmt, Variable mapVar\nwhere goStmt.getExpr().(FuncLit).getBody().getAStmt*() = rangeStmt and\n rangeStmt.getDomain() = mapVar.getARead() and\n mapVar.getType().toString().matches("map[%")\nselect rangeStmt, "Range over map " + mapVar + " in goroutine may cause race condition"\n```\n\n## Example 10: Slice Bounds Check Missing\n\n### Target Pattern\n\nSlice access without bounds checking.\n\n### Query\n\n```ql\nimport go\n\nfrom IndexExpr index, Variable slice\nwhere index.getBase() = slice.getARead() and\n slice.getType().toString().matches("[]%") and\n not exists(IfStmt guard, CallExpr lenCall, RelationalComparisonExpr compare |\n lenCall.getTarget().getName() = "len" and\n lenCall.getArgument(0) = slice.getARead() and\n compare.getAnOperand() = index.getIndex() and\n compare.getAnOperand() = lenCall and\n guard.getCondition() = compare\n )\nselect index, "Slice access without bounds check: " + slice\n```\n\n## Usage Patterns\n\n### Finding Specific Function Calls\n\n```ql\n// Find all calls to specific function\nfrom CallExpr call\nwhere call.getTarget().hasQualifiedName("fmt", "Printf")\nselect call\n\n// Find method calls on specific type\nfrom CallExpr call, SelectorExpr sel\nwhere call.getCallee() = sel and\n sel.getBase().getType().toString() = "MyType" and\n sel.getSelector().getName() = "MyMethod"\nselect call\n```\n\n### Working with Control Flow\n\n```ql\n// Find if statements with specific conditions\nfrom IfStmt ifStmt, EqlExpr eq\nwhere ifStmt.getCondition() = eq and\n eq.getRightOperand().(Ident).getName() = "nil"\nselect ifStmt\n\n// Find loops with range\nfrom RangeStmt rangeStmt\nwhere rangeStmt.getKey().getName() != "_" and\n rangeStmt.getValue().getName() != "_"\nselect rangeStmt\n```\n\n### Package and Import Analysis\n\n```ql\n// Find specific imports\nfrom ImportSpec spec\nwhere spec.getPath().getValue() = "unsafe"\nselect spec, "Unsafe package imported"\n\n// Find package-level variables\nfrom Variable v\nwhere v.isPackageLevel() and\n v.getName().matches("debug%")\nselect v\n```\n\n## Testing and Refinement\n\n### Running Queries in VS Code\n\n1. Open VS Code with CodeQL extension\n2. Paste query after `import go`\n3. Click "Run Query" or use Ctrl+Shift+P \u2192 "CodeQL: Run Query"\n4. Click results to jump to code locations\n\n### Refining Results\n\n```ql\n// Add guards to exclude false positives\nwhere not exists(CommentGroup comment |\n comment.getText().matches("%TODO%") and\n comment.getLocation().getStartLine() < result.getLocation().getStartLine()\n )\n\n// Restrict to specific files or packages\nwhere result.getFile().getBaseName().matches("%.go") and\n not result.getFile().getAbsolutePath().matches("%test%")\n```\n\n### Extensions and Improvements\n\n- Add guards to exclude writes to temporary copies\n- Restrict to exported methods/types\n- Focus on specific packages with `hasQualifiedName`\n- Convert to path queries to show data flow\n- Add more specific type checking\n\nThese examples provide practical starting points for finding real Go programming issues and can be customized for specific codebases and requirements.\n';
64108
+
64109
+ // src/resources/languages/go_dataflow.md
64110
+ var go_dataflow_default = '# Analyzing Data Flow in Go\n\n## Purpose\n\nUse CodeQL\'s Go data-flow libraries to find how values and taint propagate through Go programs. Cover local flow/taint (intra-procedural) and global flow/taint (inter-procedural), with configurable sources/sinks/barriers.\n\n## Core Concepts\n\n### Data Flow vs Taint Tracking\n\n- **Data Flow**: Tracks exact value preservation through assignments, calls, and returns\n- **Taint Tracking**: Tracks influence/contamination, including non-value-preserving operations like concatenation\n\n### Node Hierarchy\n\n- **`Node`** - Base class for data flow nodes\n - **`ExprNode`** - Expression in the AST\n - **`ParameterNode`** - Function parameter\n - **`InstructionNode`** - Intermediate representation instruction\n\n### Node Conversion\n\n- **AST to DataFlow**: `DataFlow::exprNode(expr)`, `DataFlow::parameterNode(param)`\n- **DataFlow to AST**: `node.asExpr()`, `node.asParameter()`, `node.asInstruction()`\n\n## Local Data Flow\n\n### Basic Predicates\n\n- **`localFlowStep(Node a, Node b)`** - Direct flow from `a` to `b` within same function\n- **`localFlow(Node a, Node b)`** - Transitive closure (`localFlowStep*`)\n\n### Example: Tracking to Function Arguments\n\n```ql\nimport go\nfrom Function osOpen, CallExpr call, Expr src\nwhere osOpen.hasQualifiedName("os","Open") and\n call.getTarget() = osOpen and\n DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0)))\nselect src, "flows to os.Open argument"\n```\n\n### Local Flow Patterns\n\n```ql\n// Variable assignment flow\nfrom Variable v, Expr source, Expr use\nwhere DataFlow::localFlow(DataFlow::exprNode(source), DataFlow::exprNode(use)) and\n source = v.getAnAssignment() and\n use = v.getARead()\nselect source, use\n\n// Parameter to return flow\nfrom Function f, Parameter p, ReturnStmt ret\nwhere DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(ret.getAResult()))\nselect p, ret\n```\n\n## Local Taint Tracking\n\n### Basic Predicates\n\n- **`localTaintStep(Node a, Node b)`** - Direct taint from `a` to `b`\n- **`localTaint(Node a, Node b)`** - Transitive taint closure\n\n### Taint vs Flow Examples\n\n```ql\n// String concatenation - taint but not flow\nfrom Expr source, Expr concat\nwhere concat.(AddExpr).getAnOperand() = source and\n TaintTracking::localTaint(DataFlow::exprNode(source), DataFlow::exprNode(concat))\nselect source, concat\n\n// Array element access - taint propagation\nfrom Expr array, Expr element\nwhere element.(IndexExpr).getBase() = array and\n TaintTracking::localTaint(DataFlow::exprNode(array), DataFlow::exprNode(element))\nselect array, element\n```\n\n## Global Data Flow\n\n### Configuration Interface\n\nImplement `DataFlow::ConfigSig`:\n\n```ql\nmodule MyConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n // Define where flow starts\n }\n\n predicate isSink(DataFlow::Node sink) {\n // Define where flow ends\n }\n\n predicate isBarrier(DataFlow::Node node) {\n // Optional: block flow through certain nodes\n }\n\n predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {\n // Optional: add custom flow edges\n }\n}\n\nmodule MyFlow = DataFlow::Global<MyConfig>;\n```\n\n### Usage Pattern\n\n```ql\nfrom DataFlow::Node source, DataFlow::Node sink\nwhere MyFlow::flow(source, sink)\nselect source, "flows to $@", sink, "sink"\n```\n\n### Complete Example: Hard-coded Strings to URL Parse\n\n```ql\nmodule StringToUrlConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n source.asExpr() instanceof StringLit\n }\n\n predicate isSink(DataFlow::Node sink) {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("net/url", "Parse") and\n sink.asExpr() = call.getArgument(0)\n )\n }\n}\n\nmodule StringToUrlFlow = DataFlow::Global<StringToUrlConfig>;\n\nfrom DataFlow::Node source, DataFlow::Node sink\nwhere StringToUrlFlow::flow(source, sink)\nselect source, "String literal flows to URL parse $@", sink, "here"\n```\n\n## Global Taint Tracking\n\n### Configuration Interface\n\nSame as data flow but with taint semantics:\n\n```ql\nmodule MyTaintConfig implements TaintTracking::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n source instanceof RemoteFlowSource // Built-in remote sources\n }\n\n predicate isSink(DataFlow::Node sink) {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("os/exec", "Command") and\n sink.asExpr() = call.getAnArgument()\n )\n }\n}\n\nmodule MyTaintFlow = TaintTracking::Global<MyTaintConfig>;\n```\n\n### Built-in Sources\n\n```ql\n// RemoteFlowSource covers common user input sources\nclass MyRemoteSource extends RemoteFlowSource {\n MyRemoteSource() {\n // Additional remote sources beyond built-ins\n }\n}\n```\n\n## Advanced Flow Configuration\n\n### Custom Flow Steps\n\n```ql\npredicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {\n // Custom builder pattern\n exists(CallExpr call |\n call.getTarget().getName() = "WithValue" and\n node1.asExpr() = call.getReceiver() and\n node2.asExpr() = call\n )\n or\n // Flow through slice append\n exists(CallExpr append |\n append.getTarget().getName() = "append" and\n node1.asExpr() = append.getAnArgument() and\n node2.asExpr() = append\n )\n}\n```\n\n### Barriers and Sanitizers\n\n```ql\npredicate isBarrier(DataFlow::Node node) {\n // Block flow through validation functions\n exists(CallExpr call |\n call.getTarget().getName().matches("%Validate%") and\n node.asExpr() = call\n )\n or\n // Block at error checks\n exists(IfStmt guard, NeqExpr check |\n check.getRightOperand().(Ident).getName() = "nil" and\n guard.getCondition() = check and\n node.asExpr().getParent*() = guard.getThen()\n )\n}\n```\n\n## Common Data Flow Patterns\n\n### Environment Variables to Sinks\n\n```ql\nclass GetenvSource extends DataFlow::Node {\n GetenvSource() {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("os", "Getenv") and\n this.asExpr() = call\n )\n }\n}\n\nmodule EnvToSinkConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }\n predicate isSink(DataFlow::Node sink) { /* define sinks */ }\n}\n```\n\n### Command Line Arguments\n\n```ql\nclass CommandLineArgSource extends DataFlow::Node {\n CommandLineArgSource() {\n exists(IndexExpr access |\n access.getBase().(Ident).getName() = "Args" and\n access.getBase().getType().toString() = "[]string" and\n this.asExpr() = access\n )\n }\n}\n```\n\n### HTTP Request Data\n\n```ql\nclass HttpRequestSource extends DataFlow::Node {\n HttpRequestSource() {\n exists(CallExpr call, SelectorExpr sel |\n sel.getBase().getType().toString().matches("%Request%") and\n sel.getSelector().getName() in ["FormValue", "PostFormValue", "Header"] and\n call.getCallee() = sel and\n this.asExpr() = call\n )\n }\n}\n```\n\n### Database Queries\n\n```ql\npredicate isDatabaseQuerySink(DataFlow::Node sink) {\n exists(CallExpr call, Function target |\n call.getTarget() = target and\n target.hasQualifiedName("database/sql", ["Query", "QueryRow", "Exec", "Prepare"]) and\n sink.asExpr() = call.getArgument(0)\n )\n}\n```\n\n## Path Queries for Better Results\n\n### Basic Path Query Structure\n\n```ql\n/**\n * @kind path-problem\n */\nimport go\nimport DataFlow::PathGraph\n\n// ... config definition ...\n\nfrom MyFlow::PathNode source, MyFlow::PathNode sink\nwhere MyFlow::flowPath(source, sink)\nselect sink.getNode(), source, sink,\n "Value from $@ reaches sink", source.getNode(), "source"\n```\n\n### Multi-step Flow Analysis\n\n```ql\n// First: literal to getenv parameter\nmodule LiteralToGetenvConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) { source.asExpr() instanceof StringLit }\n predicate isSink(DataFlow::Node sink) {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("os", "Getenv") and\n sink.asExpr() = call.getArgument(0)\n )\n }\n}\n\n// Second: getenv result to url.Parse\nmodule GetenvToUrlConfig implements DataFlow::ConfigSig {\n predicate isSource(DataFlow::Node source) {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("os", "Getenv") and\n source.asExpr() = call\n )\n }\n predicate isSink(DataFlow::Node sink) {\n exists(CallExpr call |\n call.getTarget().hasQualifiedName("net/url", "Parse") and\n sink.asExpr() = call.getArgument(0)\n )\n }\n}\n```\n\n## Performance and Precision Tips\n\n### Query Optimization\n\n- Start with local flow/taint for better performance\n- Use specific predicates rather than broad matching\n- Prefer `hasQualifiedName` over string patterns\n- Add barriers to reduce false paths\n\n### Debugging Flow\n\n```ql\n// Debug: show intermediate flow steps\nfrom DataFlow::Node n1, DataFlow::Node n2\nwhere DataFlow::localFlowStep(n1, n2) and\n n1.getFile().getBaseName() = "target.go"\nselect n1, n2\n```\n\n### Testing Configurations\n\n```ql\n// Test source identification\nfrom DataFlow::Node source\nwhere MyConfig::isSource(source)\nselect source\n\n// Test sink identification\nfrom DataFlow::Node sink\nwhere MyConfig::isSink(sink)\nselect sink\n```\n\n## Integration with Security Queries\n\n### Combining Multiple Configurations\n\n```ql\n// Union of different taint sources\npredicate isAnyTaintSource(DataFlow::Node source) {\n source instanceof RemoteFlowSource or\n source instanceof GetenvSource or\n source instanceof CommandLineArgSource\n}\n\n// Combined configuration\nmodule UnifiedTaintConfig implements TaintTracking::ConfigSig {\n predicate isSource(DataFlow::Node source) { isAnyTaintSource(source) }\n predicate isSink(DataFlow::Node sink) { /* any dangerous sink */ }\n}\n```\n\n### Framework-specific Flow\n\n```ql\n// Framework method chaining\npredicate isFrameworkFlowStep(DataFlow::Node node1, DataFlow::Node node2) {\n exists(CallExpr call |\n call.getReceiver() = node1.asExpr() and\n call.getTarget().getName().regexpMatch("With|Set|Add") and\n node2.asExpr() = call\n )\n}\n```\n\nThis provides the foundation for building sophisticated security queries that can track how untrusted data flows through Go programs to reach dangerous operations.\n';
64111
+
64112
+ // src/resources/languages/go_library_modeling.md
64113
+ var go_library_modeling_default = "# Customizing Library Models for Go\n\n## Purpose\n\nCustomize data-flow/taint analysis for Go by modeling frameworks/libraries via data extensions (YAML) and model packs. This enables accurate flow tracking through third-party libraries not included in CodeQL databases.\n\n## Data Extensions Overview\n\n### Structure\n\nData extensions use YAML format to extend CodeQL's knowledge of library behavior:\n\n```yaml\nextensions:\n - addsTo:\n pack: codeql/go-all\n extensible: <extensible-predicate>\n data:\n - <tuple1>\n - <tuple2>\n```\n\n### Union Semantics\n\n- Multiple YAML files are combined\n- Rows are merged across files\n- Duplicates are automatically removed\n- Order of files doesn't matter\n\n## Extensible Predicates for Go\n\n### Source Models\n\n**`sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance)`**\n\nDefine sources of untrusted data (e.g., user input):\n\n- **package**: Go package path (e.g., \"net/http\")\n- **type**: Type name (\"\" for package-level functions)\n- **subtypes**: Include subtypes (true/false)\n- **name**: Function/method name\n- **signature**: Function signature (\"\" for any)\n- **ext**: External library marker (\"\" for stdlib)\n- **output**: Access path where taint emerges\n- **kind**: Threat model category\n- **provenance**: Origin marker (manual/ai-manual/etc.)\n\n**Example**: HTTP request as source\n\n```yaml\n- ['net/http', 'Request', false, 'FormValue', '', '', 'ReturnValue', 'remote', 'manual']\n```\n\n### Sink Models\n\n**`sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)`**\n\nDefine dangerous operations (sinks):\n\n- **input**: Access path where taint is dangerous\n\n**Example**: Command execution sink\n\n```yaml\n- ['os/exec', '', false, 'Command', '', '', 'Argument[1]', 'command-injection', 'manual']\n```\n\n### Summary Models\n\n**`summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance)`**\n\nDefine how data flows through functions when dependency code isn't in the database:\n\n- **input**: Where data enters the function\n- **output**: Where data exits the function\n\n**Example**: String builder flow\n\n```yaml\n- ['strings', 'Builder', false, 'WriteString', '', '', 'Argument[0]', 'Receiver', 'taint', 'manual']\n```\n\n### Neutral Models\n\n**`neutralModel(package, type, name, signature, kind, provenance)`**\n\nDefine low-impact flows to reduce over-taint/noise:\n\n**Example**: Safe string operations\n\n```yaml\n- ['strings', '', 'ToUpper', '', 'value', 'manual']\n```\n\n## Access Paths\n\n### Basic Access Paths\n\n- **`Argument[i]`** - ith argument (0-indexed)\n- **`ReturnValue`** - Function return value\n- **`Receiver`** - Method receiver\n- **`Qualifier`** - Object being called on\n\n### Complex Access Paths\n\n- **`Argument[i].Field[\"name\"]`** - Field of argument\n- **`Argument[i].ArrayElement`** - Array/slice elements\n- **`ReturnValue.ArrayElement`** - Elements of returned array/slice\n- **`Field[\"name\"].ArrayElement`** - Elements of field array\n\n### Examples\n\n```yaml\n# Array/slice element flow\n- ['slices', '', false, 'Max', '', '', 'Argument[0].ArrayElement', 'ReturnValue', 'value', 'manual']\n\n# Nested array flow\n- [\n 'slices',\n '',\n false,\n 'Concat',\n '',\n '',\n 'Argument[0].ArrayElement.ArrayElement',\n 'ReturnValue.ArrayElement',\n 'value',\n 'manual'\n ]\n\n# Struct field flow\n- [\n 'encoding/json',\n '',\n false,\n 'Unmarshal',\n '',\n '',\n 'Argument[0]',\n 'Argument[1].Field[*]',\n 'taint',\n 'manual'\n ]\n```\n\n## Flow Kinds\n\n### Value vs Taint\n\n- **\"value\"**: Moves whole values (precise data flow)\n- **\"taint\"**: Propagates taint only (influence tracking)\n\n### Security Categories\n\nCommon `kind` values for threat modeling:\n\n- **\"remote\"**: Remote user input\n- **\"command-injection\"**: Command execution\n- **\"sql-injection\"**: Database queries\n- **\"path-injection\"**: File system access\n- **\"code-injection\"**: Code execution\n- **\"xss\"**: Cross-site scripting\n\n## Complete Examples\n\n### HTTP Framework Modeling\n\n```yaml\nextensions:\n - addsTo:\n pack: codeql/go-all\n extensible: sourceModel\n data:\n # HTTP request sources\n - ['net/http', 'Request', false, 'FormValue', '', '', 'ReturnValue', 'remote', 'manual']\n - ['net/http', 'Request', false, 'PostFormValue', '', '', 'ReturnValue', 'remote', 'manual']\n - ['net/http', 'Request', false, 'Header', '', '', 'ReturnValue', 'remote', 'manual']\n - ['net/http', 'Request', false, 'URL', '', '', 'ReturnValue.Field[*]', 'remote', 'manual']\n\n - addsTo:\n pack: codeql/go-all\n extensible: sinkModel\n data:\n # HTTP response sinks\n - ['net/http', 'ResponseWriter', false, 'Write', '', '', 'Argument[0]', 'xss', 'manual']\n - [\n 'net/http',\n 'ResponseWriter',\n false,\n 'Header',\n '',\n '',\n 'ReturnValue',\n 'response-header',\n 'manual'\n ]\n```\n\n### Database Library Modeling\n\n```yaml\nextensions:\n - addsTo:\n pack: codeql/go-all\n extensible: summaryModel\n data:\n # Database query builders\n - [\n 'github.com/jmoiron/sqlx',\n 'DB',\n false,\n 'Query',\n '',\n '',\n 'Argument[0]',\n 'ReturnValue.Field[*]',\n 'taint',\n 'manual'\n ]\n - [\n 'github.com/jmoiron/sqlx',\n 'DB',\n false,\n 'Select',\n '',\n '',\n 'Argument[1]',\n 'Argument[0].Field[*]',\n 'taint',\n 'manual'\n ]\n\n - addsTo:\n pack: codeql/go-all\n extensible: sinkModel\n data:\n # SQL injection sinks\n - [\n 'github.com/jmoiron/sqlx',\n 'DB',\n false,\n 'Query',\n '',\n '',\n 'Argument[0]',\n 'sql-injection',\n 'manual'\n ]\n - [\n 'github.com/jmoiron/sqlx',\n 'DB',\n false,\n 'Exec',\n '',\n '',\n 'Argument[0]',\n 'sql-injection',\n 'manual'\n ]\n```\n\n### JSON Processing\n\n```yaml\nextensions:\n - addsTo:\n pack: codeql/go-all\n extensible: summaryModel\n data:\n # JSON unmarshaling\n - [\n 'encoding/json',\n '',\n false,\n 'Unmarshal',\n '',\n '',\n 'Argument[0]',\n 'Argument[1].Field[*]',\n 'taint',\n 'manual'\n ]\n - [\n 'encoding/json',\n '',\n false,\n 'Marshal',\n '',\n '',\n 'Argument[0].Field[*]',\n 'ReturnValue',\n 'taint',\n 'manual'\n ]\n\n - addsTo:\n pack: codeql/go-all\n extensible: sourceModel\n data:\n # JSON from HTTP as source\n - [\n 'encoding/json',\n 'Decoder',\n false,\n 'Decode',\n '',\n '',\n 'Argument[0].Field[*]',\n 'remote',\n 'manual'\n ]\n```\n\n### String Processing Libraries\n\n```yaml\nextensions:\n - addsTo:\n pack: codeql/go-all\n extensible: summaryModel\n data:\n # String builder patterns\n - [\n 'strings',\n 'Builder',\n false,\n 'WriteString',\n '',\n '',\n 'Argument[0]',\n 'Receiver',\n 'taint',\n 'manual'\n ]\n - [\n 'strings',\n 'Builder',\n false,\n 'String',\n '',\n '',\n 'Receiver',\n 'ReturnValue',\n 'taint',\n 'manual'\n ]\n\n # Template processing\n - [\n 'text/template',\n 'Template',\n false,\n 'Execute',\n '',\n '',\n 'Argument[1].Field[*]',\n 'Argument[0]',\n 'taint',\n 'manual'\n ]\n - [\n 'html/template',\n 'Template',\n false,\n 'Execute',\n '',\n '',\n 'Argument[1].Field[*]',\n 'Argument[0]',\n 'taint',\n 'manual'\n ]\n```\n\n## Model Packs\n\n### Pack Structure\n\nCreate a CodeQL model pack to group and distribute YAML files:\n\n```yaml\n# codeql-pack.yml\nname: my-org/go-security-models\nversion: 1.0.0\ndependencies:\n codeql/go-all: '*'\ndataExtensions: '*.yml'\n```\n\n### Directory Structure\n\n```\nmy-go-models/\n\u251C\u2500\u2500 codeql-pack.yml\n\u251C\u2500\u2500 http-frameworks.yml\n\u251C\u2500\u2500 database-orms.yml\n\u2514\u2500\u2500 json-libraries.yml\n```\n\n### Publishing to GitHub Container Registry\n\n```bash\ncodeql pack publish\n```\n\n### Consuming Model Packs\n\n```yaml\n# In consumer's codeql-pack.yml\ndependencies:\n my-org/go-security-models: '^1.0.0'\n```\n\nOr via CLI:\n\n```bash\ncodeql database analyze --packs my-org/go-security-models\n```\n\n## Advanced Patterns\n\n### Framework-specific Source Patterns\n\n```yaml\n# Gin framework\n- ['github.com/gin-gonic/gin', 'Context', false, 'Param', '', '', 'ReturnValue', 'remote', 'manual']\n- ['github.com/gin-gonic/gin', 'Context', false, 'Query', '', '', 'ReturnValue', 'remote', 'manual']\n- [\n 'github.com/gin-gonic/gin',\n 'Context',\n false,\n 'PostForm',\n '',\n '',\n 'ReturnValue',\n 'remote',\n 'manual'\n ]\n\n# Echo framework\n- [\n 'github.com/labstack/echo/v4',\n 'Context',\n false,\n 'Param',\n '',\n '',\n 'ReturnValue',\n 'remote',\n 'manual'\n ]\n- [\n 'github.com/labstack/echo/v4',\n 'Context',\n false,\n 'QueryParam',\n '',\n '',\n 'ReturnValue',\n 'remote',\n 'manual'\n ]\n- [\n 'github.com/labstack/echo/v4',\n 'Context',\n false,\n 'FormValue',\n '',\n '',\n 'ReturnValue',\n 'remote',\n 'manual'\n ]\n```\n\n### ORM and Query Builder Models\n\n```yaml\n# GORM models\n- ['gorm.io/gorm', 'DB', false, 'Raw', '', '', 'Argument[0]', 'ReturnValue', 'taint', 'manual']\n- ['gorm.io/gorm', 'DB', false, 'Exec', '', '', 'Argument[0]', '', 'sql-injection', 'manual']\n\n# Squirrel query builder\n- [\n 'github.com/Masterminds/squirrel',\n 'SelectBuilder',\n false,\n 'Where',\n '',\n '',\n 'Argument[0]',\n 'Receiver',\n 'taint',\n 'manual'\n ]\n- [\n 'github.com/Masterminds/squirrel',\n 'SelectBuilder',\n false,\n 'ToSql',\n '',\n '',\n 'Receiver',\n 'ReturnValue',\n 'taint',\n 'manual'\n ]\n```\n\n### Utility Library Flows\n\n```yaml\n# Viper configuration\n- ['github.com/spf13/viper', '', false, 'GetString', '', '', '', 'ReturnValue', 'config', 'manual']\n- ['github.com/spf13/viper', '', false, 'Get', '', '', '', 'ReturnValue', 'config', 'manual']\n\n# Cobra CLI arguments\n- [\n 'github.com/spf13/cobra',\n 'Command',\n false,\n 'Flags',\n '',\n '',\n '',\n 'ReturnValue',\n 'cli-input',\n 'manual'\n ]\n```\n\n## Workflow and Best Practices\n\n### Development Process\n\n1. **Identify Gap**: Find library calls that break data flow paths\n2. **Analyze Library**: Understand how data flows through the library\n3. **Create Models**: Start with summaries for common flows\n4. **Add Sources/Sinks**: Define security-relevant entry/exit points\n5. **Test and Iterate**: Validate with path queries and unit tests\n\n### Model Quality Guidelines\n\n- **Narrow Matching**: Use `hasQualifiedName` for precision\n- **Specific Access Paths**: Be precise about which fields/elements flow\n- **Appropriate Kinds**: Match `kind` to actual threat model\n- **Documentation**: Comment complex access paths\n- **Testing**: Validate with realistic code examples\n\n### Performance Considerations\n\n- Avoid overly broad models that create too many paths\n- Use `neutralModel` to reduce noise from safe operations\n- Consider performance impact of complex access paths\n- Test query performance with models enabled\n\n### Integration Testing\n\n```ql\n// Test model coverage\nfrom DataFlow::Node source, DataFlow::Node sink\nwhere MyFlow::flow(source, sink) and\n source.getFile().getBaseName() = \"test_library.go\"\nselect source, sink\n\n// Verify specific library modeling\nfrom CallExpr call\nwhere call.getTarget().hasQualifiedName(\"my/library\", \"MyFunction\")\nselect call, \"Library call found\"\n```\n\nThis comprehensive approach to library modeling enables accurate security analysis even when third-party library source code isn't available in the CodeQL database.\n";
64114
+
64115
+ // src/resources/languages/go_security_query_guide.md
64116
+ var go_security_query_guide_default = "# Go Security Query Guide\n\nLanguage-specific notes for writing Go security queries in CodeQL. For the general taint-tracking template and workflow, see the `security_templates` resource.\n\n## Imports\n\n```ql\nimport go\n```\n\nThe `go` top-level import re-exports data flow, taint tracking, and standard library models. For path-problem queries add `import MyFlow::PathGraph` after defining your flow module.\n\n## Sources and Sinks\n\n- **Sources**: Use `RemoteFlowSource` (covers `net/http` handlers, gRPC, and other HTTP frameworks). Also consider `UntrustedFlowSource` for broader input coverage.\n- **Sinks**: Model as `DataFlow::Node` subclasses matching dangerous APIs (e.g., `os/exec`, `database/sql`, `html/template`). Existing sink libraries live under `semmle.go.security.*`.\n- **Barriers**: Model sanitizers as `DataFlow::Node` subclasses and reference them in `isBarrier`.\n\n## Key Library Modules\n\n| Module | Purpose |\n| ---------------------------------- | ---------------------------------------- |\n| `semmle.go.dataflow.DataFlow` | Data flow nodes and global analysis |\n| `semmle.go.dataflow.TaintTracking` | Taint tracking analysis |\n| `semmle.go.security.*` | Pre-built vulnerability-specific configs |\n| `semmle.go.frameworks.*` | Framework-specific API models |\n";
64117
+
64118
+ // src/resources/languages/java_ast.md
64119
+ var java_ast_default = '# CodeQL AST nodes for `java` language\n\n## CodeQL\'s core AST classes for `java` language\n\nBased on comprehensive analysis of CodeQL\'s Java test results from GitHub, here are the core AST classes for Java analysis:\n\n### Compilation and Package Structure\n\n**Top-Level Units:**\n\n- `CompilationUnit` - Java source file compilation units (e.g., `CompilationUnit A`)\n- `ImportType` - Single type imports (e.g., `import HashMap`, `import IOException`)\n- `ImportOnDemandFromPackage` - Wildcard imports (e.g., `import java.util.*`)\n\n### Class and Interface Declarations\n\n**Class Structure:**\n\n- `Class` - Class declarations (e.g., `class A`, `class Test`)\n- `Interface` - Interface declarations (e.g., `interface Ann1`)\n- `GenericType` - Generic classes with type parameters\n- `ParameterizedType` - Parameterized types with specific type arguments\n\n**Generic Support:**\n\n- `TypeVariable` - Generic type parameters (e.g., `T`, `S extends Comparable`)\n- Generic class declarations and instantiations\n- Diamond operator support (`<>`) for type inference\n\n### Type System\n\n**Basic Type Access:**\n\n- `TypeAccess` - Type references (e.g., `String`, `int`, `void`, `Object`)\n- `ArrayTypeAccess` - Array types (e.g., `String[]`, `int[][]`)\n- Type access in generic contexts (e.g., `List<String>`, `Map<String,Integer>`)\n\n**Advanced Type Features:**\n\n- Parameterized types with multiple type arguments\n- Nested type access and inner class types\n- Array types with multiple dimensions\n\n### Field and Variable Declarations\n\n**Field Declarations:**\n\n- `FieldDeclaration` - Class field declarations (e.g., `String[] a;`, `float ff;`)\n- Field initialization with expressions\n- Generic field types (e.g., `List<> l`, `Map<String,Integer> m`)\n\n**Variable Declarations:**\n\n- `LocalVariableDeclStmt` - Local variable declaration statements\n- `LocalVariableDeclExpr` - Local variable declarator expressions\n- `Parameter` - Method and constructor parameters\n- `VarDecl` - Variable declaration identifiers\n\n### Method and Constructor Declarations\n\n**Method Structure:**\n\n- `Method` - Method declarations with return types and parameters\n- `Constructor` - Constructor declarations\n- Method signatures with generic types and varargs support\n\n**Parameter Handling:**\n\n- Parameter declarations with type access\n- Varargs parameters (e.g., `int... is`, `Object... os`)\n- Generic parameter types\n\n### Expressions\n\n**Primary Expressions:**\n\n- `IntegerLiteral` - Integer constants (e.g., `42`, `1`, `2`)\n- `FloatLiteral` - Floating-point literals (e.g., `2.3f`)\n- `StringLiteral` - String literals (e.g., `"hello"`, `"rawtypes"`)\n- `NullLiteral` - Null literal (`null`)\n- `BooleanLiteral` - Boolean literals (`true`, `false`)\n\n**Variable Access:**\n\n- `VarAccess` - Variable references (e.g., `thing`, `o`, `Initializers.SFIELD`)\n- Qualified variable access with type prefixes\n\n**Object Creation:**\n\n- `ClassInstanceExpr` - Object instantiation (e.g., `new ArrayList<>()`, `new LinkedHashMap<String,Integer>()`)\n- Constructor calls with type arguments\n- Anonymous class instances\n\n**Method Calls:**\n\n- `MethodCall` - Method invocations (e.g., `source()`, `sink()`)\n- Method calls with arguments and generic types\n\n**Type Operations:**\n\n- `CastExpr` - Type casting (e.g., `(E) thing`)\n- `InstanceOfExpr` - instanceof checks with pattern matching\n\n### Statements\n\n**Control Flow:**\n\n- `BlockStmt` - Block statements containing multiple statements\n- `IfStmt` - Conditional statements\n- `SwitchStmt` - Switch statements with traditional and pattern cases\n- `SwitchExpr` - Switch expressions with yield statements\n- `ReturnStmt` - Return statements\n- `YieldStmt` - Yield statements in switch expressions\n\n**Exception Handling:**\n\n- `TryStmt` - Try-catch-finally statements\n- `CatchClause` - Catch clauses with exception types\n- `ThrowStmt` - Throw statements\n- Multi-catch support for multiple exception types\n\n**Constructor Calls:**\n\n- `ThisConstructorInvocationStmt` - this() constructor calls\n- `SuperConstructorInvocationStmt` - super() constructor calls\n\n### Modern Java Features\n\n**Pattern Matching (Java 14+):**\n\n- `PatternCase` - Pattern matching in switch statements\n- `RecordPatternExpr` - Record pattern matching expressions\n- Pattern case declarations with local variables\n- Guarded patterns and complex pattern matching\n\n**Switch Expressions:**\n\n- `ConstCase` - Traditional constant cases\n- `DefaultCase` - Default cases in switch statements\n- Pattern-based case statements with guards\n\n**Records (Java 14+):**\n\n- Record declarations and pattern matching\n- Record component access and destructuring\n\n### Annotations and Documentation\n\n**Annotations:**\n\n- `Annotation` - Annotation usage (e.g., `@SuppressWarnings("rawtypes")`)\n- Annotation with arguments and values\n\n**Documentation:**\n\n- `Javadoc` - Javadoc comments (e.g., `/** A JavaDoc comment */`)\n- `JavadocText` - Text content within Javadoc\n- `JavadocTag` - Javadoc tags (e.g., `@author someone`)\n- Multi-line Javadoc support\n\n### Enum Support\n\n**Enumeration Features:**\n\n- Enum class declarations\n- Enum constant declarations with initialization\n- Enum constants with constructor arguments\n\n### Lambda Expressions and Functional Interfaces\n\n**Functional Programming:**\n\n- Anonymous class expressions for functional interfaces\n- Functional interface implementations (e.g., `BiFunction<Integer,Integer,Integer>`)\n- Lambda-style anonymous parameter handling\n\n### Advanced Expression Features\n\n**Complex Expressions:**\n\n- Parenthesized expressions for precedence control\n- Conditional expressions (ternary operator)\n- Assignment expressions and compound assignments\n\n**Array Operations:**\n\n- Array access and indexing expressions\n- Array initialization and manipulation\n- Multi-dimensional array support\n\n### Modifier Support\n\n**Access Modifiers:**\n\n- Support for `public`, `private`, `protected` modifiers\n- `static`, `final`, `abstract` modifier handling\n- Enum constant modifiers and initialization\n\n### Collection Framework Integration\n\n**Collections:**\n\n- Generic collection types (e.g., `List<String>`, `Map<String,Integer>`)\n- Collection instantiation with type inference\n- Iterator and collection method support\n\n### Error Handling and Diagnostics\n\n**Error Types:**\n\n- `ErrorExpr` - Error expressions for malformed code\n- `ErrorType` - Error types for type resolution failures\n- Error handling in generic contexts\n\n### Example AST Hierarchy\n\nA typical Java method declaration produces the following AST node hierarchy:\n\n```text\nCompilationUnit\n \u2514\u2500\u2500 ClassDecl\n \u251C\u2500\u2500 FieldDecl\n \u2502 \u251C\u2500\u2500 TypeAccess\n \u2502 \u2514\u2500\u2500 VarDeclExpr\n \u251C\u2500\u2500 MethodDecl\n \u2502 \u251C\u2500\u2500 TypeAccess (return type)\n \u2502 \u251C\u2500\u2500 Parameter\n \u2502 \u2502 \u2514\u2500\u2500 TypeAccess\n \u2502 \u2514\u2500\u2500 Block\n \u2502 \u251C\u2500\u2500 ExprStmt\n \u2502 \u2502 \u2514\u2500\u2500 MethodCall\n \u2502 \u2502 \u251C\u2500\u2500 VarAccess\n \u2502 \u2502 \u2514\u2500\u2500 StringLiteral\n \u2502 \u2514\u2500\u2500 ReturnStmt\n \u2502 \u2514\u2500\u2500 VarAccess\n \u2514\u2500\u2500 ConstructorDecl\n \u2514\u2500\u2500 Block\n```\n\nUse `PrintAST` on your test code to see the exact hierarchy for your specific source patterns.\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `java` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="java"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `java` language:\n\n- [library-tests/comments/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/comments/PrintAst.expected)\n- [library-tests/dependency-counts/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/dependency-counts/PrintAst.expected)\n- [library-tests/generics/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/generics/PrintAst.expected)\n- [library-tests/java7/Diamond/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/java7/Diamond/PrintAst.expected)\n- [library-tests/java7/MultiCatch/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected)\n- [library-tests/modifiers/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/modifiers/PrintAst.expected)\n- [library-tests/guards12/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/guards12/PrintAst.expected)\n- [library-tests/pattern-instanceof/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/pattern-instanceof/PrintAst.expected)\n- [library-tests/typeaccesses/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/typeaccesses/PrintAst.expected)\n- [library-tests/JDK/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/JDK/PrintAst.expected)\n- [library-tests/constants/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/constants/PrintAst.expected)\n- [library-tests/errortype/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/errortype/PrintAst.expected)\n- [library-tests/comment-encoding/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/comment-encoding/PrintAst.expected)\n- [library-tests/dependency/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/dependency/PrintAst.expected)\n- [library-tests/errortype-with-params/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/errortype-with-params/PrintAst.expected)\n- [library-tests/printAst/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/printAst/PrintAst.expected)\n- [library-tests/constructors/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/constructors/PrintAst.expected)\n- [library-tests/arrays/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/arrays/PrintAst.expected)\n- [library-tests/errorexpr/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/errorexpr/PrintAst.expected)\n- [library-tests/fields/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/fields/PrintAst.expected)\n- [library-tests/javadoc/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/javadoc/PrintAst.expected)\n- [library-tests/collections/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/collections/PrintAst.expected)\n- [library-tests/varargs/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/varargs/PrintAst.expected)\n- [library-tests/reflection/PrintAst.expected](https://github.com/github/codeql/blob/main/java/ql/test/library-tests/reflection/PrintAst.expected)\n';
64120
+
64121
+ // src/resources/languages/javascript_ast.md
64122
+ var javascript_ast_default = '# CodeQL AST nodes for `javascript` language\n\n## CodeQL\'s core AST classes for `javascript` language\n\nBased on comprehensive analysis of CodeQL\'s JavaScript test results from GitHub, here are the core AST classes for JavaScript/TypeScript analysis:\n\n### Core Expression Classes\n\n**Primary Expressions:**\n\n- `Literal` - String, number, boolean, null literals (e.g., `"hello"`, `42`, `true`, `null`)\n- `VarRef` - Variable references (e.g., `x`, `myVar`)\n- `ThisExpr` - The `this` keyword\n- `ArrayExpr` - Array literals (e.g., `[1, 2, 3]`, `["source"]`)\n- `ObjectExpr` - Object literals with properties (e.g., `{rel: "noopener"}`)\n\n**Function and Call Expressions:**\n\n- `FunctionExpr` - Function expressions and arrow functions\n- `ArrowFunctionExpr` - Arrow function expressions (e.g., `(x) => x`, `() => true`)\n- `CallExpr` - Function calls (e.g., `func()`, `getResource()`)\n- `MethodCallExpr` - Method calls (e.g., `console.log()`, `arr.push()`)\n- `NewExpr` - Constructor calls (e.g., `new Date()`, `new C3<number>()`)\n\n**Access and Member Expressions:**\n\n- `DotExpr` - Property access (e.g., `obj.prop`, `console.log`, `arr.length`)\n- `IndexExpr` - Array/object indexing (e.g., `arr[0]`, `props["a:b"]`)\n- `SpreadElement` - Spread syntax (e.g., `...arr`, `...linkTypes`)\n\n**Operators and Assignments:**\n\n- `BinaryExpr` - Binary operations (e.g., `x + y`, `i < arr.length`, `typeof val !== "string"`)\n- `UnaryExpr` - Unary operations (e.g., `!condition`, `typeof val`, `++i`)\n- `AssignExpr` - Assignment expressions (e.g., `x = 5`, `test = 20`)\n- `CompoundAssignExpr` - Compound assignments (e.g., `a2 &&= a3`)\n- `UpdateExpr` - Increment/decrement (e.g., `i++`, `--count`)\n\n### Statement Classes\n\n**Declaration Statements:**\n\n- `DeclStmt` - Variable declarations (e.g., `var x = 5`, `const arr = []`)\n- `VariableDeclarator` - Individual variable declarators within declarations\n- `VarDecl` - Variable declaration identifiers\n- `FunctionDeclStmt` - Function declarations\n- `ClassDefinition` - Class declarations with constructors and methods\n\n**Control Flow Statements:**\n\n- `IfStmt` - Conditional statements with test expressions and blocks\n- `ForStmt` - For loops with initialization, condition, and update\n- `ForOfStmt` - For-of loops for iterating arrays and iterables\n- `WhileStmt` - While loops\n- `BlockStmt` - Block statements containing multiple statements\n- `ReturnStmt` - Return statements with optional expressions\n- `BreakStmt` - Break statements for loop control\n- `ContinueStmt` - Continue statements\n- `ThrowStmt` - Throw statements for error handling\n\n**Expression Statements:**\n\n- `ExprStmt` - Expression statements wrapping expressions\n\n### Modern JavaScript Features\n\n**ES6+ and Modern Syntax:**\n\n- `TemplateString` - Template literals with interpolation\n- `TaggedTemplateExpr` - Tagged template literals\n- `ParenthesizedExpr` - Parenthesized expressions\n- `ConditionalExpr` - Ternary conditional expressions\n\n**Resource Management (Modern):**\n\n- `ExplicitResource` - Using declarations for resource management (e.g., `using stream = getResource()`)\n- Resource management in async contexts and for loops\n\n### TypeScript-Specific AST Classes\n\n**Type Annotations:**\n\n- `KeywordTypeExpr` - Built-in types (e.g., `string`, `number`, `boolean`, `any`, `void`)\n- `ArrayTypeExpr` - Array types (e.g., `string[]`, `number[][]`)\n- `UnionTypeExpr` - Union types (e.g., `string | number | boolean`)\n- `IntersectionTypeExpr` - Intersection types (e.g., `string & number & boolean`)\n- `TupleTypeExpr` - Tuple types (e.g., `[number, string, boolean]`, `[...T, ...U]`)\n- `ParenthesizedTypeExpr` - Parenthesized types (e.g., `(string)`, `(boolean | string)`)\n\n**Advanced Types:**\n\n- `GenericTypeExpr` - Generic types (e.g., `Generic<number>`, `Generic<Leaf[]>`)\n- `LocalTypeAccess` - Local type references (e.g., `Interface`, `Generic`, `Leaf`)\n- `FunctionTypeExpr` - Function types (e.g., `() => number`, `new () => Object`)\n- `TypeofTypeExpr` - Typeof types (e.g., `typeof x`)\n- `IsTypeExpr` - Type predicate expressions (e.g., `x is Generic<Leaf[]>`, `this is Leaf`)\n- `PredicateTypeExpr` - Assertion signatures (e.g., `asserts condition`)\n- `RestTypeExpr` - Rest types in tuples (e.g., `...T`, `...number[]`)\n\n**Type Declarations:**\n\n- `TypeDefinition` - Type definitions and interfaces\n- `InterfaceDeclaration` - Interface declarations with properties\n- `TypeParameter` - Generic type parameters (e.g., `T`, `S extends number`)\n- `FieldDeclaration` - Interface/class field declarations\n\n**Type Access:**\n\n- `LocalVarTypeAccess` - Local variable type access (e.g., `x` in type position)\n- `ThisVarTypeAccess` - This type access (e.g., `this` in type predicates)\n\n### JSX Classes (React Support)\n\n**JSX Elements:**\n\n- `JsxElement` - JSX elements (e.g., `<div>`, `<MyComponent>`, `<Foo/>`)\n- `JsxFragment` - JSX fragments (e.g., `<>...</>`)\n- `JsxAttribute` - JSX attributes (e.g., `href={href}`, `target="_blank"`)\n- `JsxEmptyExpr` - Empty JSX expressions (e.g., `{/* comment */}`)\n\n**JSX Structure:**\n\n- JSX elements support attributes, spread attributes, and nested content\n- Namespaced attributes (e.g., `a:b="hello"`)\n- Component references and dot notation (e.g., `MyComponents.FancyLink`)\n\n### Decorator Support\n\n**Decorator Classes:**\n\n- `Decorator` - Decorator expressions (e.g., `@Dec()`)\n- Decorators on classes, methods, and properties\n- Support for decorator factories and complex decorator expressions\n\n### Pattern Matching\n\n**Destructuring Patterns:**\n\n- `ObjectPattern` - Object destructuring patterns\n- `ArrayPattern` - Array destructuring patterns\n- `PropertyPattern` - Property patterns in object destructuring\n- `RestElement` - Rest elements in destructuring\n\n### Array Methods and Operations\n\n**Array-Specific AST:**\n\n- Comprehensive support for array methods: `forEach`, `map`, `filter`, `find`, `findLast`, `findLastIndex`\n- Array method chaining with proper AST representation\n- Spread operations in arrays and function calls\n- Array manipulation methods: `push`, `pop`, `slice`, `splice`, `toSpliced`\n\n### Class and OOP Features\n\n**Class Components:**\n\n- `ClassInitializedMember` - Class members (methods, constructors)\n- `ConstructorDefinition` - Class constructors\n- `MethodDefinition` - Class methods\n- `FieldDeclaration` - Class fields and properties\n\n### Parameter Handling\n\n**Parameter Types:**\n\n- `SimpleParameter` - Simple function parameters\n- `Parameter` - General parameter interface\n- `RestParameter` - Rest parameters (e.g., `...args`)\n\n### Utility and Meta Classes\n\n**Labels and References:**\n\n- `Label` - Property names, method names, and identifiers\n- `Identifier` - General identifiers in various contexts\n\n**Parser Infrastructure:**\n\n- `Arguments` - Function call arguments container\n- `Parameters` - Function parameter container\n- `Body` - Statement body container\n- `Attributes` - JSX attributes container\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `javascript` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="javascript"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `javascript` language:\n\n- [library-tests/RegExp/VFlagOperations/QuotedString/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/RegExp/VFlagOperations/QuotedString/printAst.expected)\n- [library-tests/RegExp/VFlagOperations/Subtraction/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/RegExp/VFlagOperations/Subtraction/printAst.expected)\n- [library-tests/RegExp/VFlagOperations/CombinationOfOperators/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/RegExp/VFlagOperations/CombinationOfOperators/printAst.expected)\n- [library-tests/RegExp/VFlagOperations/Intersection/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/RegExp/VFlagOperations/Intersection/printAst.expected)\n- [library-tests/TypeScript/TypeAnnotations/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/printAst.expected)\n- [library-tests/HTML/HTMLElementAndHTMLAttribute/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/HTML/HTMLElementAndHTMLAttribute/printAst.expected)\n- [library-tests/JSON/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/JSON/printAst.expected)\n- [library-tests/Arrays/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/Arrays/printAst.expected)\n- [library-tests/AST/Decorators/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/AST/Decorators/printAst.expected)\n- [library-tests/AST/ExplicitResource/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/AST/ExplicitResource/printAst.expected)\n- [library-tests/YAML/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/YAML/printAst.expected)\n- [library-tests/frameworks/AngularJS/expressions/parsing/AstNodes.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/parsing/AstNodes.expected)\n- [library-tests/JSX/printAst.expected](https://github.com/github/codeql/blob/main/javascript/ql/test/library-tests/JSX/printAst.expected)\n';
64123
+
64124
+ // src/resources/languages/javascript_security_query_guide.md
64125
+ var javascript_security_query_guide_default = "# JavaScript Security Query Guide\n\nLanguage-specific notes for writing JavaScript/TypeScript security queries in CodeQL. For the general taint-tracking template and workflow, see the `security_templates` resource.\n\n## Imports\n\n```ql\nimport javascript\n```\n\nThe `javascript` top-level import re-exports data flow, taint tracking, and framework models. For path-problem queries add `import MyFlow::PathGraph` after defining your flow module.\n\n## Sources and Sinks\n\n- **Sources**: Use `RemoteFlowSource` (covers Express, Koa, Hapi, Fastify, and other HTTP frameworks automatically).\n- **Sinks**: Use or extend existing sink classes from `semmle.javascript.security.dataflow.*` (e.g., `DomBasedXss`, `SqlInjection`, `ServerSideUrlRedirect`), or model custom sinks as `DataFlow::Node` subclasses.\n- **Sanitizers**: Extend `Sanitizer` classes in the relevant `semmle.javascript.security.dataflow.*` module.\n\n## Key Library Modules\n\n| Module | Purpose |\n| ------------------------------------------ | ---------------------------------------- |\n| `semmle.javascript.dataflow.DataFlow` | Data flow nodes and global analysis |\n| `semmle.javascript.dataflow.TaintTracking` | Taint tracking analysis |\n| `semmle.javascript.security.dataflow.*` | Pre-built vulnerability-specific configs |\n| `semmle.javascript.frameworks.*` | Framework-specific API models |\n";
64126
+
64127
+ // src/resources/languages/python_ast.md
64128
+ var python_ast_default = '# CodeQL AST nodes for `python` language\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `python` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="python"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## CodeQL\'s core AST classes for `python` language\n\n### Expression Types\n\n- **`Call`** - Function/method calls (e.g., `func(args)`)\n- **`Attribute`** - Attribute access (e.g., `obj.attr`, `module.function`)\n- **`Subscript`** - Subscript operations (e.g., `obj[key]`, `list[0]`)\n- **`Name`** - Variable references and identifiers\n- **`StringLiteral`** - String literals (e.g., `"hello"`, `\'world\'`)\n- **`Bytes`** - Byte string literals\n- **`List`** - List literals (e.g., `[1, 2, 3]`)\n- **`Dict`** - Dictionary literals (e.g., `{"key": "value"}`)\n- **`KeyValuePair`** - Key-value pairs in dictionaries\n- **`BinOp`** - Binary operations (e.g., `+`, `-`, `*`)\n- **`UnaryExpr`** - Unary expressions (e.g., `not`, `-`)\n\n### Statement Types\n\n- **`FunctionDef`** - Function definitions\n- **`FunctionExpr`** - Function expressions\n- **`Function`** - Function objects\n- **`ClassDef`** - Class definitions\n- **`ClassExpr`** - Class expressions\n- **`Class`** - Class objects\n- **`Import`** - Import statements (`import module`)\n- **`ImportFrom`** - From-import statements (`from module import name`)\n- **`ImportExpr`** - Import expressions\n- **`Assign`** - Assignment statements (e.g., `x = y`)\n- **`AssignStmt`** - Assignment statement nodes\n- **`If`** - Conditional statements\n- **`For`** - For loop statements\n- **`While`** - While loop statements\n- **`Return`** - Return statements\n- **`ExprStmt`** - Expression statements\n- **`Pass`** - Pass statements\n\n### Parameters and Arguments\n\n- **`Parameter`** - Function parameters\n- **`arguments`** - Function argument lists\n- **`parameters`** - Function parameter lists\n\n### Control Flow\n\n- **`StmtList`** - Statement lists (body, orelse)\n- **`body`** - Statement body containers\n- **`orelse`** - Else clause containers\n\n### YAML Support (for configuration files)\n\n- **`YamlScalar`** - YAML scalar values\n- **`YamlMapping`** - YAML mapping/dictionary structures\n- **`YamlSequence`** - YAML sequence/list structures\n- **`YamlAliasNode`** - YAML alias references\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `python` language:\n\n- [github-codeql:python/ql/test/library-tests/taint/general/printAst.expected](https://github.com/github/codeql/blob/main/python/ql/test/library-tests/taint/general/printAst.expected)\n- [github-codeql:python/ql/test/library-tests/Yaml/printAst.expected](https://github.com/github/codeql/blob/main/python/ql/test/library-tests/Yaml/printAst.expected)\n';
64129
+
64130
+ // src/resources/languages/python_security_query_guide.md
64131
+ var python_security_query_guide_default = '# Python Security Query Guide\n\nLanguage-specific notes for writing Python security queries in CodeQL. For the general taint-tracking template and workflow, see the `security_templates` resource.\n\n## Imports\n\n```ql\nimport python\nimport semmle.python.dataflow.new.DataFlow\nimport semmle.python.dataflow.new.TaintTracking\nimport semmle.python.Concepts\nimport semmle.python.ApiGraphs\n```\n\nFor path-problem queries add `import MyFlow::PathGraph` after defining your flow module.\n\n## Sources and Sinks\n\n- **Sources**: Use `RemoteFlowSource` from `semmle.python.dataflow.new.RemoteFlowSources` (covers Flask, Django, FastAPI, and other HTTP frameworks).\n- **Sinks**: Use the `Concepts` module (e.g., `SqlExecution`, `SystemCommandExecution`, `FileSystemAccess`) or model custom sinks as `DataFlow::Node` subclasses.\n- **Barriers**: Use `semmle.python.dataflow.new.BarrierGuards` for common sanitizer patterns.\n\n## ApiGraph Navigation (Framework Modeling)\n\nUse `API::moduleImport("pkg")` to get a reference to an imported module, then chain `.getMember()`, `.getACall()`, `.getReturn()`, `.getParameter()`, and `.getASubclass()` to navigate the API surface. Convert to data flow nodes via `.asSource()` / `.asSink()`.\n\n## Key Library Modules\n\n| Module | Purpose |\n| ---------------------------------------------- | ------------------------------------------- |\n| `semmle.python.dataflow.new.DataFlow` | Data flow nodes and global analysis |\n| `semmle.python.dataflow.new.TaintTracking` | Taint tracking analysis |\n| `semmle.python.Concepts` | Abstract security concepts (sinks) |\n| `semmle.python.ApiGraphs` | API-graph navigation for framework modeling |\n| `semmle.python.dataflow.new.RemoteFlowSources` | Remote flow source definitions |\n';
64132
+
64133
+ // src/resources/languages/ruby_ast.md
64134
+ var ruby_ast_default = '# CodeQL AST nodes for `ruby` language\n\n## CodeQL\'s core AST classes for `ruby` language\n\nBased on comprehensive analysis of GitHub CodeQL Ruby AST test results\n\n### Expression Types\n\n#### Literal Expressions\n\n- **IntegerLiteral**: Numeric constants (1, 2, 100, -5)\n- **StringLiteral**: String constants with StringTextComponent and StringEscapeSequenceComponent\n- **BooleanLiteral**: true/false values\n- **NilLiteral**: nil value\n- **SymbolLiteral**: :foo, :"foo bar" symbols with StringTextComponent\n- **ArrayLiteral**: [1, 2, 3] arrays (desugared to Array.[])\n- **HashLiteral**: {:foo => 1} hashes (desugared to Hash.[])\n- **RegExpLiteral**: /foo.\\*/ regular expressions with RegExpSequence, RegExpConstant, RegExpStar, RegExpDot\n- **RangeLiteral**: 1..10, 1...10 ranges with getBegin/getEnd\n- **HereDoc**: <<SQL heredoc strings\n\n#### Variable Access\n\n- **LocalVariableAccess**: Local variable references\n- **InstanceVariableAccess**: @instance_var with getReceiver\n- **ClassVariableAccess**: @@class_var\n- **GlobalVariableAccess**: $global_var\n- **SelfVariableAccess**: self references\n\n#### Constant Access\n\n- **ConstantReadAccess**: Reading constants with optional getScopeExpr\n- **ConstantAssignment**: Assigning to constants with optional getScopeExpr\n\n#### Method and Call Expressions\n\n- **MethodCall**: Method invocations with getReceiver, getArgument, getBlock\n- **SetterMethodCall**: Setter method calls (foo=)\n- **SuperCall**: super calls with getArgument, getBlock\n\n#### Binary Operations\n\n- **AddExpr**: + addition\n- **SubExpr**: - subtraction\n- **MulExpr**: \\* multiplication\n- **DivExpr**: / division\n- **ModExpr**: % modulo\n- **PowerExpr**: \\*\\* exponentiation\n- **EqExpr**: == equality\n- **NeExpr**: != inequality\n- **LTExpr**: < less than\n- **LEExpr**: <= less than or equal\n- **GTExpr**: > greater than\n- **GEExpr**: >= greater than or equal\n- **SpaceshipExpr**: <=> spaceship operator\n- **RegExpMatchExpr**: =~ regex match\n- **NoRegExpMatchExpr**: !~ regex no match\n\n#### Logical Operations\n\n- **LogicalAndExpr**: && and \'and\'\n- **LogicalOrExpr**: || and \'or\'\n- **NotExpr**: ! negation\n\n#### Bitwise Operations\n\n- **BitwiseAndExpr**: & bitwise and\n- **BitwiseOrExpr**: | bitwise or\n- **BitwiseXorExpr**: ^ bitwise xor\n- **LeftShiftExpr**: << left shift\n- **RightShiftExpr**: >> right shift\n\n#### Unary Operations\n\n- **UnaryMinusExpr**: -value\n- **UnaryPlusExpr**: +value\n- **ComplementExpr**: ~value\n\n#### Assignment Operations\n\n- **AssignExpr**: = assignment\n- **AssignAddExpr**: += (desugared to = and +)\n- **AssignSubExpr**: -= (desugared to = and -)\n- **AssignMulExpr**: _= (desugared to = and _)\n- **AssignDivExpr**: /= (desugared to = and /)\n- **AssignModExpr**: %= (desugared to = and %)\n- **AssignPowerExpr**: **= (desugared to = and **)\n- **AssignLogicalAndExpr**: &&= (desugared to = and &&)\n- **AssignLogicalOrExpr**: ||= (desugared to = and ||)\n- **AssignBitwiseAndExpr**: &= (desugared to = and &)\n- **AssignBitwiseOrExpr**: |= (desugared to = and |)\n- **AssignBitwiseXorExpr**: ^= (desugared to = and ^)\n- **AssignLeftShiftExpr**: <<= (desugared to = and <<)\n- **AssignRightShiftExpr**: >>= (desugared to = and >>)\n\n#### Special Expressions\n\n- **TernaryIfExpr**: condition ? true_val : false_val\n- **SplatExpr**: \\*args splat operator\n- **HashSplatExpr**: \\*\\*kwargs hash splat\n- **DefinedExpr**: defined? operator\n- **DestructuredLhsExpr**: (a, b, c) destructuring assignment left side\n\n### Statement Types\n\n#### Method Definitions\n\n- **Method**: Regular method definitions with getParameter, getStmt\n- **SingletonMethod**: Class method definitions with getObject\n\n#### Class and Module Definitions\n\n- **ClassDeclaration**: Class definitions with optional getSuperclassExpr\n- **ModuleDeclaration**: Module definitions\n\n#### Control Flow Statements\n\n- **IfExpr**: if/elsif/else conditionals with getCondition, getThen, getElse\n- **UnlessExpr**: unless conditionals with getCondition, getThen, getElse\n- **IfModifierExpr**: statement if condition\n- **UnlessModifierExpr**: statement unless condition\n- **CaseExpr**: case statements with getValue, getBranch\n- **WhenClause**: when branches with getPattern, getBody\n- **InClause**: in pattern matching with getPattern, getCondition, getBody\n\n#### Loop Statements\n\n- **WhileExpr**: while loops with getCondition, getBody\n- **WhileModifierExpr**: statement while condition\n- **UntilExpr**: until loops with getCondition, getBody\n- **UntilModifierExpr**: statement until condition\n- **ForExpr**: for loops (desugared to each with blocks)\n\n#### Flow Control\n\n- **NextStmt**: next statement\n- **BreakStmt**: break statement\n- **ReturnStmt**: return statement\n- **RedoStmt**: redo statement\n- **RetryStmt**: retry statement\n\n#### Block Statements\n\n- **BeginExpr**: begin/rescue/ensure/end blocks\n- **RescueClause**: rescue clauses\n- **EnsureClause**: ensure clauses\n- **EndBlock**: END {} blocks\n\n#### Utility Statements\n\n- **UndefStmt**: undef method_name\n- **AliasStmt**: alias new_name old_name\n- **StmtSequence**: Statement sequences\n\n### Parameters\n\n#### Basic Parameters\n\n- **SimpleParameter**: Regular parameters with getDefiningAccess\n- **OptionalParameter**: Parameters with default values, getDefaultValue\n- **KeywordParameter**: Keyword parameters with optional getDefaultValue\n- **SplatParameter**: \\*args parameters with getDefiningAccess\n- **HashSplatParameter**: \\*\\*kwargs parameters with getDefiningAccess\n- **HashSplatNilParameter**: \\*\\*nil parameters\n- **BlockParameter**: &block parameters with getDefiningAccess\n- **DestructuredParameter**: (a, b) destructured parameters with getElement\n\n### Control Flow\n\n#### Conditional Expressions\n\n- **IfExpr**: Complete if/elsif/else with getBranch structure\n- **UnlessExpr**: unless statements with conditional logic\n- **CaseExpr**: case/when/else with pattern matching\n- **TernaryIfExpr**: Inline conditional expressions\n\n#### Loop Constructs\n\n- **WhileExpr**: while condition do body end\n- **UntilExpr**: until condition do body end\n- **ForExpr**: for var in collection (desugared to each)\n\n#### Block Constructs\n\n- **DoBlock**: do |params| body end blocks\n- **BraceBlock**: { |params| body } blocks\n- **Lambda**: -> { } and lambda { } constructs\n\n#### Pattern Matching\n\n- **ArrayPattern**: [a, b, *rest] array patterns\n- **AlternativePattern**: pattern1 | pattern2\n- **AsPattern**: pattern => variable\n- **CapturePattern**: Variable capture patterns\n\n#### Exception Handling\n\n- **BeginExpr**: begin/rescue/ensure structure\n- **RescueClause**: Exception rescue clauses\n- **EnsureClause**: Cleanup ensure clauses\n\n### Method Names and Identifiers\n\n- **MethodName**: Method name identifiers in various contexts\n- **Toplevel**: Top-level program scope\n\n## Expected test results for local `PrintAst.ql` query\n\nThis repo contains a variant of the open-source `PrintAst.ql` query for `ruby` language, with modifications for local testing:\n\n- Use the `codeql_query_run` tool with `queryName="PrintAST"` and `language="ruby"` to run the bundled PrintAST query\n- Use the `codeql_test_run` tool to run the PrintAST test and compare against expected results\n\n## Expected test results for open-source `PrintAst.ql` query\n\nThe following links can be fetched to get the expected results for different unit tests of the open-source `PrintAst.ql` query for the `ruby` language:\n\n- https://github.com/github/codeql/blob/main/ruby/ql/test/library-tests/ast/Ast.expected\n- https://github.com/github/codeql/blob/main/ruby/ql/test/library-tests/ast/AstDesugar.expected\n';
63257
64135
 
63258
64136
  // src/types/language-types.ts
63259
64137
  var LANGUAGE_RESOURCES = [
63260
64138
  {
63261
64139
  language: "actions",
63262
- astFile: "ql/languages/actions/tools/dev/actions_ast.prompt.md"
64140
+ astContent: actions_ast_default
63263
64141
  },
63264
64142
  {
63265
64143
  language: "cpp",
63266
- astFile: "ql/languages/cpp/tools/dev/cpp_ast.prompt.md",
63267
- securityFile: "ql/languages/cpp/tools/dev/cpp_security_query_guide.prompt.md"
64144
+ astContent: cpp_ast_default,
64145
+ securityContent: cpp_security_query_guide_default
63268
64146
  },
63269
64147
  {
63270
64148
  language: "csharp",
63271
- astFile: "ql/languages/csharp/tools/dev/csharp_ast.prompt.md",
63272
- securityFile: "ql/languages/csharp/tools/dev/csharp_security_query_guide.prompt.md"
64149
+ astContent: csharp_ast_default,
64150
+ securityContent: csharp_security_query_guide_default
63273
64151
  },
63274
64152
  {
63275
64153
  language: "go",
63276
- astFile: "ql/languages/go/tools/dev/go_ast.prompt.md",
63277
- securityFile: "ql/languages/go/tools/dev/go_security_query_guide.prompt.md",
63278
- additionalFiles: {
63279
- "dataflow": "ql/languages/go/tools/dev/go_dataflow.prompt.md",
63280
- "library-modeling": "ql/languages/go/tools/dev/go_library_modeling.prompt.md",
63281
- "basic-queries": "ql/languages/go/tools/dev/go_basic_queries.prompt.md"
64154
+ astContent: go_ast_default,
64155
+ securityContent: go_security_query_guide_default,
64156
+ additionalResources: {
64157
+ "basic-queries": go_basic_queries_default,
64158
+ "dataflow": go_dataflow_default,
64159
+ "library-modeling": go_library_modeling_default
63282
64160
  }
63283
64161
  },
63284
64162
  {
63285
64163
  language: "java",
63286
- astFile: "ql/languages/java/tools/dev/java_ast.prompt.md"
64164
+ astContent: java_ast_default
63287
64165
  },
63288
64166
  {
63289
64167
  language: "javascript",
63290
- astFile: "ql/languages/javascript/tools/dev/javascript_ast.prompt.md",
63291
- securityFile: "ql/languages/javascript/tools/dev/javascript_security_query_guide.prompt.md"
64168
+ astContent: javascript_ast_default,
64169
+ securityContent: javascript_security_query_guide_default
63292
64170
  },
63293
64171
  {
63294
64172
  language: "python",
63295
- astFile: "ql/languages/python/tools/dev/python_ast.prompt.md",
63296
- securityFile: "ql/languages/python/tools/dev/python_security_query_guide.prompt.md"
63297
- },
63298
- {
63299
- language: "ql",
63300
- astFile: "ql/languages/ql/tools/dev/ql_ast.prompt.md"
64173
+ astContent: python_ast_default,
64174
+ securityContent: python_security_query_guide_default
63301
64175
  },
63302
64176
  {
63303
64177
  language: "ruby",
63304
- astFile: "ql/languages/ruby/tools/dev/ruby_ast.prompt.md"
64178
+ astContent: ruby_ast_default
63305
64179
  }
63306
64180
  ];
63307
64181
 
63308
64182
  // src/resources/language-resources.ts
63309
- init_package_paths();
63310
64183
  init_logger();
63311
- function getQLBasePath() {
63312
- return workspaceRootDir;
63313
- }
63314
- function loadResourceContent(relativePath) {
63315
- try {
63316
- const fullPath = join17(getQLBasePath(), relativePath);
63317
- if (!existsSync12(fullPath)) {
63318
- logger.warn(`Resource file not found: ${fullPath}`);
63319
- return null;
63320
- }
63321
- return readFileSync11(fullPath, "utf-8");
63322
- } catch (error2) {
63323
- logger.error(`Error loading resource file ${relativePath}:`, error2);
63324
- return null;
63325
- }
63326
- }
63327
64184
  function registerLanguageASTResources(server) {
63328
64185
  for (const langResource of LANGUAGE_RESOURCES) {
63329
- if (!langResource.astFile) continue;
64186
+ if (!langResource.astContent) continue;
63330
64187
  const resourceUri = `codeql://languages/${langResource.language}/ast`;
64188
+ const content = langResource.astContent;
63331
64189
  server.resource(
63332
64190
  `${langResource.language.toUpperCase()} AST Reference`,
63333
64191
  resourceUri,
@@ -63335,34 +64193,21 @@ function registerLanguageASTResources(server) {
63335
64193
  description: `CodeQL AST class reference for ${langResource.language} programs`,
63336
64194
  mimeType: "text/markdown"
63337
64195
  },
63338
- async () => {
63339
- const content = loadResourceContent(langResource.astFile);
63340
- if (!content) {
63341
- return {
63342
- contents: [{
63343
- uri: resourceUri,
63344
- mimeType: "text/markdown",
63345
- text: `# ${langResource.language.toUpperCase()} AST Reference
63346
-
63347
- Resource file not found or could not be loaded.`
63348
- }]
63349
- };
63350
- }
63351
- return {
63352
- contents: [{
63353
- uri: resourceUri,
63354
- mimeType: "text/markdown",
63355
- text: content
63356
- }]
63357
- };
63358
- }
64196
+ async () => ({
64197
+ contents: [{
64198
+ uri: resourceUri,
64199
+ mimeType: "text/markdown",
64200
+ text: content
64201
+ }]
64202
+ })
63359
64203
  );
63360
64204
  }
63361
64205
  }
63362
64206
  function registerLanguageSecurityResources(server) {
63363
64207
  for (const langResource of LANGUAGE_RESOURCES) {
63364
- if (!langResource.securityFile) continue;
64208
+ if (!langResource.securityContent) continue;
63365
64209
  const resourceUri = `codeql://languages/${langResource.language}/security`;
64210
+ const content = langResource.securityContent;
63366
64211
  server.resource(
63367
64212
  `${langResource.language.toUpperCase()} Security Patterns`,
63368
64213
  resourceUri,
@@ -63370,34 +64215,20 @@ function registerLanguageSecurityResources(server) {
63370
64215
  description: `CodeQL security query patterns and framework modeling for ${langResource.language}`,
63371
64216
  mimeType: "text/markdown"
63372
64217
  },
63373
- async () => {
63374
- const content = loadResourceContent(langResource.securityFile);
63375
- if (!content) {
63376
- return {
63377
- contents: [{
63378
- uri: resourceUri,
63379
- mimeType: "text/markdown",
63380
- text: `# ${langResource.language.toUpperCase()} Security Patterns
63381
-
63382
- Resource file not found or could not be loaded.`
63383
- }]
63384
- };
63385
- }
63386
- return {
63387
- contents: [{
63388
- uri: resourceUri,
63389
- mimeType: "text/markdown",
63390
- text: content
63391
- }]
63392
- };
63393
- }
64218
+ async () => ({
64219
+ contents: [{
64220
+ uri: resourceUri,
64221
+ mimeType: "text/markdown",
64222
+ text: content
64223
+ }]
64224
+ })
63394
64225
  );
63395
64226
  }
63396
64227
  }
63397
64228
  function registerLanguageAdditionalResources(server) {
63398
64229
  for (const langResource of LANGUAGE_RESOURCES) {
63399
- if (!langResource.additionalFiles) continue;
63400
- for (const [resourceType, filePath] of Object.entries(langResource.additionalFiles)) {
64230
+ if (!langResource.additionalResources) continue;
64231
+ for (const [resourceType, content] of Object.entries(langResource.additionalResources)) {
63401
64232
  const resourceUri = `codeql://languages/${langResource.language}/${resourceType}`;
63402
64233
  server.resource(
63403
64234
  `${langResource.language.toUpperCase()} ${resourceType.replace("-", " ").replace(/\b\w/g, (l) => l.toUpperCase())}`,
@@ -63406,27 +64237,13 @@ function registerLanguageAdditionalResources(server) {
63406
64237
  description: `CodeQL ${resourceType.replace("-", " ")} guide for ${langResource.language}`,
63407
64238
  mimeType: "text/markdown"
63408
64239
  },
63409
- async () => {
63410
- const content = loadResourceContent(filePath);
63411
- if (!content) {
63412
- return {
63413
- contents: [{
63414
- uri: resourceUri,
63415
- mimeType: "text/markdown",
63416
- text: `# ${langResource.language.toUpperCase()} ${resourceType.replace("-", " ").replace(/\b\w/g, (l) => l.toUpperCase())}
63417
-
63418
- Resource file not found or could not be loaded.`
63419
- }]
63420
- };
63421
- }
63422
- return {
63423
- contents: [{
63424
- uri: resourceUri,
63425
- mimeType: "text/markdown",
63426
- text: content
63427
- }]
63428
- };
63429
- }
64240
+ async () => ({
64241
+ contents: [{
64242
+ uri: resourceUri,
64243
+ mimeType: "text/markdown",
64244
+ text: content
64245
+ }]
64246
+ })
63430
64247
  );
63431
64248
  }
63432
64249
  }
@@ -63440,22 +64257,22 @@ function registerLanguageResources(server) {
63440
64257
  }
63441
64258
 
63442
64259
  // src/prompts/workflow-prompts.ts
63443
- import { basename as basename6 } from "path";
64260
+ import { basename as basename7 } from "path";
63444
64261
 
63445
64262
  // src/prompts/document-codeql-query.prompt.md
63446
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';
63447
64264
 
63448
64265
  // src/prompts/explain-codeql-query.prompt.md
63449
- 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';
63450
64267
 
63451
64268
  // src/prompts/ql-lsp-iterative-development.prompt.md
63452
- 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';
63453
64270
 
63454
64271
  // src/prompts/ql-tdd-advanced.prompt.md
63455
- 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';
63456
64273
 
63457
64274
  // src/prompts/ql-tdd-basic.prompt.md
63458
- 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';
63459
64276
 
63460
64277
  // src/prompts/run-query-and-summarize-false-positives.prompt.md
63461
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';
@@ -63467,7 +64284,7 @@ var sarif_rank_false_positives_prompt_default = '---\nagent: agent\n---\n\n# Eva
63467
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';
63468
64285
 
63469
64286
  // src/prompts/tools-query-workflow.prompt.md
63470
- 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';
63471
64288
 
63472
64289
  // src/prompts/workshop-creation-workflow.prompt.md
63473
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';
@@ -63650,7 +64467,7 @@ ${content}`
63650
64467
  workshopCreationWorkflowSchema.shape,
63651
64468
  async ({ queryPath, language, workshopName, numStages }) => {
63652
64469
  const template = loadPromptTemplate("workshop-creation-workflow.prompt.md");
63653
- 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";
63654
64471
  const contextSection = buildWorkshopContext(
63655
64472
  queryPath,
63656
64473
  language,
@@ -64010,7 +64827,7 @@ var Low = class {
64010
64827
  };
64011
64828
 
64012
64829
  // ../node_modules/lowdb/lib/adapters/node/TextFile.js
64013
- import { readFileSync as readFileSync12, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
64830
+ import { readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
64014
64831
  import path3 from "node:path";
64015
64832
  var TextFileSync = class {
64016
64833
  #tempFilename;
@@ -64023,7 +64840,7 @@ var TextFileSync = class {
64023
64840
  read() {
64024
64841
  let data;
64025
64842
  try {
64026
- data = readFileSync12(this.#filename, "utf-8");
64843
+ data = readFileSync10(this.#filename, "utf-8");
64027
64844
  } catch (e) {
64028
64845
  if (e.code === "ENOENT") {
64029
64846
  return null;
@@ -65369,9 +66186,9 @@ init_cli_executor();
65369
66186
  init_server_manager();
65370
66187
  init_package_paths();
65371
66188
  init_logger();
65372
- import_dotenv.default.config({ path: resolve12(packageRootDir, ".env"), quiet: true });
66189
+ import_dotenv.default.config({ path: resolve13(packageRootDir, ".env"), quiet: true });
65373
66190
  var PACKAGE_NAME = "codeql-development-mcp-server";
65374
- var VERSION = "2.24.1";
66191
+ var VERSION = "2.24.3-rc2";
65375
66192
  async function startServer(mode = "stdio") {
65376
66193
  logger.info(`Starting CodeQL Development MCP McpServer v${VERSION} in ${mode} mode`);
65377
66194
  const codeqlBinary = resolveCodeQLBinary();
@@ -65425,10 +66242,10 @@ async function startServer(mode = "stdio") {
65425
66242
  });
65426
66243
  const host = process.env.HTTP_HOST || "localhost";
65427
66244
  const port = Number(process.env.HTTP_PORT || process.env.PORT) || 3e3;
65428
- return new Promise((resolve13, reject) => {
66245
+ return new Promise((resolve14, reject) => {
65429
66246
  const httpServer = app.listen(port, host, () => {
65430
66247
  logger.info(`HTTP server listening on http://${host}:${port}/mcp`);
65431
- resolve13();
66248
+ resolve14();
65432
66249
  });
65433
66250
  httpServer.on("error", (error2) => {
65434
66251
  logger.error("HTTP server error:", error2);
@@ -65465,7 +66282,7 @@ async function main() {
65465
66282
  process.exit(1);
65466
66283
  }
65467
66284
  }
65468
- 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;
65469
66286
  if (scriptPath && import.meta.url === pathToFileURL5(scriptPath).href) {
65470
66287
  main();
65471
66288
  }