@akasecurity/ai-tc-claude-code 0.9.5 → 0.9.6

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.
@@ -26963,6 +26963,40 @@ function escapeRegExp2(value) {
26963
26963
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26964
26964
  }
26965
26965
 
26966
+ // ../../packages/detections/src/regex-cache.ts
26967
+ var singles = /* @__PURE__ */ new WeakMap();
26968
+ var keywordLists = /* @__PURE__ */ new WeakMap();
26969
+ var labelLists = /* @__PURE__ */ new WeakMap();
26970
+ function listCache(kind) {
26971
+ return kind === "keyword" ? keywordLists : labelLists;
26972
+ }
26973
+ function memoizedRegExp(owner, build) {
26974
+ const cached2 = singles.get(owner);
26975
+ if (cached2 !== void 0) {
26976
+ cached2.lastIndex = 0;
26977
+ return cached2;
26978
+ }
26979
+ const compiled = build();
26980
+ singles.set(owner, compiled);
26981
+ return compiled;
26982
+ }
26983
+ function memoizedRegExpList(kind, owner, build) {
26984
+ const cache = listCache(kind);
26985
+ const cached2 = cache.get(owner);
26986
+ if (cached2 !== void 0) {
26987
+ if (cached2.stateful) {
26988
+ for (const re of cached2.entries) if (re !== void 0) re.lastIndex = 0;
26989
+ }
26990
+ return cached2.entries;
26991
+ }
26992
+ const entries = build();
26993
+ cache.set(owner, {
26994
+ entries,
26995
+ stateful: entries.some((re) => re !== void 0 && (re.global || re.sticky))
26996
+ });
26997
+ return entries;
26998
+ }
26999
+
26966
27000
  // ../../packages/detections/src/matchers/limits.ts
26967
27001
  var MAX_MATCHES_PER_RULE = 1e4;
26968
27002
  var MAX_REGEX_INPUT_LENGTH = 2e5;
@@ -26973,10 +27007,17 @@ var KeywordMatcher2 = class {
26973
27007
  if (rule.matcher.type !== "keyword") return [];
26974
27008
  const { keywords, caseSensitive } = rule.matcher;
26975
27009
  const spans = [];
26976
- for (const kw of keywords) {
26977
- if (kw.length === 0) continue;
27010
+ const compiled = memoizedRegExpList(
27011
+ "keyword",
27012
+ rule.matcher,
27013
+ () => keywords.map((kw) => {
27014
+ if (kw.length === 0) return void 0;
27015
+ return new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
27016
+ })
27017
+ );
27018
+ for (const re of compiled) {
27019
+ if (re === void 0) continue;
26978
27020
  if (spans.length >= MAX_MATCHES_PER_RULE) break;
26979
- const re = new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
26980
27021
  let m;
26981
27022
  while ((m = re.exec(text)) !== null) {
26982
27023
  spans.push({ start: m.index, end: m.index + m[0].length });
@@ -26992,7 +27033,10 @@ var RegexMatcher2 = class {
26992
27033
  match(text, rule) {
26993
27034
  if (rule.matcher.type !== "regex") return [];
26994
27035
  const { pattern, flags, captureGroup } = rule.matcher;
26995
- const re = new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`);
27036
+ const re = memoizedRegExp(
27037
+ rule.matcher,
27038
+ () => new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`)
27039
+ );
26996
27040
  const scanText2 = text.length > MAX_REGEX_INPUT_LENGTH ? text.slice(0, MAX_REGEX_INPUT_LENGTH) : text;
26997
27041
  const spans = [];
26998
27042
  let m;
@@ -27100,11 +27144,15 @@ function isCorroborated(candidate, candidates, text) {
27100
27144
  const labels = req.labels;
27101
27145
  if (labels && labels.length > 0) {
27102
27146
  const haystack = text.slice(Math.max(0, winStart), winEnd);
27103
- for (const label of labels) {
27104
- const trimmed = label.trim();
27105
- if (trimmed.length === 0) continue;
27106
- const re = new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
27107
- if (re.test(haystack)) return true;
27147
+ for (const re of memoizedRegExpList(
27148
+ "label",
27149
+ req,
27150
+ () => labels.map((label) => {
27151
+ const trimmed = label.trim();
27152
+ return trimmed.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
27153
+ })
27154
+ )) {
27155
+ if (re?.test(haystack)) return true;
27108
27156
  }
27109
27157
  }
27110
27158
  return false;
@@ -29547,7 +29595,7 @@ import { basename as basename4, dirname as dirname3, sep as sep3 } from "path";
29547
29595
  // ../../packages/plugin-sdk/src/project-files.ts
29548
29596
  var import_ignore = __toESM(require_ignore(), 1);
29549
29597
  import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "fs";
29550
- import { basename as basename5, join as join12, relative, sep as sep4 } from "path";
29598
+ import { basename as basename5, join as join12 } from "path";
29551
29599
 
29552
29600
  // ../../packages/plugin-sdk/src/provider-env-antigravity.ts
29553
29601
  var optionalBaseUrl2 = external_exports.preprocess((v) => {
@@ -30202,7 +30250,7 @@ var EXCEPTION_RETENTION_MS = 90 * 24 * 60 * 60 * 1e3;
30202
30250
 
30203
30251
  // src/remediation/redact.ts
30204
30252
  import { readFileSync as readFileSync10, realpathSync as realpathSync3, renameSync as renameSync5, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
30205
- import { isAbsolute as isAbsolute2, relative as relative2, resolve } from "path";
30253
+ import { isAbsolute as isAbsolute2, relative, resolve } from "path";
30206
30254
 
30207
30255
  // src/history/transcripts.ts
30208
30256
  import { readdirSync as readdirSync5, readFileSync as readFileSync9 } from "fs";
@@ -30426,7 +30474,7 @@ function realPathOrNull(path) {
30426
30474
  function isWithinRoot(realTarget, root) {
30427
30475
  const realRoot = realPathOrNull(root);
30428
30476
  if (realRoot === null) return false;
30429
- const rel = relative2(realRoot, realTarget);
30477
+ const rel = relative(realRoot, realTarget);
30430
30478
  return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
30431
30479
  }
30432
30480
  function resolveRedactableArtifact(filePath, scope) {
@@ -26961,6 +26961,40 @@ function escapeRegExp2(value) {
26961
26961
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26962
26962
  }
26963
26963
 
26964
+ // ../../packages/detections/src/regex-cache.ts
26965
+ var singles = /* @__PURE__ */ new WeakMap();
26966
+ var keywordLists = /* @__PURE__ */ new WeakMap();
26967
+ var labelLists = /* @__PURE__ */ new WeakMap();
26968
+ function listCache(kind) {
26969
+ return kind === "keyword" ? keywordLists : labelLists;
26970
+ }
26971
+ function memoizedRegExp(owner, build) {
26972
+ const cached2 = singles.get(owner);
26973
+ if (cached2 !== void 0) {
26974
+ cached2.lastIndex = 0;
26975
+ return cached2;
26976
+ }
26977
+ const compiled = build();
26978
+ singles.set(owner, compiled);
26979
+ return compiled;
26980
+ }
26981
+ function memoizedRegExpList(kind, owner, build) {
26982
+ const cache = listCache(kind);
26983
+ const cached2 = cache.get(owner);
26984
+ if (cached2 !== void 0) {
26985
+ if (cached2.stateful) {
26986
+ for (const re of cached2.entries) if (re !== void 0) re.lastIndex = 0;
26987
+ }
26988
+ return cached2.entries;
26989
+ }
26990
+ const entries = build();
26991
+ cache.set(owner, {
26992
+ entries,
26993
+ stateful: entries.some((re) => re !== void 0 && (re.global || re.sticky))
26994
+ });
26995
+ return entries;
26996
+ }
26997
+
26964
26998
  // ../../packages/detections/src/matchers/limits.ts
26965
26999
  var MAX_MATCHES_PER_RULE = 1e4;
26966
27000
  var MAX_REGEX_INPUT_LENGTH = 2e5;
@@ -26971,10 +27005,17 @@ var KeywordMatcher2 = class {
26971
27005
  if (rule.matcher.type !== "keyword") return [];
26972
27006
  const { keywords, caseSensitive } = rule.matcher;
26973
27007
  const spans = [];
26974
- for (const kw of keywords) {
26975
- if (kw.length === 0) continue;
27008
+ const compiled = memoizedRegExpList(
27009
+ "keyword",
27010
+ rule.matcher,
27011
+ () => keywords.map((kw) => {
27012
+ if (kw.length === 0) return void 0;
27013
+ return new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
27014
+ })
27015
+ );
27016
+ for (const re of compiled) {
27017
+ if (re === void 0) continue;
26976
27018
  if (spans.length >= MAX_MATCHES_PER_RULE) break;
26977
- const re = new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
26978
27019
  let m;
26979
27020
  while ((m = re.exec(text)) !== null) {
26980
27021
  spans.push({ start: m.index, end: m.index + m[0].length });
@@ -26990,7 +27031,10 @@ var RegexMatcher2 = class {
26990
27031
  match(text, rule) {
26991
27032
  if (rule.matcher.type !== "regex") return [];
26992
27033
  const { pattern, flags, captureGroup } = rule.matcher;
26993
- const re = new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`);
27034
+ const re = memoizedRegExp(
27035
+ rule.matcher,
27036
+ () => new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`)
27037
+ );
26994
27038
  const scanText2 = text.length > MAX_REGEX_INPUT_LENGTH ? text.slice(0, MAX_REGEX_INPUT_LENGTH) : text;
26995
27039
  const spans = [];
26996
27040
  let m;
@@ -27098,11 +27142,15 @@ function isCorroborated(candidate, candidates, text) {
27098
27142
  const labels = req.labels;
27099
27143
  if (labels && labels.length > 0) {
27100
27144
  const haystack = text.slice(Math.max(0, winStart), winEnd);
27101
- for (const label of labels) {
27102
- const trimmed = label.trim();
27103
- if (trimmed.length === 0) continue;
27104
- const re = new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
27105
- if (re.test(haystack)) return true;
27145
+ for (const re of memoizedRegExpList(
27146
+ "label",
27147
+ req,
27148
+ () => labels.map((label) => {
27149
+ const trimmed = label.trim();
27150
+ return trimmed.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
27151
+ })
27152
+ )) {
27153
+ if (re?.test(haystack)) return true;
27106
27154
  }
27107
27155
  }
27108
27156
  return false;
@@ -27370,13 +27418,14 @@ function probesFor(rule) {
27370
27418
  const derived = rule.matcher.type === "regex" ? derivedProbes(rule.matcher.pattern) : [];
27371
27419
  return [...derived, ...EXPONENTIAL_PROBES, ...POLYNOMIAL_PROBES];
27372
27420
  }
27373
- function worstProbeMs(rule) {
27421
+ var wallClock = () => performance.now();
27422
+ function worstProbeMs(rule, now = wallClock) {
27374
27423
  let ms = 0;
27375
27424
  let probe = "";
27376
27425
  for (const text of probesFor(rule)) {
27377
- const start = performance.now();
27426
+ const start = now();
27378
27427
  scan(text, [rule]);
27379
- const elapsed = performance.now() - start;
27428
+ const elapsed = now() - start;
27380
27429
  if (elapsed > ms) {
27381
27430
  ms = elapsed;
27382
27431
  probe = text;
@@ -30011,7 +30060,7 @@ function applyCategoryPosture(posture, repo, mode = "fill-gaps") {
30011
30060
  // ../../packages/plugin-sdk/src/project-files.ts
30012
30061
  var import_ignore = __toESM(require_ignore(), 1);
30013
30062
  import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "fs";
30014
- import { basename as basename5, join as join12, relative, sep as sep4 } from "path";
30063
+ import { basename as basename5, join as join12 } from "path";
30015
30064
 
30016
30065
  // ../../packages/plugin-sdk/src/provider-env-antigravity.ts
30017
30066
  var optionalBaseUrl2 = external_exports.preprocess((v) => {
@@ -31084,8 +31133,8 @@ function table(headers, rows, opts = {}) {
31084
31133
  const widths = headers.map(
31085
31134
  (h, i) => Math.max(visibleLength(h), ...rows.map((r) => visibleLength(r[i] ?? "")))
31086
31135
  );
31087
- const sep5 = " ".repeat(gap);
31088
- const fmt = (cells) => cells.map((cell, i) => padEnd(cell, widths[i] ?? 0)).join(sep5);
31136
+ const sep4 = " ".repeat(gap);
31137
+ const fmt = (cells) => cells.map((cell, i) => padEnd(cell, widths[i] ?? 0)).join(sep4);
31089
31138
  const headerLine = fmt(headers.map((h) => h.toUpperCase()));
31090
31139
  if (opts.rowSep === true) {
31091
31140
  const fullWidth = widths.reduce((n, w) => n + w, 0) + gap * Math.max(0, widths.length - 1);
@@ -31097,7 +31146,7 @@ function table(headers, rows, opts = {}) {
31097
31146
  });
31098
31147
  return [headerLine, rule, ...body].join("\n");
31099
31148
  }
31100
- const ruleLine = widths.map((w) => "\u2500".repeat(w)).join(sep5);
31149
+ const ruleLine = widths.map((w) => "\u2500".repeat(w)).join(sep4);
31101
31150
  return [headerLine, ruleLine, ...rows.map(fmt)].join("\n");
31102
31151
  }
31103
31152
  function fenced(body) {
@@ -31472,7 +31521,7 @@ var DAY_MS5 = 24 * 60 * 60 * 1e3;
31472
31521
 
31473
31522
  // src/remediation/redact.ts
31474
31523
  import { readFileSync as readFileSync11, realpathSync as realpathSync3, renameSync as renameSync5, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "fs";
31475
- import { isAbsolute as isAbsolute2, relative as relative2, resolve } from "path";
31524
+ import { isAbsolute as isAbsolute2, relative, resolve } from "path";
31476
31525
  var REDACTED_PLACEHOLDER = "[REDACTED:SECRET]";
31477
31526
  var REPLACE_PATTERN_SEQUENCE = /\$[$&`'<0-9]/;
31478
31527
  function replacementFor(rawValue, replacements) {
@@ -31495,7 +31544,7 @@ function realPathOrNull(path) {
31495
31544
  function isWithinRoot(realTarget, root) {
31496
31545
  const realRoot = realPathOrNull(root);
31497
31546
  if (realRoot === null) return false;
31498
- const rel = relative2(realRoot, realTarget);
31547
+ const rel = relative(realRoot, realTarget);
31499
31548
  return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
31500
31549
  }
31501
31550
  function resolveRedactableArtifact(filePath, scope) {
@@ -579,6 +579,40 @@ function escapeRegExp2(value) {
579
579
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
580
580
  }
581
581
 
582
+ // ../../packages/detections/src/regex-cache.ts
583
+ var singles = /* @__PURE__ */ new WeakMap();
584
+ var keywordLists = /* @__PURE__ */ new WeakMap();
585
+ var labelLists = /* @__PURE__ */ new WeakMap();
586
+ function listCache(kind) {
587
+ return kind === "keyword" ? keywordLists : labelLists;
588
+ }
589
+ function memoizedRegExp(owner, build) {
590
+ const cached2 = singles.get(owner);
591
+ if (cached2 !== void 0) {
592
+ cached2.lastIndex = 0;
593
+ return cached2;
594
+ }
595
+ const compiled = build();
596
+ singles.set(owner, compiled);
597
+ return compiled;
598
+ }
599
+ function memoizedRegExpList(kind, owner, build) {
600
+ const cache = listCache(kind);
601
+ const cached2 = cache.get(owner);
602
+ if (cached2 !== void 0) {
603
+ if (cached2.stateful) {
604
+ for (const re of cached2.entries) if (re !== void 0) re.lastIndex = 0;
605
+ }
606
+ return cached2.entries;
607
+ }
608
+ const entries = build();
609
+ cache.set(owner, {
610
+ entries,
611
+ stateful: entries.some((re) => re !== void 0 && (re.global || re.sticky))
612
+ });
613
+ return entries;
614
+ }
615
+
582
616
  // ../../packages/detections/src/matchers/limits.ts
583
617
  var MAX_MATCHES_PER_RULE = 1e4;
584
618
  var MAX_REGEX_INPUT_LENGTH = 2e5;
@@ -589,10 +623,17 @@ var KeywordMatcher = class {
589
623
  if (rule.matcher.type !== "keyword") return [];
590
624
  const { keywords, caseSensitive } = rule.matcher;
591
625
  const spans = [];
592
- for (const kw of keywords) {
593
- if (kw.length === 0) continue;
626
+ const compiled = memoizedRegExpList(
627
+ "keyword",
628
+ rule.matcher,
629
+ () => keywords.map((kw) => {
630
+ if (kw.length === 0) return void 0;
631
+ return new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
632
+ })
633
+ );
634
+ for (const re of compiled) {
635
+ if (re === void 0) continue;
594
636
  if (spans.length >= MAX_MATCHES_PER_RULE) break;
595
- const re = new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
596
637
  let m;
597
638
  while ((m = re.exec(text)) !== null) {
598
639
  spans.push({ start: m.index, end: m.index + m[0].length });
@@ -608,7 +649,10 @@ var RegexMatcher = class {
608
649
  match(text, rule) {
609
650
  if (rule.matcher.type !== "regex") return [];
610
651
  const { pattern, flags, captureGroup } = rule.matcher;
611
- const re = new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`);
652
+ const re = memoizedRegExp(
653
+ rule.matcher,
654
+ () => new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`)
655
+ );
612
656
  const scanText = text.length > MAX_REGEX_INPUT_LENGTH ? text.slice(0, MAX_REGEX_INPUT_LENGTH) : text;
613
657
  const spans = [];
614
658
  let m;
@@ -713,11 +757,15 @@ function isCorroborated(candidate, candidates, text) {
713
757
  const labels = req.labels;
714
758
  if (labels && labels.length > 0) {
715
759
  const haystack = text.slice(Math.max(0, winStart), winEnd);
716
- for (const label of labels) {
717
- const trimmed = label.trim();
718
- if (trimmed.length === 0) continue;
719
- const re = new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
720
- if (re.test(haystack)) return true;
760
+ for (const re of memoizedRegExpList(
761
+ "label",
762
+ req,
763
+ () => labels.map((label) => {
764
+ const trimmed = label.trim();
765
+ return trimmed.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
766
+ })
767
+ )) {
768
+ if (re?.test(haystack)) return true;
721
769
  }
722
770
  }
723
771
  return false;
@@ -17951,13 +17999,14 @@ function probesFor(rule) {
17951
17999
  const derived = rule.matcher.type === "regex" ? derivedProbes(rule.matcher.pattern) : [];
17952
18000
  return [...derived, ...EXPONENTIAL_PROBES, ...POLYNOMIAL_PROBES];
17953
18001
  }
17954
- function worstProbeMs(rule) {
18002
+ var wallClock = () => performance.now();
18003
+ function worstProbeMs(rule, now = wallClock) {
17955
18004
  let ms = 0;
17956
18005
  let probe = "";
17957
18006
  for (const text of probesFor(rule)) {
17958
- const start = performance.now();
18007
+ const start = now();
17959
18008
  scan(text, [rule]);
17960
- const elapsed = performance.now() - start;
18009
+ const elapsed = now() - start;
17961
18010
  if (elapsed > ms) {
17962
18011
  ms = elapsed;
17963
18012
  probe = text;
@@ -26053,6 +26053,40 @@ function escapeRegExp2(value) {
26053
26053
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26054
26054
  }
26055
26055
 
26056
+ // ../../packages/detections/src/regex-cache.ts
26057
+ var singles = /* @__PURE__ */ new WeakMap();
26058
+ var keywordLists = /* @__PURE__ */ new WeakMap();
26059
+ var labelLists = /* @__PURE__ */ new WeakMap();
26060
+ function listCache(kind) {
26061
+ return kind === "keyword" ? keywordLists : labelLists;
26062
+ }
26063
+ function memoizedRegExp(owner, build) {
26064
+ const cached2 = singles.get(owner);
26065
+ if (cached2 !== void 0) {
26066
+ cached2.lastIndex = 0;
26067
+ return cached2;
26068
+ }
26069
+ const compiled = build();
26070
+ singles.set(owner, compiled);
26071
+ return compiled;
26072
+ }
26073
+ function memoizedRegExpList(kind, owner, build) {
26074
+ const cache = listCache(kind);
26075
+ const cached2 = cache.get(owner);
26076
+ if (cached2 !== void 0) {
26077
+ if (cached2.stateful) {
26078
+ for (const re of cached2.entries) if (re !== void 0) re.lastIndex = 0;
26079
+ }
26080
+ return cached2.entries;
26081
+ }
26082
+ const entries = build();
26083
+ cache.set(owner, {
26084
+ entries,
26085
+ stateful: entries.some((re) => re !== void 0 && (re.global || re.sticky))
26086
+ });
26087
+ return entries;
26088
+ }
26089
+
26056
26090
  // ../../packages/detections/src/matchers/limits.ts
26057
26091
  var MAX_MATCHES_PER_RULE = 1e4;
26058
26092
  var MAX_REGEX_INPUT_LENGTH = 2e5;
@@ -26063,10 +26097,17 @@ var KeywordMatcher2 = class {
26063
26097
  if (rule.matcher.type !== "keyword") return [];
26064
26098
  const { keywords, caseSensitive } = rule.matcher;
26065
26099
  const spans = [];
26066
- for (const kw of keywords) {
26067
- if (kw.length === 0) continue;
26100
+ const compiled = memoizedRegExpList(
26101
+ "keyword",
26102
+ rule.matcher,
26103
+ () => keywords.map((kw) => {
26104
+ if (kw.length === 0) return void 0;
26105
+ return new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
26106
+ })
26107
+ );
26108
+ for (const re of compiled) {
26109
+ if (re === void 0) continue;
26068
26110
  if (spans.length >= MAX_MATCHES_PER_RULE) break;
26069
- const re = new RegExp(escapeRegExp2(kw), caseSensitive ? "gu" : "giu");
26070
26111
  let m;
26071
26112
  while ((m = re.exec(text)) !== null) {
26072
26113
  spans.push({ start: m.index, end: m.index + m[0].length });
@@ -26082,7 +26123,10 @@ var RegexMatcher2 = class {
26082
26123
  match(text, rule) {
26083
26124
  if (rule.matcher.type !== "regex") return [];
26084
26125
  const { pattern, flags, captureGroup } = rule.matcher;
26085
- const re = new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`);
26126
+ const re = memoizedRegExp(
26127
+ rule.matcher,
26128
+ () => new RegExp(pattern, flags.includes("d") ? flags : `${flags}d`)
26129
+ );
26086
26130
  const scanText2 = text.length > MAX_REGEX_INPUT_LENGTH ? text.slice(0, MAX_REGEX_INPUT_LENGTH) : text;
26087
26131
  const spans = [];
26088
26132
  let m;
@@ -26190,11 +26234,15 @@ function isCorroborated(candidate, candidates, text) {
26190
26234
  const labels = req.labels;
26191
26235
  if (labels && labels.length > 0) {
26192
26236
  const haystack = text.slice(Math.max(0, winStart), winEnd);
26193
- for (const label of labels) {
26194
- const trimmed = label.trim();
26195
- if (trimmed.length === 0) continue;
26196
- const re = new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
26197
- if (re.test(haystack)) return true;
26237
+ for (const re of memoizedRegExpList(
26238
+ "label",
26239
+ req,
26240
+ () => labels.map((label) => {
26241
+ const trimmed = label.trim();
26242
+ return trimmed.length === 0 ? void 0 : new RegExp(`(?<![A-Za-z0-9])${escapeRegExp2(trimmed)}(?![A-Za-z0-9])`, "i");
26243
+ })
26244
+ )) {
26245
+ if (re?.test(haystack)) return true;
26198
26246
  }
26199
26247
  }
26200
26248
  return false;
@@ -29027,10 +29075,10 @@ function parseFrontmatter(raw) {
29027
29075
  if (lines[0]?.trim() !== "---") return out;
29028
29076
  for (const line of lines.slice(1)) {
29029
29077
  if (line.trim() === "---") break;
29030
- const sep5 = line.indexOf(":");
29031
- if (sep5 === -1) continue;
29032
- const key = line.slice(0, sep5).trim();
29033
- const value = line.slice(sep5 + 1).trim().replace(/^['"]|['"]$/g, "");
29078
+ const sep4 = line.indexOf(":");
29079
+ if (sep4 === -1) continue;
29080
+ const key = line.slice(0, sep4).trim();
29081
+ const value = line.slice(sep4 + 1).trim().replace(/^['"]|['"]$/g, "");
29034
29082
  if (value === "") continue;
29035
29083
  if (key === "name") out.name = value;
29036
29084
  else if (key === "description") out.description = value;
@@ -29249,7 +29297,7 @@ import { basename as basename5, dirname as dirname3, sep as sep3 } from "path";
29249
29297
  // ../../packages/plugin-sdk/src/project-files.ts
29250
29298
  var import_ignore = __toESM(require_ignore(), 1);
29251
29299
  import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "fs";
29252
- import { basename as basename6, join as join12, relative, sep as sep4 } from "path";
29300
+ import { basename as basename6, join as join12 } from "path";
29253
29301
  var SKIP_DIRS = /* @__PURE__ */ new Set([
29254
29302
  ".git",
29255
29303
  "node_modules",
@@ -29267,23 +29315,28 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
29267
29315
  ".cache"
29268
29316
  ]);
29269
29317
  var MAX_FILES = 2e4;
29270
- function readIgnoreLayer(dir) {
29318
+ function readIgnoreLayer(dir, anchorLen) {
29271
29319
  try {
29272
29320
  const content = readFileSync8(join12(dir, ".gitignore"), "utf8");
29273
- return { base: dir, matcher: (0, import_ignore.default)().add(content) };
29321
+ return { matcher: (0, import_ignore.default)().add(content), anchorLen };
29274
29322
  } catch {
29275
29323
  return void 0;
29276
29324
  }
29277
29325
  }
29278
- function isIgnored(layers, absPath, isDir) {
29279
- let ignored = false;
29280
- for (const layer of layers) {
29281
- const rel = relative(layer.base, absPath).split(sep4).join("/") + (isDir ? "/" : "");
29282
- const verdict = layer.matcher.test(rel);
29283
- if (verdict.ignored) ignored = true;
29284
- else if (verdict.unignored) ignored = false;
29326
+ function relToAnchor(dirRel, anchorLen, name) {
29327
+ if (anchorLen === dirRel.length) return name;
29328
+ return `${dirRel.slice(anchorLen === 0 ? 0 : anchorLen + 1)}/${name}`;
29329
+ }
29330
+ function isIgnored(layers, dirRel, name, isDir) {
29331
+ const suffix = isDir ? "/" : "";
29332
+ for (let i = layers.length - 1; i >= 0; i--) {
29333
+ const layer = layers[i];
29334
+ if (layer === void 0) continue;
29335
+ const verdict = layer.matcher.test(relToAnchor(dirRel, layer.anchorLen, name) + suffix);
29336
+ if (verdict.ignored) return true;
29337
+ if (verdict.unignored) return false;
29285
29338
  }
29286
- return ignored;
29339
+ return false;
29287
29340
  }
29288
29341
  var GENERATED_FILES = /* @__PURE__ */ new Set([
29289
29342
  "pnpm-lock.yaml",
@@ -29336,7 +29389,7 @@ function classifyOrigin(relPath, name) {
29336
29389
  }
29337
29390
  function resolveProjectFiles(cwd) {
29338
29391
  try {
29339
- let visit2 = function(dir, layers) {
29392
+ let visit2 = function(dir, dirRel, layers) {
29340
29393
  let dirents;
29341
29394
  try {
29342
29395
  dirents = readdirSync4(dir, { withFileTypes: true, encoding: "utf8" });
@@ -29344,21 +29397,22 @@ function resolveProjectFiles(cwd) {
29344
29397
  walk.lostSubtree = true;
29345
29398
  return false;
29346
29399
  }
29347
- const layer = readIgnoreLayer(dir);
29400
+ const layer = readIgnoreLayer(dir, dirRel.length);
29348
29401
  const dirLayers = layer ? [...layers, layer] : layers;
29349
29402
  for (const entry of dirents) {
29350
- const fullPath = join12(dir, entry.name);
29351
29403
  if (entry.isDirectory()) {
29352
- if (SKIP_DIRS.has(entry.name) || isIgnored(dirLayers, fullPath, true)) continue;
29404
+ if (SKIP_DIRS.has(entry.name) || isIgnored(dirLayers, dirRel, entry.name, true)) continue;
29405
+ const fullPath = join12(dir, entry.name);
29353
29406
  if (existsSync8(join12(fullPath, ".git"))) continue;
29354
- if (visit2(fullPath, dirLayers)) return true;
29407
+ const childRel = dirRel === "" ? entry.name : `${dirRel}/${entry.name}`;
29408
+ if (visit2(fullPath, childRel, dirLayers)) return true;
29355
29409
  continue;
29356
29410
  }
29357
29411
  if (!entry.isFile()) continue;
29358
29412
  if (entry.name === ".git") continue;
29359
- if (isIgnored(dirLayers, fullPath, false)) continue;
29413
+ if (isIgnored(dirLayers, dirRel, entry.name, false)) continue;
29360
29414
  if (files.length >= MAX_FILES) return true;
29361
- const relPath = relative(root, fullPath).split(sep4).join("/");
29415
+ const relPath = dirRel === "" ? entry.name : `${dirRel}/${entry.name}`;
29362
29416
  files.push({
29363
29417
  path: relPath,
29364
29418
  name: basename6(entry.name),
@@ -29375,7 +29429,7 @@ function resolveProjectFiles(cwd) {
29375
29429
  const isLinkedCheckout = resolveHeadRoot(cwd) !== worktree;
29376
29430
  const files = [];
29377
29431
  const walk = { lostSubtree: false };
29378
- const truncated = visit2(root, []) || walk.lostSubtree || isLinkedCheckout;
29432
+ const truncated = visit2(root, "", []) || walk.lostSubtree || isLinkedCheckout;
29379
29433
  if (files.length === 0) return void 0;
29380
29434
  files.sort((a, b) => a.path.localeCompare(b.path));
29381
29435
  return { files, truncated, scannedAt: (/* @__PURE__ */ new Date()).toISOString() };