@probelabs/visor 0.1.92 → 0.1.93

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.
Files changed (26) hide show
  1. package/defaults/.visor.yaml +15 -16
  2. package/dist/check-execution-engine.d.ts +6 -0
  3. package/dist/check-execution-engine.d.ts.map +1 -1
  4. package/dist/defaults/.visor.yaml +15 -16
  5. package/dist/index.js +413 -624
  6. package/dist/liquid-extensions.d.ts +12 -0
  7. package/dist/liquid-extensions.d.ts.map +1 -1
  8. package/dist/output/issue-assistant/schema.json +14 -1
  9. package/dist/sdk/{check-execution-engine-L73PFZQY.mjs → check-execution-engine-RORGGGGP.mjs} +3 -3
  10. package/dist/sdk/{chunk-2U6BIWSY.mjs → chunk-I3GQJIR7.mjs} +14 -10
  11. package/dist/sdk/chunk-I3GQJIR7.mjs.map +1 -0
  12. package/dist/sdk/{chunk-LJHRU3WQ.mjs → chunk-Z47UECAT.mjs} +26 -24
  13. package/dist/sdk/{chunk-LJHRU3WQ.mjs.map → chunk-Z47UECAT.mjs.map} +1 -1
  14. package/dist/sdk/{liquid-extensions-AFKRYROF.mjs → liquid-extensions-GMEGEGC3.mjs} +6 -2
  15. package/dist/sdk/sdk.js +34 -28
  16. package/dist/sdk/sdk.js.map +1 -1
  17. package/dist/sdk/sdk.mjs +2 -2
  18. package/dist/traces/{run-2025-10-15T07-21-47-696Z.ndjson → run-2025-10-15T11-54-04-087Z.ndjson} +19 -3
  19. package/dist/traces/{run-2025-10-15T07-21-58-106Z.ndjson → run-2025-10-15T11-54-14-046Z.ndjson} +19 -3
  20. package/dist/traces/{run-2025-10-15T07-21-58-693Z.ndjson → run-2025-10-15T11-54-14-575Z.ndjson} +19 -3
  21. package/dist/traces/{run-2025-10-15T07-21-59-167Z.ndjson → run-2025-10-15T11-54-15-082Z.ndjson} +19 -3
  22. package/dist/traces/{run-2025-10-15T07-21-59-629Z.ndjson → run-2025-10-15T11-54-15-561Z.ndjson} +4 -0
  23. package/package.json +2 -2
  24. package/dist/sdk/chunk-2U6BIWSY.mjs.map +0 -1
  25. /package/dist/sdk/{check-execution-engine-L73PFZQY.mjs.map → check-execution-engine-RORGGGGP.mjs.map} +0 -0
  26. /package/dist/sdk/{liquid-extensions-AFKRYROF.mjs.map → liquid-extensions-GMEGEGC3.mjs.map} +0 -0
@@ -1,4 +1,16 @@
1
1
  import { Liquid, TagToken, Context, TopLevelToken, Tag, Emitter } from 'liquidjs';
2
+ /**
3
+ * Sanitize label strings to only allow [A-Za-z0-9:/] characters
4
+ * @param value - Label value to sanitize
5
+ * @returns Sanitized label string
6
+ */
7
+ export declare function sanitizeLabel(value: unknown): string;
8
+ /**
9
+ * Sanitize an array of labels
10
+ * @param labels - Array of label values
11
+ * @returns Array of sanitized, non-empty label strings
12
+ */
13
+ export declare function sanitizeLabelList(labels: unknown): string[];
2
14
  /**
3
15
  * Custom ReadFile tag for Liquid templates
4
16
  * Usage: {% readfile "path/to/file.txt" %}
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/liquid-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAS,OAAO,EAAE,MAAM,UAAU,CAAC;AAezF;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,GAAG;IAClC,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM;IAKzE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC;CAgC3E;AAKD,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,GAAG,EAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAwGlE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAUlF"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/liquid-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAS,OAAO,EAAE,MAAM,UAAU,CAAC;AAezF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKpD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAG3D;AAED;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,GAAG;IAClC,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM;IAKzE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC;CAgC3E;AAKD,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,GAAG,EAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA6FlE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAUlF"}
@@ -22,7 +22,20 @@
22
22
  "labels": {
23
23
  "type": "array",
24
24
  "description": "Optional labels to apply (only respected on issue_opened)",
25
- "items": { "type": "string" }
25
+ "items": {
26
+ "type": "string",
27
+ "enum": [
28
+ "bug",
29
+ "chore",
30
+ "documentation",
31
+ "enhancement",
32
+ "feature",
33
+ "question",
34
+ "wontfix",
35
+ "invalid",
36
+ "duplicate"
37
+ ]
38
+ }
26
39
  }
27
40
  },
28
41
  "additionalProperties": true
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  CheckExecutionEngine
3
- } from "./chunk-LJHRU3WQ.mjs";
3
+ } from "./chunk-Z47UECAT.mjs";
4
4
  import "./chunk-KVHVCGY6.mjs";
5
- import "./chunk-2U6BIWSY.mjs";
5
+ import "./chunk-I3GQJIR7.mjs";
6
6
  import "./chunk-TWJKAYT6.mjs";
7
7
  import "./chunk-WMJKH4XE.mjs";
8
8
  export {
9
9
  CheckExecutionEngine
10
10
  };
11
- //# sourceMappingURL=check-execution-engine-L73PFZQY.mjs.map
11
+ //# sourceMappingURL=check-execution-engine-RORGGGGP.mjs.map
@@ -616,6 +616,15 @@ var MemoryStore = class _MemoryStore {
616
616
  };
617
617
 
618
618
  // src/liquid-extensions.ts
619
+ function sanitizeLabel(value) {
620
+ if (value == null) return "";
621
+ const s = String(value);
622
+ return s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/");
623
+ }
624
+ function sanitizeLabelList(labels) {
625
+ if (!Array.isArray(labels)) return [];
626
+ return labels.map((v) => sanitizeLabel(v)).filter((s) => s.length > 0);
627
+ }
619
628
  var ReadFileTag = class extends Tag {
620
629
  filepath;
621
630
  constructor(token, remainTokens, liquid) {
@@ -666,15 +675,8 @@ function configureLiquidWithExtensions(liquid) {
666
675
  return "[Error: Unable to serialize to JSON]";
667
676
  }
668
677
  });
669
- liquid.registerFilter("safe_label", (value) => {
670
- if (value == null) return "";
671
- const s = String(value);
672
- return s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/");
673
- });
674
- liquid.registerFilter("safe_label_list", (value) => {
675
- if (!Array.isArray(value)) return [];
676
- return value.map((v) => v == null ? "" : String(v)).map((s) => s.replace(/[^A-Za-z0-9:\/]/g, "").replace(/\/{2,}/g, "/")).filter((s) => s.length > 0);
677
- });
678
+ liquid.registerFilter("safe_label", (value) => sanitizeLabel(value));
679
+ liquid.registerFilter("safe_label_list", (value) => sanitizeLabelList(value));
678
680
  liquid.registerFilter("unescape_newlines", (value) => {
679
681
  if (value == null) return "";
680
682
  const s = String(value);
@@ -740,9 +742,11 @@ export {
740
742
  detectLocalMode,
741
743
  resolveAssociationFromEvent,
742
744
  MemoryStore,
745
+ sanitizeLabel,
746
+ sanitizeLabelList,
743
747
  ReadFileTag,
744
748
  withPermissionsContext,
745
749
  configureLiquidWithExtensions,
746
750
  createExtendedLiquid
747
751
  };
748
- //# sourceMappingURL=chunk-2U6BIWSY.mjs.map
752
+ //# sourceMappingURL=chunk-I3GQJIR7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logger.ts","../../src/liquid-extensions.ts","../../src/utils/author-permissions.ts","../../src/memory-store.ts"],"sourcesContent":["/*\n * Centralized logger for Visor CLI and Action modes.\n * - Respects output format (suppresses info in JSON/SARIF unless debug)\n * - Supports levels: silent < error < warn < info < verbose < debug\n * - Routes logs to stderr to keep stdout clean for machine-readable output\n */\n\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'verbose' | 'debug';\n\nfunction levelToNumber(level: LogLevel): number {\n switch (level) {\n case 'silent':\n return 0;\n case 'error':\n return 10;\n case 'warn':\n return 20;\n case 'info':\n return 30;\n case 'verbose':\n return 40;\n case 'debug':\n return 50;\n }\n}\n\nclass Logger {\n private level: LogLevel = 'info';\n private isJsonLike: boolean = false;\n private isTTY: boolean = typeof process !== 'undefined' ? !!process.stderr.isTTY : false;\n\n configure(\n opts: {\n outputFormat?: string;\n level?: LogLevel;\n debug?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n } = {}\n ): void {\n // Determine base level\n let lvl: LogLevel = 'info';\n\n if (opts.debug || process.env.VISOR_DEBUG === 'true') {\n lvl = 'debug';\n } else if (opts.verbose || process.env.VISOR_LOG_LEVEL === 'verbose') {\n lvl = 'verbose';\n } else if (opts.quiet || process.env.VISOR_LOG_LEVEL === 'quiet') {\n lvl = 'warn';\n } else if (opts.level) {\n lvl = opts.level;\n } else if (process.env.VISOR_LOG_LEVEL) {\n const envLvl = process.env.VISOR_LOG_LEVEL as LogLevel;\n if (['silent', 'error', 'warn', 'info', 'verbose', 'debug'].includes(envLvl)) {\n lvl = envLvl as LogLevel;\n }\n }\n\n this.level = lvl;\n const output = opts.outputFormat || process.env.VISOR_OUTPUT_FORMAT || 'table';\n // In JSON/SARIF we suppress non-error logs unless explicitly verbose/debug\n this.isJsonLike = output === 'json' || output === 'sarif';\n }\n\n private shouldLog(level: LogLevel): boolean {\n const desired = levelToNumber(level);\n const current = levelToNumber(this.level);\n if (desired > current) return false;\n if (\n this.isJsonLike &&\n desired < levelToNumber('error') &&\n this.level !== 'debug' &&\n this.level !== 'verbose'\n ) {\n // In JSON/SARIF, hide info/warn unless explicitly verbose/debug\n return false;\n }\n return true;\n }\n\n private write(msg: string): void {\n // Always route to stderr to keep stdout clean for results\n try {\n process.stderr.write(msg + '\\n');\n } catch {\n // Ignore write errors\n }\n }\n\n info(msg: string): void {\n if (this.shouldLog('info')) this.write(msg);\n }\n\n warn(msg: string): void {\n if (this.shouldLog('warn')) this.write(msg);\n }\n\n error(msg: string): void {\n if (this.shouldLog('error')) this.write(msg);\n }\n\n verbose(msg: string): void {\n if (this.shouldLog('verbose')) this.write(msg);\n }\n\n debug(msg: string): void {\n if (this.shouldLog('debug')) this.write(msg);\n }\n\n step(msg: string): void {\n // High-level phase indicator\n if (this.shouldLog('info')) this.write(`▶ ${msg}`);\n }\n\n success(msg: string): void {\n if (this.shouldLog('info')) this.write(`✔ ${msg}`);\n }\n}\n\n// Singleton instance\nexport const logger = new Logger();\n\n// Helper to configure from CLI options in a single place\nexport function configureLoggerFromCli(options: {\n output?: string;\n debug?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n}): void {\n logger.configure({\n outputFormat: options.output,\n debug: options.debug,\n verbose: options.verbose,\n quiet: options.quiet,\n });\n\n // Expose output format and debug to process env for modules that need to gate\n // stdout emissions without plumbing the value through every call site.\n try {\n if (options.output) process.env.VISOR_OUTPUT_FORMAT = String(options.output);\n if (typeof options.debug === 'boolean') {\n process.env.VISOR_DEBUG = options.debug ? 'true' : 'false';\n }\n } catch {\n // ignore\n }\n}\n","import { Liquid, TagToken, Context, TopLevelToken, Tag, Value, Emitter } from 'liquidjs';\nimport { AsyncLocalStorage } from 'async_hooks';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport {\n hasMinPermission,\n isOwner,\n isMember,\n isCollaborator,\n isContributor,\n isFirstTimer,\n detectLocalMode,\n} from './utils/author-permissions';\nimport { MemoryStore } from './memory-store';\n\n/**\n * Sanitize label strings to only allow [A-Za-z0-9:/] characters\n * @param value - Label value to sanitize\n * @returns Sanitized label string\n */\nexport function sanitizeLabel(value: unknown): string {\n if (value == null) return '';\n const s = String(value);\n // Keep only alphanumerics, colon, slash; collapse repeated slashes\n return s.replace(/[^A-Za-z0-9:\\/]/g, '').replace(/\\/{2,}/g, '/');\n}\n\n/**\n * Sanitize an array of labels\n * @param labels - Array of label values\n * @returns Array of sanitized, non-empty label strings\n */\nexport function sanitizeLabelList(labels: unknown): string[] {\n if (!Array.isArray(labels)) return [];\n return (labels as unknown[]).map(v => sanitizeLabel(v)).filter(s => s.length > 0);\n}\n\n/**\n * Custom ReadFile tag for Liquid templates\n * Usage: {% readfile \"path/to/file.txt\" %}\n * or with variable: {% readfile filename %}\n */\nexport class ReadFileTag extends Tag {\n private filepath: Value;\n\n constructor(token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {\n super(token, remainTokens, liquid);\n this.filepath = new Value(token.args, liquid);\n }\n\n *render(ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {\n const filePath = yield this.filepath.value(ctx, false);\n\n // Validate the path\n if (!filePath || typeof filePath !== 'string') {\n emitter.write('[Error: Invalid file path]');\n return;\n }\n\n // Security: Resolve path relative to project root to prevent directory traversal\n const projectRoot = process.cwd();\n const resolvedPath = path.resolve(projectRoot, filePath.toString());\n\n // Ensure the resolved path is within the project directory\n if (!resolvedPath.startsWith(projectRoot)) {\n emitter.write('[Error: File path escapes project directory]');\n return;\n }\n\n // Read the file content\n try {\n const content = yield fs.readFile(resolvedPath, 'utf-8');\n emitter.write(content);\n } catch (error) {\n // Handle file read errors gracefully\n const errorMessage =\n error instanceof Error\n ? error.message\n : (error as NodeJS.ErrnoException)?.code || 'Unknown error';\n emitter.write(`[Error reading file: ${errorMessage}]`);\n }\n }\n}\n\n// Async-local permissions context for filters (per-render)\nconst permissionsALS = new AsyncLocalStorage<{ authorAssociation?: string }>();\n\nexport async function withPermissionsContext<T>(\n ctx: { authorAssociation?: string },\n fn: () => Promise<T>\n): Promise<T> {\n return await permissionsALS.run(ctx, fn as any);\n}\n\n/**\n * Configure a Liquid instance with custom extensions\n */\nexport function configureLiquidWithExtensions(liquid: Liquid): void {\n // Register the readfile tag\n liquid.registerTag('readfile', ReadFileTag);\n\n // Register parse_json filter to parse JSON strings into objects\n liquid.registerFilter('parse_json', (value: string) => {\n if (typeof value !== 'string') {\n return value;\n }\n try {\n return JSON.parse(value);\n } catch {\n // Return original value if parsing fails\n return value;\n }\n });\n\n // Register to_json filter as alias for json (for consistency)\n liquid.registerFilter('to_json', (value: unknown) => {\n try {\n return JSON.stringify(value);\n } catch {\n return '[Error: Unable to serialize to JSON]';\n }\n });\n\n // Sanitize a label to allowed characters only: [A-Za-z0-9:/]\n liquid.registerFilter('safe_label', (value: unknown) => sanitizeLabel(value));\n\n // Sanitize an array of labels\n liquid.registerFilter('safe_label_list', (value: unknown) => sanitizeLabelList(value));\n\n // Convert literal escape sequences (e.g., \"\\n\") into actual newlines\n liquid.registerFilter('unescape_newlines', (value: unknown) => {\n if (value == null) return '';\n const s = String(value);\n return s.replace(/\\\\n/g, '\\n').replace(/\\\\r/g, '\\r').replace(/\\\\t/g, '\\t');\n });\n\n // Register author permission filters (from main)\n // These filters check the author's permission level; detect local mode for tests\n const isLocal = detectLocalMode();\n\n const resolveAssoc = (val: unknown): string | undefined => {\n if (typeof val === 'string' && val.length > 0) return val;\n const store = permissionsALS.getStore();\n return store?.authorAssociation;\n };\n\n liquid.registerFilter('has_min_permission', (authorAssociation: unknown, level: string) => {\n return hasMinPermission(resolveAssoc(authorAssociation), level as any, isLocal);\n });\n\n liquid.registerFilter('is_owner', (authorAssociation: unknown) => {\n return isOwner(resolveAssoc(authorAssociation), isLocal);\n });\n\n liquid.registerFilter('is_member', (authorAssociation: unknown) => {\n return isMember(resolveAssoc(authorAssociation), isLocal);\n });\n\n liquid.registerFilter('is_collaborator', (authorAssociation: unknown) => {\n return isCollaborator(resolveAssoc(authorAssociation), isLocal);\n });\n\n liquid.registerFilter('is_contributor', (authorAssociation: unknown) => {\n return isContributor(resolveAssoc(authorAssociation), isLocal);\n });\n\n liquid.registerFilter('is_first_timer', (authorAssociation: unknown) => {\n return isFirstTimer(resolveAssoc(authorAssociation), isLocal);\n });\n\n // Register memory filters for accessing memory store\n const memoryStore = MemoryStore.getInstance();\n\n liquid.registerFilter('memory_get', (key: string, namespace?: string) => {\n if (typeof key !== 'string') {\n return undefined;\n }\n return memoryStore.get(key, namespace);\n });\n\n liquid.registerFilter('memory_has', (key: string, namespace?: string) => {\n if (typeof key !== 'string') {\n return false;\n }\n return memoryStore.has(key, namespace);\n });\n\n liquid.registerFilter('memory_list', (namespace?: string) => {\n return memoryStore.list(namespace);\n });\n}\n\n/**\n * Create a new Liquid instance with custom extensions\n */\nexport function createExtendedLiquid(options: Record<string, unknown> = {}): Liquid {\n const liquid = new Liquid({\n cache: false,\n strictFilters: false,\n strictVariables: false,\n ...options,\n });\n\n configureLiquidWithExtensions(liquid);\n return liquid;\n}\n","/**\n * Author permission utilities for checking GitHub author associations\n *\n * GitHub provides author_association field with these values (in order of privilege):\n * - OWNER: Repository owner\n * - MEMBER: Organization member\n * - COLLABORATOR: Invited collaborator\n * - CONTRIBUTOR: Has contributed before\n * - FIRST_TIME_CONTRIBUTOR: First PR to this repo\n * - FIRST_TIMER: First GitHub contribution ever\n * - NONE: No association\n */\n\nexport type AuthorAssociation =\n | 'OWNER'\n | 'MEMBER'\n | 'COLLABORATOR'\n | 'CONTRIBUTOR'\n | 'FIRST_TIME_CONTRIBUTOR'\n | 'FIRST_TIMER'\n | 'NONE';\n\n/**\n * Permission hierarchy (from highest to lowest privilege)\n */\nconst PERMISSION_HIERARCHY: AuthorAssociation[] = [\n 'OWNER',\n 'MEMBER',\n 'COLLABORATOR',\n 'CONTRIBUTOR',\n 'FIRST_TIME_CONTRIBUTOR',\n 'FIRST_TIMER',\n 'NONE',\n];\n\n/**\n * Get permission level (0 = highest, higher number = lower privilege)\n */\nfunction getPermissionLevel(association: string | undefined): number {\n if (!association) return PERMISSION_HIERARCHY.length; // Treat unknown as lowest\n const index = PERMISSION_HIERARCHY.indexOf(association.toUpperCase() as AuthorAssociation);\n return index === -1 ? PERMISSION_HIERARCHY.length : index;\n}\n\n/**\n * Check if author has at least the specified permission level (>= logic)\n *\n * @param authorAssociation - The author's association from GitHub API\n * @param minPermission - Minimum required permission level\n * @param isLocalMode - Whether running in local/CLI mode (defaults to true for local runs)\n * @returns true if author has at least the specified permission level\n *\n * @example\n * hasMinPermission('MEMBER', 'MEMBER') // true (exact match)\n * hasMinPermission('OWNER', 'MEMBER') // true (owner >= member)\n * hasMinPermission('COLLABORATOR', 'MEMBER') // false (collaborator < member)\n * hasMinPermission(undefined, 'OWNER', true) // true (local mode)\n */\nexport function hasMinPermission(\n authorAssociation: string | undefined,\n minPermission: AuthorAssociation,\n isLocalMode: boolean = false\n): boolean {\n // In local mode (not GitHub Actions), treat as owner\n if (isLocalMode) {\n return true;\n }\n\n const authorLevel = getPermissionLevel(authorAssociation);\n const minLevel = getPermissionLevel(minPermission);\n\n // Lower number = higher privilege, so author must have equal or lower number\n return authorLevel <= minLevel;\n}\n\n/**\n * Check if author is exactly the repository owner\n */\nexport function isOwner(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n): boolean {\n if (isLocalMode) return true;\n return authorAssociation?.toUpperCase() === 'OWNER';\n}\n\n/**\n * Check if author is an organization member or owner\n */\nexport function isMember(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n): boolean {\n if (isLocalMode) return true;\n return hasMinPermission(authorAssociation, 'MEMBER', isLocalMode);\n}\n\n/**\n * Check if author is a collaborator (or higher)\n */\nexport function isCollaborator(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n): boolean {\n if (isLocalMode) return true;\n return hasMinPermission(authorAssociation, 'COLLABORATOR', isLocalMode);\n}\n\n/**\n * Check if author is a contributor (has contributed before)\n */\nexport function isContributor(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n): boolean {\n if (isLocalMode) return true;\n return hasMinPermission(authorAssociation, 'CONTRIBUTOR', isLocalMode);\n}\n\n/**\n * Check if author is a first-time contributor (to this repo or GitHub)\n */\nexport function isFirstTimer(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n): boolean {\n if (isLocalMode) return false; // In local mode, not a first-timer\n const assoc = authorAssociation?.toUpperCase();\n return assoc === 'FIRST_TIME_CONTRIBUTOR' || assoc === 'FIRST_TIMER';\n}\n\n/**\n * Create permission helper functions bound to a specific author association\n * This is used to inject functions into JavaScript execution contexts\n *\n * @param authorAssociation - The author's association from PR data\n * @param isLocalMode - Whether running in local/CLI mode\n */\nexport function createPermissionHelpers(\n authorAssociation: string | undefined,\n isLocalMode: boolean = false\n) {\n return {\n hasMinPermission: (minPermission: AuthorAssociation) =>\n hasMinPermission(authorAssociation, minPermission, isLocalMode),\n isOwner: () => isOwner(authorAssociation, isLocalMode),\n isMember: () => isMember(authorAssociation, isLocalMode),\n isCollaborator: () => isCollaborator(authorAssociation, isLocalMode),\n isContributor: () => isContributor(authorAssociation, isLocalMode),\n isFirstTimer: () => isFirstTimer(authorAssociation, isLocalMode),\n };\n}\n\n/**\n * Determine if we're running in local mode (not GitHub Actions)\n */\nexport function detectLocalMode(): boolean {\n return !process.env.GITHUB_ACTIONS;\n}\n\n/**\n * Resolve the most relevant GitHub author association from an event context.\n * Prefers commenter association for issue_comment events, then issue/PR author,\n * and finally falls back to the provided default association.\n */\nexport function resolveAssociationFromEvent(\n eventContext: any | undefined,\n fallback?: string\n): string | undefined {\n try {\n const ec = eventContext || {};\n return (\n ec?.comment?.author_association ||\n ec?.issue?.author_association ||\n ec?.pull_request?.author_association ||\n fallback\n );\n } catch {\n return fallback;\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { MemoryConfig } from './types/config';\nimport { logger } from './logger';\n\n/**\n * Memory store for persistent key-value storage across checks\n * Supports namespaces for isolation and both in-memory and file-based persistence\n */\nexport class MemoryStore {\n private static instance: MemoryStore;\n private data: Map<string, Map<string, unknown>>; // namespace -> key -> value\n private config: MemoryConfig;\n private initialized = false;\n\n private constructor(config?: MemoryConfig) {\n this.data = new Map();\n this.config = this.normalizeConfig(config);\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(config?: MemoryConfig): MemoryStore {\n if (!MemoryStore.instance) {\n MemoryStore.instance = new MemoryStore(config);\n } else if (config && !MemoryStore.instance.initialized) {\n // Update config if not yet initialized\n MemoryStore.instance.config = MemoryStore.instance.normalizeConfig(config);\n }\n return MemoryStore.instance;\n }\n\n /**\n * Reset singleton instance (for testing)\n */\n static resetInstance(): void {\n MemoryStore.instance = undefined!;\n }\n\n /**\n * Initialize memory store (load from file if configured)\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Auto-load if file storage is configured\n if (this.config.storage === 'file' && this.config.auto_load && this.config.file) {\n try {\n await this.load();\n logger.debug(`Memory store loaded from ${this.config.file}`);\n } catch (error) {\n // If file doesn't exist, that's ok - we'll create it on first save\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n logger.warn(\n `Failed to load memory store from ${this.config.file}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n }\n\n this.initialized = true;\n }\n\n /**\n * Normalize and apply defaults to config\n */\n private normalizeConfig(config?: MemoryConfig): MemoryConfig {\n const storage = config?.storage || 'memory';\n return {\n storage,\n format: config?.format || 'json',\n file: config?.file,\n namespace: config?.namespace || 'default',\n auto_load: config?.auto_load !== false,\n auto_save: config?.auto_save !== false,\n };\n }\n\n /**\n * Get the default namespace\n */\n getDefaultNamespace(): string {\n return this.config.namespace || 'default';\n }\n\n /**\n * Get a value from memory\n */\n get(key: string, namespace?: string): unknown {\n const ns = namespace || this.getDefaultNamespace();\n const nsData = this.data.get(ns);\n return nsData?.get(key);\n }\n\n /**\n * Check if a key exists in memory\n */\n has(key: string, namespace?: string): boolean {\n const ns = namespace || this.getDefaultNamespace();\n const nsData = this.data.get(ns);\n return nsData?.has(key) || false;\n }\n\n /**\n * Set a value in memory (override existing)\n */\n async set(key: string, value: unknown, namespace?: string): Promise<void> {\n const ns = namespace || this.getDefaultNamespace();\n\n // Ensure namespace exists\n if (!this.data.has(ns)) {\n this.data.set(ns, new Map());\n }\n\n const nsData = this.data.get(ns)!;\n nsData.set(key, value);\n\n // Auto-save if configured\n if (this.config.storage === 'file' && this.config.auto_save) {\n await this.save();\n }\n }\n\n /**\n * Append a value to an array in memory\n * If key doesn't exist, creates a new array\n * If key exists but is not an array, converts it to an array\n */\n async append(key: string, value: unknown, namespace?: string): Promise<void> {\n const ns = namespace || this.getDefaultNamespace();\n const existing = this.get(key, ns);\n\n let newValue: unknown[];\n if (existing === undefined) {\n // Create new array\n newValue = [value];\n } else if (Array.isArray(existing)) {\n // Append to existing array\n newValue = [...existing, value];\n } else {\n // Convert single value to array with both values\n newValue = [existing, value];\n }\n\n await this.set(key, newValue, ns);\n }\n\n /**\n * Increment a numeric value in memory\n * If key doesn't exist, initializes to 0 before incrementing\n * If key exists but is not a number, throws an error\n */\n async increment(key: string, amount = 1, namespace?: string): Promise<number> {\n const ns = namespace || this.getDefaultNamespace();\n const existing = this.get(key, ns);\n\n let newValue: number;\n if (existing === undefined || existing === null) {\n // Initialize to 0 and then increment\n newValue = amount;\n } else if (typeof existing === 'number') {\n // Increment existing number\n newValue = existing + amount;\n } else {\n throw new Error(\n `Cannot increment non-numeric value at key '${key}' (type: ${typeof existing})`\n );\n }\n\n await this.set(key, newValue, ns);\n return newValue;\n }\n\n /**\n * Delete a key from memory\n */\n async delete(key: string, namespace?: string): Promise<boolean> {\n const ns = namespace || this.getDefaultNamespace();\n const nsData = this.data.get(ns);\n\n if (!nsData) {\n return false;\n }\n\n const deleted = nsData.delete(key);\n\n // Auto-save if configured\n if (deleted && this.config.storage === 'file' && this.config.auto_save) {\n await this.save();\n }\n\n return deleted;\n }\n\n /**\n * Clear all keys in a namespace (or all namespaces if none specified)\n */\n async clear(namespace?: string): Promise<void> {\n if (namespace) {\n // Clear specific namespace\n this.data.delete(namespace);\n } else {\n // Clear all namespaces\n this.data.clear();\n }\n\n // Auto-save if configured\n if (this.config.storage === 'file' && this.config.auto_save) {\n await this.save();\n }\n }\n\n /**\n * List all keys in a namespace\n */\n list(namespace?: string): string[] {\n const ns = namespace || this.getDefaultNamespace();\n const nsData = this.data.get(ns);\n return nsData ? Array.from(nsData.keys()) : [];\n }\n\n /**\n * List all namespaces\n */\n listNamespaces(): string[] {\n return Array.from(this.data.keys());\n }\n\n /**\n * Get all data in a namespace\n */\n getAll(namespace?: string): Record<string, unknown> {\n const ns = namespace || this.getDefaultNamespace();\n const nsData = this.data.get(ns);\n if (!nsData) {\n return {};\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of nsData.entries()) {\n result[key] = value;\n }\n return result;\n }\n\n /**\n * Load data from file\n */\n async load(): Promise<void> {\n if (!this.config.file) {\n throw new Error('No file path configured for memory store');\n }\n\n const filePath = path.resolve(process.cwd(), this.config.file);\n const content = await fs.readFile(filePath, 'utf-8');\n\n if (this.config.format === 'json') {\n await this.loadFromJson(content);\n } else if (this.config.format === 'csv') {\n await this.loadFromCsv(content);\n } else {\n throw new Error(`Unsupported format: ${this.config.format}`);\n }\n }\n\n /**\n * Save data to file\n */\n async save(): Promise<void> {\n if (!this.config.file) {\n throw new Error('No file path configured for memory store');\n }\n\n const filePath = path.resolve(process.cwd(), this.config.file);\n\n // Ensure directory exists\n const dir = path.dirname(filePath);\n await fs.mkdir(dir, { recursive: true });\n\n let content: string;\n if (this.config.format === 'json') {\n content = this.saveToJson();\n } else if (this.config.format === 'csv') {\n content = this.saveToCsv();\n } else {\n throw new Error(`Unsupported format: ${this.config.format}`);\n }\n\n await fs.writeFile(filePath, content, 'utf-8');\n }\n\n /**\n * Load data from JSON format\n */\n private async loadFromJson(content: string): Promise<void> {\n const data = JSON.parse(content);\n\n // Clear existing data\n this.data.clear();\n\n // Load namespaces\n for (const [namespace, nsData] of Object.entries(data)) {\n if (typeof nsData === 'object' && nsData !== null && !Array.isArray(nsData)) {\n const nsMap = new Map<string, unknown>();\n for (const [key, value] of Object.entries(nsData)) {\n nsMap.set(key, value);\n }\n this.data.set(namespace, nsMap);\n }\n }\n }\n\n /**\n * Save data to JSON format\n */\n private saveToJson(): string {\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [namespace, nsData] of this.data.entries()) {\n const nsObj: Record<string, unknown> = {};\n for (const [key, value] of nsData.entries()) {\n nsObj[key] = value;\n }\n result[namespace] = nsObj;\n }\n\n return JSON.stringify(result, null, 2);\n }\n\n /**\n * Load data from CSV format\n * CSV format: namespace,key,value,type\n */\n private async loadFromCsv(content: string): Promise<void> {\n const lines = content.split('\\n').filter(line => line.trim());\n\n // Skip header if present\n let startIndex = 0;\n if (lines[0]?.startsWith('namespace,')) {\n startIndex = 1;\n }\n\n // Clear existing data\n this.data.clear();\n\n // Track arrays (keys that have multiple values)\n const arrays = new Map<string, Map<string, unknown[]>>(); // namespace -> key -> values[]\n\n for (let i = startIndex; i < lines.length; i++) {\n const line = lines[i];\n const parts = this.parseCsvLine(line);\n\n if (parts.length < 3) {\n logger.warn(`Invalid CSV line ${i + 1}: ${line}`);\n continue;\n }\n\n const [namespace, key, valueStr, typeStr] = parts;\n const value = this.parseCsvValue(valueStr, typeStr);\n\n // Ensure namespace exists in data\n if (!this.data.has(namespace)) {\n this.data.set(namespace, new Map());\n arrays.set(namespace, new Map());\n }\n\n const nsData = this.data.get(namespace)!;\n const nsArrays = arrays.get(namespace)!;\n\n // Check if this is a duplicate key (array)\n if (nsData.has(key)) {\n // Convert to array if not already\n if (!nsArrays.has(key)) {\n const existingValue = nsData.get(key);\n nsArrays.set(key, [existingValue]);\n }\n nsArrays.get(key)!.push(value);\n nsData.set(key, nsArrays.get(key)!);\n } else {\n // First occurrence\n nsData.set(key, value);\n }\n }\n }\n\n /**\n * Save data to CSV format\n */\n private saveToCsv(): string {\n const lines: string[] = ['namespace,key,value,type'];\n\n for (const [namespace, nsData] of this.data.entries()) {\n for (const [key, value] of nsData.entries()) {\n if (Array.isArray(value)) {\n // Multiple rows for arrays\n for (const item of value) {\n lines.push(this.formatCsvLine(namespace, key, item));\n }\n } else {\n // Single row\n lines.push(this.formatCsvLine(namespace, key, value));\n }\n }\n }\n\n return lines.join('\\n') + '\\n';\n }\n\n /**\n * Parse a CSV line, handling quoted values with commas\n */\n private parseCsvLine(line: string): string[] {\n const parts: string[] = [];\n let current = '';\n let inQuotes = false;\n\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n\n if (char === '\"') {\n if (inQuotes && line[i + 1] === '\"') {\n // Escaped quote\n current += '\"';\n i++;\n } else {\n // Toggle quotes\n inQuotes = !inQuotes;\n }\n } else if (char === ',' && !inQuotes) {\n // End of field\n parts.push(current);\n current = '';\n } else {\n current += char;\n }\n }\n\n // Add last field\n parts.push(current);\n\n return parts;\n }\n\n /**\n * Format a CSV line with proper escaping\n */\n private formatCsvLine(namespace: string, key: string, value: unknown): string {\n const type = this.getValueType(value);\n const valueStr = this.formatCsvValue(value);\n\n return `${this.escapeCsv(namespace)},${this.escapeCsv(key)},${valueStr},${type}`;\n }\n\n /**\n * Escape a CSV value\n */\n private escapeCsv(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n }\n\n /**\n * Format a value for CSV storage\n */\n private formatCsvValue(value: unknown): string {\n if (value === null) {\n return '\"\"';\n }\n if (value === undefined) {\n return '\"\"';\n }\n if (typeof value === 'string') {\n return this.escapeCsv(value);\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return this.escapeCsv(String(value));\n }\n // Objects and arrays are serialized as JSON\n return this.escapeCsv(JSON.stringify(value));\n }\n\n /**\n * Parse a CSV value based on its type\n */\n private parseCsvValue(valueStr: string, typeStr?: string): unknown {\n if (!typeStr || typeStr === 'string') {\n return valueStr;\n }\n if (typeStr === 'number') {\n return Number(valueStr);\n }\n if (typeStr === 'boolean') {\n return valueStr === 'true';\n }\n if (typeStr === 'object' || typeStr === 'array') {\n try {\n return JSON.parse(valueStr);\n } catch {\n return valueStr;\n }\n }\n return valueStr;\n }\n\n /**\n * Get the type of a value for CSV storage\n */\n private getValueType(value: unknown): string {\n if (value === null || value === undefined) {\n return 'string';\n }\n if (typeof value === 'number') {\n return 'number';\n }\n if (typeof value === 'boolean') {\n return 'boolean';\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n if (typeof value === 'object') {\n return 'object';\n }\n return 'string';\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): MemoryConfig {\n return { ...this.config };\n }\n}\n"],"mappings":"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","names":["fs","path","path","fs"]}
@@ -11,7 +11,7 @@ import {
11
11
  logger,
12
12
  logger_exports,
13
13
  resolveAssociationFromEvent
14
- } from "./chunk-2U6BIWSY.mjs";
14
+ } from "./chunk-I3GQJIR7.mjs";
15
15
  import {
16
16
  addEvent,
17
17
  addFailIfTriggered,
@@ -2178,7 +2178,7 @@ var PRReviewer = class {
2178
2178
  async reviewPR(owner, repo, prNumber, prInfo, options = {}) {
2179
2179
  const { debug = false, config, checks } = options;
2180
2180
  if (config && checks && checks.length > 0) {
2181
- const { CheckExecutionEngine: CheckExecutionEngine2 } = await import("./check-execution-engine-L73PFZQY.mjs");
2181
+ const { CheckExecutionEngine: CheckExecutionEngine2 } = await import("./check-execution-engine-RORGGGGP.mjs");
2182
2182
  const engine = new CheckExecutionEngine2();
2183
2183
  const { results } = await engine.executeGroupedChecks(
2184
2184
  prInfo,
@@ -8282,6 +8282,18 @@ var CheckExecutionEngine = class _CheckExecutionEngine {
8282
8282
  this.mockOctokit = this.createMockOctokit();
8283
8283
  this.reviewer = new PRReviewer(this.mockOctokit);
8284
8284
  }
8285
+ /**
8286
+ * Enrich event context with authenticated octokit instance
8287
+ * @param eventContext - The event context to enrich
8288
+ * @returns Enriched event context with octokit if available
8289
+ */
8290
+ enrichEventContext(eventContext) {
8291
+ const baseContext = eventContext || {};
8292
+ if (this.actionContext?.octokit) {
8293
+ return { ...baseContext, octokit: this.actionContext.octokit };
8294
+ }
8295
+ return baseContext;
8296
+ }
8285
8297
  /**
8286
8298
  * Lazily create a secure sandbox for routing JS (goto_js, run_js)
8287
8299
  */
@@ -8481,10 +8493,6 @@ ${expr}
8481
8493
  const providerType = targetCfg.type || "ai";
8482
8494
  const prov = this.providerRegistry.getProviderOrThrow(providerType);
8483
8495
  this.setProviderWebhookContext(prov);
8484
- const enrichedEventContext = {
8485
- ...prInfo.eventContext,
8486
- ...this.actionContext?.octokit ? { octokit: this.actionContext.octokit } : {}
8487
- };
8488
8496
  const provCfg = {
8489
8497
  type: providerType,
8490
8498
  prompt: targetCfg.prompt,
@@ -8493,7 +8501,7 @@ ${expr}
8493
8501
  schema: targetCfg.schema,
8494
8502
  group: targetCfg.group,
8495
8503
  checkName: target,
8496
- eventContext: enrichedEventContext,
8504
+ eventContext: this.enrichEventContext(prInfo.eventContext),
8497
8505
  transform: targetCfg.transform,
8498
8506
  transform_js: targetCfg.transform_js,
8499
8507
  env: targetCfg.env,
@@ -9134,8 +9142,7 @@ ${expr}
9134
9142
  const providerConfig = {
9135
9143
  type: checks[0],
9136
9144
  prompt: "all",
9137
- eventContext: prInfo.eventContext,
9138
- // Pass event context for templates
9145
+ eventContext: this.enrichEventContext(prInfo.eventContext),
9139
9146
  ai: timeout ? { timeout } : void 0
9140
9147
  };
9141
9148
  const result = await provider.execute(prInfo, providerConfig);
@@ -9169,8 +9176,7 @@ ${expr}
9169
9176
  type: "ai",
9170
9177
  prompt: focus2,
9171
9178
  focus: focus2,
9172
- eventContext: prInfo.eventContext,
9173
- // Pass event context for templates
9179
+ eventContext: this.enrichEventContext(prInfo.eventContext),
9174
9180
  ai: timeout ? { timeout } : void 0,
9175
9181
  // Inherit global AI provider and model settings if config is available
9176
9182
  ai_provider: config?.ai_provider,
@@ -9325,8 +9331,7 @@ ${expr}
9325
9331
  focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
9326
9332
  schema: checkConfig.schema,
9327
9333
  group: checkConfig.group,
9328
- eventContext: prInfo.eventContext,
9329
- // Pass event context for templates
9334
+ eventContext: this.enrichEventContext(prInfo.eventContext),
9330
9335
  ai: {
9331
9336
  timeout: timeout || 6e5,
9332
9337
  debug,
@@ -9615,7 +9620,7 @@ ${expr}
9615
9620
  if (typeof directContent === "string" && directContent.trim()) {
9616
9621
  return directContent.trim();
9617
9622
  }
9618
- const { createExtendedLiquid: createExtendedLiquid2 } = await import("./liquid-extensions-AFKRYROF.mjs");
9623
+ const { createExtendedLiquid: createExtendedLiquid2 } = await import("./liquid-extensions-GMEGEGC3.mjs");
9619
9624
  const fs5 = await import("fs/promises");
9620
9625
  const path5 = await import("path");
9621
9626
  const liquid = createExtendedLiquid2({
@@ -9684,7 +9689,7 @@ ${expr}
9684
9689
  templateData.authorAssociation = authorAssociation;
9685
9690
  templateData.event = { name: eventName, action: eventAction };
9686
9691
  }
9687
- const { withPermissionsContext } = await import("./liquid-extensions-AFKRYROF.mjs");
9692
+ const { withPermissionsContext } = await import("./liquid-extensions-GMEGEGC3.mjs");
9688
9693
  let authorAssociationForFilters;
9689
9694
  try {
9690
9695
  const anyInfo = _prInfo;
@@ -9930,8 +9935,7 @@ ${expr}
9930
9935
  group: checkConfig.group,
9931
9936
  checkName,
9932
9937
  // Add checkName for sessionID
9933
- eventContext: prInfo.eventContext,
9934
- // Pass event context for templates
9938
+ eventContext: this.enrichEventContext(prInfo.eventContext),
9935
9939
  transform: checkConfig.transform,
9936
9940
  transform_js: checkConfig.transform_js,
9937
9941
  // Important: pass through provider-level timeout from check config
@@ -10118,7 +10122,7 @@ ${expr}
10118
10122
  schema: childCfg.schema,
10119
10123
  group: childCfg.group,
10120
10124
  checkName: childName,
10121
- eventContext: prInfo.eventContext,
10125
+ eventContext: this.enrichEventContext(prInfo.eventContext),
10122
10126
  transform: childCfg.transform,
10123
10127
  transform_js: childCfg.transform_js,
10124
10128
  env: childCfg.env,
@@ -10512,7 +10516,7 @@ ${expr}
10512
10516
  schema: nodeCfg.schema,
10513
10517
  group: nodeCfg.group,
10514
10518
  checkName: node,
10515
- eventContext: prInfo.eventContext,
10519
+ eventContext: this.enrichEventContext(prInfo.eventContext),
10516
10520
  transform: nodeCfg.transform,
10517
10521
  transform_js: nodeCfg.transform_js,
10518
10522
  env: nodeCfg.env,
@@ -11208,8 +11212,7 @@ ${error.stack || ""}` : String(error);
11208
11212
  focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
11209
11213
  schema: checkConfig.schema,
11210
11214
  group: checkConfig.group,
11211
- eventContext: prInfo.eventContext,
11212
- // Pass event context for templates
11215
+ eventContext: this.enrichEventContext(prInfo.eventContext),
11213
11216
  ai: {
11214
11217
  timeout: timeout || 6e5,
11215
11218
  debug,
@@ -11285,8 +11288,7 @@ ${error.stack || ""}` : String(error);
11285
11288
  focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
11286
11289
  schema: checkConfig.schema,
11287
11290
  group: checkConfig.group,
11288
- eventContext: prInfo.eventContext,
11289
- // Pass event context for templates
11291
+ eventContext: this.enrichEventContext(prInfo.eventContext),
11290
11292
  ai: {
11291
11293
  timeout: timeout || 6e5,
11292
11294
  ...checkConfig.ai || {}
@@ -12492,4 +12494,4 @@ ${result.value.result.debug.rawResponse}`;
12492
12494
  export {
12493
12495
  CheckExecutionEngine
12494
12496
  };
12495
- //# sourceMappingURL=chunk-LJHRU3WQ.mjs.map
12497
+ //# sourceMappingURL=chunk-Z47UECAT.mjs.map