nexus-agents 8.47.6 → 8.47.7

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 (31) hide show
  1. package/dist/{chunk-U2PGDAEV.js → chunk-4GDMHCKX.js} +41 -16
  2. package/dist/chunk-4GDMHCKX.js.map +1 -0
  3. package/dist/{chunk-4ISEAPTW.js → chunk-6B7YJMG4.js} +2 -2
  4. package/dist/{chunk-XVKJE3EM.js → chunk-BY6NRKVI.js} +2 -2
  5. package/dist/{chunk-DG3IK7AM.js → chunk-FTOJAN24.js} +2 -2
  6. package/dist/{chunk-MD5GZDWZ.js → chunk-KVWEVIPU.js} +11 -11
  7. package/dist/{chunk-MD5GZDWZ.js.map → chunk-KVWEVIPU.js.map} +1 -1
  8. package/dist/{chunk-2DLBUEWQ.js → chunk-OKSGCMDV.js} +2 -2
  9. package/dist/{chunk-3PMSY3OI.js → chunk-Q7O7SACB.js} +3 -3
  10. package/dist/{chunk-5HHF7O7T.js → chunk-UOYS6IQ4.js} +3 -3
  11. package/dist/cli.js +9 -9
  12. package/dist/{consensus-vote-NTV2KWAE.js → consensus-vote-TAZ2YBDV.js} +4 -4
  13. package/dist/{improvement-review-MS2SD26Z.js → improvement-review-AKJN5RXY.js} +4 -4
  14. package/dist/index.d.ts +35 -2
  15. package/dist/index.js +8 -8
  16. package/dist/{repo-analyze-R6WFDFBV.js → repo-analyze-LNZ3Y6BR.js} +2 -2
  17. package/dist/{repo-security-plan-S6F4U76D.js → repo-security-plan-4JKIYRQH.js} +3 -3
  18. package/dist/{setup-data-dir-4IALX33J.js → setup-data-dir-4ZJEO3GZ.js} +3 -3
  19. package/package.json +1 -1
  20. package/dist/chunk-U2PGDAEV.js.map +0 -1
  21. /package/dist/{chunk-4ISEAPTW.js.map → chunk-6B7YJMG4.js.map} +0 -0
  22. /package/dist/{chunk-XVKJE3EM.js.map → chunk-BY6NRKVI.js.map} +0 -0
  23. /package/dist/{chunk-DG3IK7AM.js.map → chunk-FTOJAN24.js.map} +0 -0
  24. /package/dist/{chunk-2DLBUEWQ.js.map → chunk-OKSGCMDV.js.map} +0 -0
  25. /package/dist/{chunk-3PMSY3OI.js.map → chunk-Q7O7SACB.js.map} +0 -0
  26. /package/dist/{chunk-5HHF7O7T.js.map → chunk-UOYS6IQ4.js.map} +0 -0
  27. /package/dist/{consensus-vote-NTV2KWAE.js.map → consensus-vote-TAZ2YBDV.js.map} +0 -0
  28. /package/dist/{improvement-review-MS2SD26Z.js.map → improvement-review-AKJN5RXY.js.map} +0 -0
  29. /package/dist/{repo-analyze-R6WFDFBV.js.map → repo-analyze-LNZ3Y6BR.js.map} +0 -0
  30. /package/dist/{repo-security-plan-S6F4U76D.js.map → repo-security-plan-4JKIYRQH.js.map} +0 -0
  31. /package/dist/{setup-data-dir-4IALX33J.js.map → setup-data-dir-4ZJEO3GZ.js.map} +0 -0
@@ -191,11 +191,15 @@ function getLanguageRecommendations(language, securityTooling) {
191
191
  }
192
192
  var SAST_TOOLS = /* @__PURE__ */ new Set(["semgrep", "codeql", "snyk"]);
193
193
  var SAST_GAP_MSG = "No SAST/SCA security scanning configured";
194
- function removeSastGapIfToolDetected(gaps, secTools) {
194
+ var SAST_UNVERIFIED_MSG = "SAST/SCA scanning unverified \u2014 .github/workflows could not be listed";
195
+ function removeSastGapIfToolDetected(gaps, secTools, workflowsMeasured) {
196
+ const idx = gaps.indexOf(SAST_GAP_MSG);
197
+ if (idx === -1) return;
195
198
  if (secTools.some((t) => SAST_TOOLS.has(t))) {
196
- const idx = gaps.indexOf(SAST_GAP_MSG);
197
- if (idx !== -1) gaps.splice(idx, 1);
199
+ gaps.splice(idx, 1);
200
+ return;
198
201
  }
202
+ if (!workflowsMeasured) gaps[idx] = SAST_UNVERIFIED_MSG;
199
203
  }
200
204
  function judgedGaps(entries, language, codeowners) {
201
205
  const gaps = [];
@@ -205,14 +209,28 @@ function judgedGaps(entries, language, codeowners) {
205
209
  if (tests.measured && !tests.hasTests) gaps.push("No test directory detected");
206
210
  return gaps;
207
211
  }
208
- function identifyGaps(entries, ciProvider, language, securityTooling, codeowners = {}) {
212
+ function resolveListings(listings) {
213
+ return {
214
+ dotGithubEntries: listings.dotGithubEntries ?? [],
215
+ dotGithubListed: listings.dotGithubListed ?? false,
216
+ workflowsMeasured: listings.workflowsMeasured ?? true
217
+ };
218
+ }
219
+ function resolveObserved(observed) {
220
+ return {
221
+ codeowners: observed.codeowners ?? {},
222
+ workflowsMeasured: observed.workflowsMeasured ?? true
223
+ };
224
+ }
225
+ function identifyGaps(entries, ciProvider, language, securityTooling, observed = {}) {
226
+ const { codeowners, workflowsMeasured } = resolveObserved(observed);
209
227
  const gaps = [];
210
228
  if (ciProvider === null) gaps.push("No CI/CD configuration detected");
211
229
  for (const [files, message] of GAP_RULES) {
212
230
  if (!files.some((f) => entries.includes(f))) gaps.push(message);
213
231
  }
214
232
  gaps.push(...judgedGaps(entries, language, codeowners));
215
- removeSastGapIfToolDetected(gaps, securityTooling ?? []);
233
+ removeSastGapIfToolDetected(gaps, securityTooling ?? [], workflowsMeasured);
216
234
  const hasGenericSecGap = gaps.includes("No SAST/SCA security scanning configured");
217
235
  if (hasGenericSecGap && language !== null && language !== void 0 && securityTooling !== void 0) {
218
236
  const langRecs = getLanguageRecommendations(language, securityTooling);
@@ -220,7 +238,8 @@ function identifyGaps(entries, ciProvider, language, securityTooling, codeowners
220
238
  }
221
239
  return gaps;
222
240
  }
223
- function analyzeRepo(metadata, topLevelEntries, workflowEntries, dotGithubEntries = [], dotGithubListed = false) {
241
+ function analyzeRepo(metadata, topLevelEntries, workflowEntries, listings = {}) {
242
+ const { dotGithubEntries, dotGithubListed, workflowsMeasured } = resolveListings(listings);
224
243
  const ciProvider = detectCiProvider(topLevelEntries);
225
244
  const secTooling = detectSecurityTooling(topLevelEntries, workflowEntries);
226
245
  const tests = detectTestInfraMeasured(topLevelEntries, metadata.language);
@@ -245,9 +264,10 @@ function analyzeRepo(metadata, topLevelEntries, workflowEntries, dotGithubEntrie
245
264
  stars: metadata.stargazers_count,
246
265
  topLevelEntries: [...topLevelEntries],
247
266
  gaps: identifyGaps(topLevelEntries, ciProvider, metadata.language, secTooling, {
248
- entries: dotGithubEntries,
249
- listed: dotGithubListed
250
- })
267
+ codeowners: { entries: dotGithubEntries, listed: dotGithubListed },
268
+ workflowsMeasured
269
+ }),
270
+ workflowsMeasured
251
271
  };
252
272
  }
253
273
  var MARKUP_LANGUAGES = /* @__PURE__ */ new Set([
@@ -392,9 +412,10 @@ async function fetchWorkflowEntries(repoId, exec) {
392
412
  { timeout: 15e3 }
393
413
  );
394
414
  const parsed = JSON.parse(stdout.trim());
395
- return Array.isArray(parsed) ? parsed.filter((e) => typeof e === "string") : [];
415
+ const entries = Array.isArray(parsed) ? parsed.filter((e) => typeof e === "string") : [];
416
+ return { entries, listed: true };
396
417
  } catch {
397
- return [];
418
+ return { entries: [], listed: false };
398
419
  }
399
420
  }
400
421
  async function fetchDotGithubEntries(repoId, exec) {
@@ -410,9 +431,9 @@ async function fetchDotGithubEntries(repoId, exec) {
410
431
  return { entries: [], listed: false };
411
432
  }
412
433
  }
413
- async function analyzeGitHubRepo(input) {
434
+ async function analyzeGitHubRepo(input, execOverride) {
414
435
  const repoId = normalizeRepoId(input.repo);
415
- const exec = await getExecFile();
436
+ const exec = execOverride ?? await getExecFile();
416
437
  const { metadata, entries } = await fetchRepoData(repoId, exec);
417
438
  const primaryLang = await resolveLanguage(repoId, entries, metadata, exec);
418
439
  const enhanced = { ...metadata, language: primaryLang };
@@ -422,9 +443,13 @@ async function analyzeGitHubRepo(input) {
422
443
  const resolved = await resolveLicense(repoId, exec);
423
444
  if (resolved !== null) enhanced.license = { spdx_id: resolved };
424
445
  }
425
- const workflowEntries = entries.includes(".github") ? await fetchWorkflowEntries(repoId, exec) : [];
446
+ const workflows = entries.includes(".github") ? await fetchWorkflowEntries(repoId, exec) : { entries: [], listed: true };
426
447
  const dotGithub = entries.includes(".github") ? await fetchDotGithubEntries(repoId, exec) : { entries: [], listed: true };
427
- return analyzeRepo(enhanced, entries, workflowEntries, dotGithub.entries, dotGithub.listed);
448
+ return analyzeRepo(enhanced, entries, workflows.entries, {
449
+ dotGithubEntries: dotGithub.entries,
450
+ dotGithubListed: dotGithub.listed,
451
+ workflowsMeasured: workflows.listed
452
+ });
428
453
  }
429
454
 
430
455
  export {
@@ -438,4 +463,4 @@ export {
438
463
  analyzeRepo,
439
464
  analyzeGitHubRepo
440
465
  };
441
- //# sourceMappingURL=chunk-U2PGDAEV.js.map
466
+ //# sourceMappingURL=chunk-4GDMHCKX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/tools/repo-analyze.ts"],"sourcesContent":["/* eslint-disable max-lines -- cohesive module, governance allows 400-600 */\n/**\n * nexus-agents/mcp - Repository Analyze Logic\n *\n * Inspects a GitHub repository and returns structured analysis\n * including language, tooling, CI, security, and gap identification.\n *\n * @module mcp/tools/repo-analyze\n * (Source: Issue #1074)\n */\n\nimport { z } from 'zod';\nimport type {\n RepoAnalyzeInput,\n RepoAnalysis,\n CodeownersLookup,\n ExecFileFn,\n GapObservations,\n RepoListings,\n} from './repo-analyze-types.js';\n\n/**\n * Zod schema for the `gh api repos/{repoId}` payload (#2962). Pre-fix the\n * stdout was cast directly via `JSON.parse(...) as GhRepoMetadata`, so any\n * GitHub-side schema drift went unflagged until `analyzeRepo` dereferenced\n * a missing field. Now `safeParse` + a structured error surface the drift\n * with a stdout preview.\n */\nconst GhRepoMetadataSchema = z.object({\n name: z.string(),\n full_name: z.string(),\n description: z.string().nullable(),\n language: z.string().nullable(),\n default_branch: z.string(),\n stargazers_count: z.number(),\n license: z.object({ spdx_id: z.string() }).nullable(),\n});\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Normalize \"owner/repo\" from either \"owner/repo\" or full GitHub URL. */\nexport function normalizeRepoId(input: string): string {\n const urlMatch = /github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?(?:\\/|$)/.exec(input);\n const matched = urlMatch?.[1] ?? '';\n if (matched.length > 0) return matched;\n if (/^[^/]+\\/[^/]+$/.test(input)) return input;\n throw new Error(`Invalid repo format: \"${input}\". Use \"owner/name\" or a GitHub URL.`);\n}\n\n/** Package manager detection rules: [files, manager]. First match wins. */\nconst PACKAGE_MANAGER_RULES: ReadonlyArray<readonly [readonly string[], string]> = [\n [['pnpm-lock.yaml'], 'pnpm'],\n [['yarn.lock'], 'yarn'],\n [['package-lock.json', 'package.json'], 'npm'],\n [['Cargo.toml'], 'cargo'],\n [['go.mod'], 'go'],\n [['requirements.txt', 'pyproject.toml'], 'pip'],\n [['Gemfile'], 'bundler'],\n [['pom.xml'], 'maven'],\n [['build.gradle', 'build.gradle.kts'], 'gradle'],\n];\n\n/** Detect package manager from top-level files. */\nexport function detectPackageManager(entries: readonly string[]): string | null {\n for (const [files, manager] of PACKAGE_MANAGER_RULES) {\n if (files.some((f) => entries.includes(f))) return manager;\n }\n return null;\n}\n\n/** Detect CI provider from directory structure. */\nexport function detectCiProvider(entries: readonly string[]): string | null {\n if (entries.includes('.github')) return 'github-actions';\n if (entries.includes('.gitlab-ci.yml')) return 'gitlab-ci';\n if (entries.includes('Jenkinsfile')) return 'jenkins';\n if (entries.includes('.circleci')) return 'circleci';\n if (entries.includes('.travis.yml')) return 'travis';\n if (entries.includes('azure-pipelines.yml')) return 'azure-devops';\n if (entries.includes('concourse')) return 'concourse';\n return null;\n}\n\n/** Tool names detectable from CI workflow filenames (#1674). */\nconst WORKFLOW_SECURITY_PATTERNS: ReadonlyArray<readonly [string, string]> = [\n ['semgrep', 'semgrep'],\n ['codeql', 'codeql'],\n ['grype', 'grype'],\n ['snyk', 'snyk'],\n];\n\n/** Detect security tools from .github/workflows/ filenames. */\nfunction detectWorkflowSecurity(\n workflowEntries: readonly string[],\n existing: readonly string[]\n): readonly string[] {\n const wfLower = workflowEntries.map((w) => w.toLowerCase());\n const found: string[] = [];\n for (const [pattern, tool] of WORKFLOW_SECURITY_PATTERNS) {\n if (!existing.includes(tool) && wfLower.some((w) => w.includes(pattern))) {\n found.push(tool);\n }\n }\n return found;\n}\n\n/** Root-level config files that imply a security tool is in use. */\nconst ROOT_SECURITY_FILES: ReadonlyArray<readonly [readonly string[], string]> = [\n [['.semgrep.yml', '.semgrep'], 'semgrep'],\n [['.snyk'], 'snyk'],\n [['SECURITY.md'], 'security-policy'],\n [['.grype.yaml'], 'grype'],\n [['CODEOWNERS'], 'codeowners'],\n // gitleaks (#2732). Catches `.gitleaks.toml` (canonical) plus legacy\n // `gitleaks.toml` / `.gitleaksignore` variants. Without this, a repo\n // carrying `.gitleaks.toml` reported `existingTooling` without gitleaks,\n // and `repo_security_plan` then showed `secrets: covered: true,\n // scanners: []` (covered by existing-but-undetected tooling).\n [['.gitleaks.toml', 'gitleaks.toml', '.gitleaksignore'], 'gitleaks'],\n];\n\n/** Detect security tooling from root files and CI workflow filenames (#1674). */\nexport function detectSecurityTooling(\n entries: readonly string[],\n workflowEntries?: readonly string[]\n): readonly string[] {\n const tools: string[] = [];\n for (const [files, tool] of ROOT_SECURITY_FILES) {\n if (files.some((f) => entries.includes(f))) tools.push(tool);\n }\n if (workflowEntries !== undefined) {\n tools.push(...detectWorkflowSecurity(workflowEntries, tools));\n }\n return tools;\n}\n\n/** Detect framework from package manager config. */\nexport function detectFramework(entries: readonly string[]): string | null {\n if (entries.includes('helmfile.yaml') || entries.includes('helmfile.yaml.gotmpl'))\n return 'helmfile';\n if (entries.includes('next.config.js') || entries.includes('next.config.ts')) return 'nextjs';\n if (entries.includes('angular.json')) return 'angular';\n if (entries.includes('vite.config.ts') || entries.includes('vite.config.js')) return 'vite';\n if (entries.includes('tsconfig.json') && entries.includes('package.json')) return 'typescript';\n return null;\n}\n\n/**\n * A LICENSE file under any conventional name (#6018).\n *\n * The previous check was `entries.includes('LICENSE') || includes('LICENSE.md')`,\n * which misses the Rust/Go convention of dual-licensing as `LICENSE-APACHE` +\n * `LICENSE-MIT`. `repo_analyze` therefore reported \"No LICENSE file\" for a repo\n * whose own `topLevelEntries` — in the same response — listed both.\n */\nfunction hasLicenseFileIn(entries: readonly string[]): boolean {\n return entries.some((e) => /^licen[cs]e/i.test(e));\n}\n\n/**\n * CODEOWNERS in any location GitHub honours (#6018).\n *\n * GitHub reads it from the repo root, `.github/`, or `docs/`. Checking only the\n * root reported \"No CODEOWNERS file\" against a repo carrying a 31-line\n * `.github/CODEOWNERS`, which is where most projects put it.\n *\n * `dotGithubEntries` is the listing of `.github/` when it could be fetched;\n * pass an empty array when it could not, in which case a root-only miss is\n * UNMEASURED rather than a gap — see {@link identifyGaps}.\n */\nfunction hasCodeownersFile(\n entries: readonly string[],\n dotGithubEntries: readonly string[],\n docsEntries: readonly string[] = []\n): boolean {\n return (\n entries.includes('CODEOWNERS') ||\n dotGithubEntries.includes('CODEOWNERS') ||\n docsEntries.includes('CODEOWNERS')\n );\n}\n\n/**\n * Whether CODEOWNERS is genuinely absent, as opposed to merely unlooked-at.\n *\n * Returns false — no gap — when `.github/` exists but could not be listed. An\n * absence nobody checked is not a finding, and reporting it as one is the\n * defect this whole change is about (#6018).\n */\nfunction codeownersIsMissing(entries: readonly string[], lookup: CodeownersLookup): boolean {\n if (hasCodeownersFile(entries, lookup.entries ?? [])) return false;\n const unlooked = entries.includes('.github') && lookup.listed !== true;\n return !unlooked;\n}\n\n/** Gap detection rules: [files-any-present, gap message]. */\nconst GAP_RULES: ReadonlyArray<readonly [readonly string[], string]> = [\n [['SECURITY.md'], 'No SECURITY.md policy'],\n // CODEOWNERS and LICENSE are matched by predicate, not exact name — see\n // hasCodeownersFile / hasLicenseFile. GitHub honours CODEOWNERS in three\n // locations and Rust/Go dual-license as LICENSE-APACHE + LICENSE-MIT (#6018).\n [\n ['.semgrep.yml', '.semgrep', '.grype.yaml', '.snyk'],\n 'No SAST/SCA security scanning configured',\n ],\n // Test detection handled separately via detectTestInfra (supports monorepo + co-located patterns)\n [['.gitignore'], 'No .gitignore file'],\n];\n\n/** Scanner recommendation per language. Canonical source: secure-language-stacks. */\ninterface LanguageScanners {\n readonly sast: readonly string[];\n readonly sca: readonly string[];\n}\n\nconst LANGUAGE_SCANNER_MATRIX: Readonly<Record<string, LanguageScanners>> = {\n TypeScript: {\n sast: ['semgrep (p/typescript, p/nodejs)', 'eslint-plugin-security'],\n sca: ['osv-scanner', 'npm audit'],\n },\n JavaScript: {\n sast: ['semgrep (p/javascript, p/nodejs)', 'eslint-plugin-security'],\n sca: ['osv-scanner', 'npm audit'],\n },\n Python: {\n sast: ['semgrep (p/python)', 'bandit'],\n sca: ['osv-scanner', 'pip-audit'],\n },\n Java: {\n sast: ['semgrep (p/java)', 'spotbugs + find-sec-bugs'],\n sca: ['osv-scanner', 'OWASP dependency-check'],\n },\n Go: {\n sast: ['semgrep (p/golang)', 'gosec'],\n sca: ['osv-scanner', 'govulncheck'],\n },\n Rust: {\n sast: ['semgrep (p/rust)'],\n sca: ['osv-scanner', 'cargo-audit'],\n },\n 'C++': {\n sast: ['semgrep (p/c)', 'cppcheck'],\n sca: ['osv-scanner'],\n },\n C: {\n sast: ['semgrep (p/c)', 'cppcheck'],\n sca: ['osv-scanner'],\n },\n Kotlin: {\n sast: ['semgrep (p/kotlin)', 'detekt'],\n sca: ['osv-scanner', 'OWASP dependency-check'],\n },\n Swift: {\n sast: ['semgrep (p/swift)'],\n sca: ['osv-scanner'],\n },\n Ruby: {\n sast: ['semgrep (p/ruby)', 'brakeman'],\n sca: ['osv-scanner', 'bundler-audit'],\n },\n PHP: {\n sast: ['semgrep (p/php)', 'phpstan'],\n sca: ['osv-scanner', 'composer audit'],\n },\n Shell: {\n sast: ['semgrep (p/bash)', 'shellcheck'],\n sca: [],\n },\n HCL: {\n sast: ['semgrep (p/terraform)', 'tfsec'],\n sca: ['osv-scanner'],\n },\n};\n\n/** Generate language-specific scanner recommendations when SAST/SCA is missing. */\nexport function getLanguageRecommendations(\n language: string | null,\n securityTooling: readonly string[]\n): readonly string[] {\n if (language === null) return [];\n const scanners = LANGUAGE_SCANNER_MATRIX[language];\n if (scanners === undefined) return [];\n\n const hasSast = securityTooling.includes('semgrep') || securityTooling.includes('snyk');\n const hasSca =\n securityTooling.includes('osv-scanner') ||\n securityTooling.includes('grype') ||\n securityTooling.includes('snyk');\n\n const recs: string[] = [];\n if (!hasSast && scanners.sast.length > 0) {\n const tools = scanners.sast.join(', ');\n recs.push(`${language} project missing SAST: ${tools}`);\n }\n if (!hasSca && scanners.sca.length > 0) {\n const tools = scanners.sca.join(', ');\n recs.push(`${language} project missing SCA: ${tools}`);\n }\n return recs;\n}\n\n/** SAST tool names that suppress the generic gap message. */\nconst SAST_TOOLS = new Set(['semgrep', 'codeql', 'snyk']);\nconst SAST_GAP_MSG = 'No SAST/SCA security scanning configured';\n\n/** What the SAST gap says when the workflows listing failed (#6035). */\nconst SAST_UNVERIFIED_MSG = 'SAST/SCA scanning unverified — .github/workflows could not be listed';\n\n/**\n * Resolve the SAST/SCA gap against what was actually observed (#1674, #6035).\n *\n * Three outcomes, not two. A detected tool removes the gap. An unmeasured\n * workflows listing REPLACES the assertion with an unverified statement,\n * because CI-level SAST detection is exactly what that listing provides — with\n * it absent, \"no scanning is configured\" is a claim the analysis cannot make.\n * Only a successful listing that found nothing leaves the gap asserted.\n */\nfunction removeSastGapIfToolDetected(\n gaps: string[],\n secTools: readonly string[],\n workflowsMeasured: boolean\n): void {\n const idx = gaps.indexOf(SAST_GAP_MSG);\n if (idx === -1) return;\n if (secTools.some((t) => SAST_TOOLS.has(t))) {\n gaps.splice(idx, 1);\n return;\n }\n if (!workflowsMeasured) gaps[idx] = SAST_UNVERIFIED_MSG;\n}\n\n/**\n * The three gaps that cannot be judged from an exact-filename table (#6018).\n *\n * Each needs either a glob (LICENSE-APACHE), a second directory listing\n * (.github/CODEOWNERS), or the repo's language (Rust keeps tests where a\n * top-level listing cannot see them). Extracted from {@link identifyGaps} to\n * keep that function under the complexity cap, and because these three share a\n * property the table-driven rules do not: each can be UNMEASURABLE, and must\n * stay silent rather than assert an absence nobody checked.\n */\nfunction judgedGaps(\n entries: readonly string[],\n language: string | null | undefined,\n codeowners: CodeownersLookup\n): string[] {\n const gaps: string[] = [];\n if (!hasLicenseFileIn(entries)) gaps.push('No LICENSE file');\n if (codeownersIsMissing(entries, codeowners)) gaps.push('No CODEOWNERS file');\n const tests = detectTestInfraMeasured(entries, language ?? null);\n if (tests.measured && !tests.hasTests) gaps.push('No test directory detected');\n return gaps;\n}\n\n/**\n * Apply the listing defaults in ONE place.\n *\n * Inline `??` chains at each use site put the defaults inside the functions\n * that consume them, which tipped both past the complexity cap and — more to\n * the point — scattered the decision about what an omitted listing means.\n * `workflowsMeasured` defaults TRUE because an omitted flag comes from a caller\n * that did no listing at all (the unit-test callers), not from a failed one;\n * a failed listing passes false explicitly.\n */\nfunction resolveListings(listings: RepoListings): Required<RepoListings> {\n return {\n dotGithubEntries: listings.dotGithubEntries ?? [],\n dotGithubListed: listings.dotGithubListed ?? false,\n workflowsMeasured: listings.workflowsMeasured ?? true,\n };\n}\n\n/**\n * Apply the observation defaults in one place, for the same reason\n * {@link resolveListings} exists: inline `??`/destructuring defaults inside\n * `identifyGaps` pushed it past the complexity cap, and scattered the decision\n * about what an omitted observation means.\n */\nfunction resolveObserved(observed: GapObservations): Required<GapObservations> {\n return {\n codeowners: observed.codeowners ?? {},\n workflowsMeasured: observed.workflowsMeasured ?? true,\n };\n}\n\n/** Identify gaps in repository best practices. */\nexport function identifyGaps(\n entries: readonly string[],\n ciProvider: string | null,\n language?: string | null,\n securityTooling?: readonly string[],\n /**\n * What the listings actually observed. Bundled rather than two more\n * positional params: they travel together, they are both \"what did we manage\n * to measure\" rather than \"what did we find\", and two more defaults tipped\n * this function past the complexity cap.\n */\n observed: GapObservations = {}\n): readonly string[] {\n const { codeowners, workflowsMeasured } = resolveObserved(observed);\n const gaps: string[] = [];\n if (ciProvider === null) gaps.push('No CI/CD configuration detected');\n for (const [files, message] of GAP_RULES) {\n if (!files.some((f) => entries.includes(f))) gaps.push(message);\n }\n\n gaps.push(...judgedGaps(entries, language, codeowners));\n\n // Resolve the SAST/SCA gap against what was observed (#1674, #6035)\n removeSastGapIfToolDetected(gaps, securityTooling ?? [], workflowsMeasured);\n\n // Language-specific recommendations when generic SAST/SCA gap detected\n const hasGenericSecGap = gaps.includes('No SAST/SCA security scanning configured');\n if (\n hasGenericSecGap &&\n language !== null &&\n language !== undefined &&\n securityTooling !== undefined\n ) {\n const langRecs = getLanguageRecommendations(language, securityTooling);\n gaps.push(...langRecs);\n }\n\n return gaps;\n}\n\n// ============================================================================\n// Core\n// ============================================================================\n\n/** GitHub repo metadata from the API. */\nexport interface GhRepoMetadata {\n readonly name: string;\n readonly full_name: string;\n readonly description: string | null;\n readonly language: string | null;\n readonly default_branch: string;\n readonly stargazers_count: number;\n readonly license: { readonly spdx_id: string } | null;\n}\n\n/** Analyze a GitHub repository given its metadata and file tree. */\nexport function analyzeRepo(\n metadata: GhRepoMetadata,\n topLevelEntries: readonly string[],\n workflowEntries?: readonly string[],\n /** What each secondary listing observed — grouped, not four positional flags. */\n listings: RepoListings = {}\n): RepoAnalysis {\n const { dotGithubEntries, dotGithubListed, workflowsMeasured } = resolveListings(listings);\n const ciProvider = detectCiProvider(topLevelEntries);\n const secTooling = detectSecurityTooling(topLevelEntries, workflowEntries);\n const tests = detectTestInfraMeasured(topLevelEntries, metadata.language);\n\n return {\n name: metadata.full_name,\n language: metadata.language,\n framework: detectFramework(topLevelEntries),\n packageManager: detectPackageManager(topLevelEntries),\n ciProvider,\n securityTooling: secTooling,\n // Match `Dockerfile`, `Dockerfile.<purpose>` (e.g. `Dockerfile.sandbox`),\n // and docker-compose variants. Pre-#2730 the check was exact-match only,\n // so a repo with three legitimate `Dockerfile.*` files reported false.\n hasDockerfile:\n topLevelEntries.some((e) => e === 'Dockerfile' || e.startsWith('Dockerfile.')) ||\n topLevelEntries.includes('docker-compose.yml') ||\n topLevelEntries.includes('docker-compose.yaml'),\n hasHelmCharts:\n topLevelEntries.includes('Chart.yaml') ||\n topLevelEntries.includes('charts') ||\n topLevelEntries.includes('helm'),\n hasMakefile: topLevelEntries.includes('Makefile'),\n hasTests: tests.hasTests,\n testsMeasured: tests.measured,\n license: metadata.license?.spdx_id ?? null,\n description: metadata.description,\n defaultBranch: metadata.default_branch,\n stars: metadata.stargazers_count,\n topLevelEntries: [...topLevelEntries],\n gaps: identifyGaps(topLevelEntries, ciProvider, metadata.language, secTooling, {\n codeowners: { entries: dotGithubEntries, listed: dotGithubListed },\n workflowsMeasured,\n }),\n workflowsMeasured,\n };\n}\n\n/** Non-code languages to exclude when detecting primary language. */\nconst MARKUP_LANGUAGES = new Set([\n 'HTML',\n 'CSS',\n 'SCSS',\n 'Less',\n 'Markdown',\n 'Roff',\n 'SVG',\n 'XML',\n 'XSLT',\n 'Mustache',\n 'Handlebars',\n 'EJS',\n]);\n\n/** Detect primary language from GitHub languages API (byte counts). */\nfunction detectPrimaryLanguage(\n languages: Record<string, number>,\n fallback: string | null\n): string | null {\n const sorted = Object.entries(languages)\n .filter(([lang]) => !MARKUP_LANGUAGES.has(lang))\n .sort((a, b) => b[1] - a[1]);\n const top = sorted[0];\n return top !== undefined ? top[0] : fallback;\n}\n\n/** Check for test infrastructure beyond top-level directories. */\nfunction detectTestInfra(entries: readonly string[]): boolean {\n const testDirs = ['tests', 'test', '__tests__', 'spec'];\n if (testDirs.some((d) => entries.includes(d))) return true;\n // Check for test config files (co-located test pattern, monorepos)\n const testConfigs = [\n 'vitest.config.ts',\n 'vitest.config.js',\n 'vitest.config.mts',\n 'vitest.workspace.ts',\n 'vitest.workspace.js',\n 'jest.config.ts',\n 'jest.config.js',\n 'jest.config.mjs',\n 'cypress.config.ts',\n 'cypress.config.js',\n 'playwright.config.ts',\n '.mocharc.yml',\n '.mocharc.json',\n ];\n if (testConfigs.some((c) => entries.includes(c))) return true;\n // Monorepo: packages/ dir + package.json implies co-located tests\n return entries.includes('packages') && entries.includes('package.json');\n}\n\n/**\n * Languages whose test layout the probes above actually understand.\n *\n * The list is the honest boundary of {@link detectTestInfra}: every rule in it\n * looks for a JS/TS-shaped root `tests/` directory or a JS test-runner config.\n * A language absent from this list is not \"a repo without tests\" — it is a repo\n * this function cannot measure, and #6018 is what happens when the two are\n * conflated (a 9-crate Rust workspace with 1385 `#[test]` functions reported\n * `hasTests: false` and \"No test directory detected\").\n *\n * Adding a language here is a promise that the probes below recognise its\n * conventions. Rust is deliberately ABSENT: its tests live in `#[cfg(test)]`\n * modules inside source files and in per-crate `tests/` directories, neither of\n * which a top-level listing can see.\n */\nconst TEST_DETECTABLE_LANGUAGES: ReadonlySet<string> = new Set([\n 'TypeScript',\n 'JavaScript',\n 'Python',\n 'Ruby',\n 'PHP',\n]);\n\n/** Test detection plus whether it was measurable at all (#6018). */\ninterface TestInfraVerdict {\n readonly hasTests: boolean;\n readonly measured: boolean;\n}\n\n/**\n * Detect tests, reporting `measured: false` when the repo's language has no\n * probe rather than reporting a JS-shaped absence as a finding (#6018).\n *\n * A positive detection is trusted regardless of language: a root `tests/`\n * directory means tests whoever wrote it. Only the NEGATIVE needs the\n * language guard, because that is the direction that fabricates a gap.\n */\nfunction detectTestInfraMeasured(\n entries: readonly string[],\n language: string | null\n): TestInfraVerdict {\n const detected = detectTestInfra(entries);\n if (detected) return { hasTests: true, measured: true };\n const measured = language !== null && TEST_DETECTABLE_LANGUAGES.has(language);\n return { hasTests: false, measured };\n}\n\n/** Infer code language from project files when GitHub reports markup. */\nfunction inferLanguageFromEntries(\n entries: readonly string[],\n fallback: string | null\n): string | null {\n if (entries.includes('tsconfig.json')) return 'TypeScript';\n if (entries.includes('Cargo.toml')) return 'Rust';\n if (entries.includes('go.mod')) return 'Go';\n if (entries.includes('pyproject.toml') || entries.includes('setup.py')) return 'Python';\n if (entries.includes('pom.xml') || entries.includes('build.gradle')) return 'Java';\n if (entries.includes('Gemfile')) return 'Ruby';\n if (entries.includes('package.json')) return 'JavaScript';\n return fallback;\n}\n\n/** Lazy-load promisified execFile. */\nasync function getExecFile(): Promise<ExecFileFn> {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n return promisify(execFile);\n}\n\n/** Fetch repo metadata and languages via GitHub API. */\nasync function fetchRepoData(\n repoId: string,\n exec: ExecFileFn\n): Promise<{ metadata: GhRepoMetadata; entries: string[] }> {\n const { stdout: metaJson } = await exec(\n 'gh',\n [\n 'api',\n `repos/${repoId}`,\n '--jq',\n '{name: .name, full_name: .full_name, description: .description, language: .language, default_branch: .default_branch, stargazers_count: .stargazers_count, license: .license}',\n ],\n { timeout: 30_000 }\n );\n let parsed: unknown;\n try {\n parsed = JSON.parse(metaJson.trim());\n } catch {\n throw new Error(`Failed to parse repo metadata for ${repoId}: ${metaJson.slice(0, 200)}`);\n }\n // Closes #2962 (P1): Zod-validate the parsed JSON instead of casting\n // blindly. Pre-fix, a GitHub-side schema drift produced a typed-but-\n // mismatched object that crashed deep in `analyzeRepo` or silently\n // surfaced a wrong field (e.g., enhanced.license.spdx_id null →\n // \"no license\" — same shape as #2943).\n const validated = GhRepoMetadataSchema.safeParse(parsed);\n if (!validated.success) {\n throw new Error(\n `Repo metadata schema mismatch for ${repoId}: ${validated.error.message} ` +\n `(payload preview: ${metaJson.slice(0, 200)})`\n );\n }\n const metadata: GhRepoMetadata = validated.data;\n const { stdout: contentsJson } = await exec(\n 'gh',\n ['api', `repos/${repoId}/contents`, '--jq', '[.[].name]'],\n { timeout: 30_000 }\n );\n let entries: string[];\n try {\n const parsed: unknown = JSON.parse(contentsJson.trim());\n entries = Array.isArray(parsed) ? parsed.filter((e): e is string => typeof e === 'string') : [];\n } catch {\n throw new Error(`Failed to parse repo contents for ${repoId}: ${contentsJson.slice(0, 200)}`);\n }\n return { metadata, entries };\n}\n\n/** Resolve NOASSERTION license via the GitHub license API. */\nasync function resolveLicense(repoId: string, exec: ExecFileFn): Promise<string | null> {\n try {\n const { stdout } = await exec(\n 'gh',\n ['api', `repos/${repoId}/license`, '--jq', '.license.spdx_id'],\n { timeout: 15_000 }\n );\n const spdxId = stdout.trim();\n if (spdxId !== '' && spdxId !== 'null' && spdxId !== 'NOASSERTION') {\n return spdxId;\n }\n } catch {\n // Keep NOASSERTION if license API also fails\n }\n return null;\n}\n\n/** Resolve primary language, falling back to entry inference for markup repos. */\nasync function resolveLanguage(\n repoId: string,\n entries: readonly string[],\n metadata: GhRepoMetadata,\n exec: ExecFileFn\n): Promise<string | null> {\n let languages: Record<string, number> = {};\n try {\n const { stdout } = await exec('gh', ['api', `repos/${repoId}/languages`], { timeout: 15_000 });\n languages = JSON.parse(stdout.trim()) as Record<string, number>;\n } catch {\n /* fall back to metadata.language */\n }\n const primary = detectPrimaryLanguage(languages, metadata.language);\n if (primary === null || MARKUP_LANGUAGES.has(primary)) {\n return inferLanguageFromEntries(entries, primary);\n }\n return primary;\n}\n\n/**\n * Fetch workflow filenames from `.github/workflows/` (#1674).\n *\n * Returns `listed: false` when the directory could not be read (#6035), so a\n * miss stays unmeasured instead of becoming a false gap — the same discipline\n * {@link fetchDotGithubEntries} got in #6018. This one returned a bare `[]` on\n * any error, which is indistinguishable from a repo with no workflows, and\n * `removeSastGapIfToolDetected` then left \"No SAST/SCA security scanning\n * configured\" standing for a repo running CodeQL. A 403 from a secondary rate\n * limit or a token without `contents` scope was enough.\n */\nasync function fetchWorkflowEntries(\n repoId: string,\n exec: ExecFileFn\n): Promise<{ entries: readonly string[]; listed: boolean }> {\n try {\n const { stdout } = await exec(\n 'gh',\n ['api', `repos/${repoId}/contents/.github/workflows`, '--jq', '[.[].name]'],\n { timeout: 15_000 }\n );\n const parsed: unknown = JSON.parse(stdout.trim());\n const entries = Array.isArray(parsed)\n ? parsed.filter((e): e is string => typeof e === 'string')\n : [];\n return { entries, listed: true };\n } catch {\n // Cannot distinguish \"no workflows directory\" from \"the API call failed\",\n // so report the weaker claim. A 404 for a repo with no workflows is\n // therefore also unmeasured here; the SAST gap is then stated as unverified\n // rather than asserted, which is the honest reading of both.\n return { entries: [], listed: false };\n }\n}\n\n/**\n * Fetch the `.github/` listing so CODEOWNERS can be found where GitHub actually\n * honours it (#6018). Returns `listed: false` when the directory could not be\n * read, so a miss stays unmeasured instead of becoming a false gap.\n */\nasync function fetchDotGithubEntries(\n repoId: string,\n exec: ExecFileFn\n): Promise<{ entries: readonly string[]; listed: boolean }> {\n try {\n const { stdout } = await exec(\n 'gh',\n ['api', `repos/${repoId}/contents/.github`, '--jq', '[.[].name]'],\n { timeout: 15_000 }\n );\n const parsed: unknown = JSON.parse(stdout.trim());\n return Array.isArray(parsed)\n ? { entries: parsed.filter((e): e is string => typeof e === 'string'), listed: true }\n : { entries: [], listed: false };\n } catch {\n return { entries: [], listed: false };\n }\n}\n\n/** Fetch repo data from GitHub and produce analysis. */\nexport async function analyzeGitHubRepo(\n input: RepoAnalyzeInput,\n /**\n * Injected `gh` runner, so the FETCH path is testable and not only the\n * pure functions downstream of it (#6035).\n *\n * Without this, reverting `fetchWorkflowEntries` to report `listed: true`\n * on error broke no test: the flag was exercised by injecting it into\n * `identifyGaps` directly, while the producer that derives it had no\n * coverage at all. Every other fetch in this module already takes an\n * `ExecFileFn`; the entry point was the one place that did not.\n */\n execOverride?: ExecFileFn\n): Promise<RepoAnalysis> {\n const repoId = normalizeRepoId(input.repo);\n const exec = execOverride ?? (await getExecFile());\n const { metadata, entries } = await fetchRepoData(repoId, exec);\n\n const primaryLang = await resolveLanguage(repoId, entries, metadata, exec);\n const enhanced = { ...metadata, language: primaryLang };\n\n // Resolve null or NOASSERTION license when LICENSE file exists\n const hasLicenseFile = hasLicenseFileIn(entries);\n const licenseUnresolved = enhanced.license === null || enhanced.license.spdx_id === 'NOASSERTION';\n if (licenseUnresolved && hasLicenseFile) {\n const resolved = await resolveLicense(repoId, exec);\n if (resolved !== null) enhanced.license = { spdx_id: resolved };\n }\n\n // Fetch workflow filenames for CI-level security detection (#1674)\n const workflows = entries.includes('.github')\n ? await fetchWorkflowEntries(repoId, exec)\n : { entries: [] as readonly string[], listed: true }; // no .github/ at all = measured absence\n const dotGithub = entries.includes('.github')\n ? await fetchDotGithubEntries(repoId, exec)\n : { entries: [] as readonly string[], listed: true }; // no .github/ at all = measured absence\n\n return analyzeRepo(enhanced, entries, workflows.entries, {\n dotGithubEntries: dotGithub.entries,\n dotGithubListed: dotGithub.listed,\n workflowsMeasured: workflows.listed,\n });\n}\n"],"mappings":"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","names":["parsed"]}
@@ -1,6 +1,6 @@
1
1
  // src/version.ts
2
2
  import semver from "semver";
3
- var VERSION = true ? "8.47.6" : "dev";
3
+ var VERSION = true ? "8.47.7" : "dev";
4
4
  var NODE_ENGINE_RANGE = ">=22.5.0";
5
5
  function isNodeVersionSupported(version) {
6
6
  return semver.satisfies(version, NODE_ENGINE_RANGE);
@@ -11,4 +11,4 @@ export {
11
11
  NODE_ENGINE_RANGE,
12
12
  isNodeVersionSupported
13
13
  };
14
- //# sourceMappingURL=chunk-4ISEAPTW.js.map
14
+ //# sourceMappingURL=chunk-6B7YJMG4.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  analyzeGitHubRepo
3
- } from "./chunk-U2PGDAEV.js";
3
+ } from "./chunk-4GDMHCKX.js";
4
4
  import {
5
5
  createLogger,
6
6
  getTimeProvider
@@ -721,4 +721,4 @@ export {
721
721
  generateSecurityPlan,
722
722
  buildPlanFromAnalysis
723
723
  };
724
- //# sourceMappingURL=chunk-XVKJE3EM.js.map
724
+ //# sourceMappingURL=chunk-BY6NRKVI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-4ISEAPTW.js";
3
+ } from "./chunk-6B7YJMG4.js";
4
4
  import {
5
5
  emitClawGuardViolation
6
6
  } from "./chunk-MWQ2UYSX.js";
@@ -2317,4 +2317,4 @@ export {
2317
2317
  VOTING_THRESHOLDS,
2318
2318
  ConsensusMetricsSchema
2319
2319
  };
2320
- //# sourceMappingURL=chunk-DG3IK7AM.js.map
2320
+ //# sourceMappingURL=chunk-FTOJAN24.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  generateSecurityPlan
3
- } from "./chunk-XVKJE3EM.js";
3
+ } from "./chunk-BY6NRKVI.js";
4
4
  import {
5
5
  analyzeGitHubRepo
6
- } from "./chunk-U2PGDAEV.js";
6
+ } from "./chunk-4GDMHCKX.js";
7
7
  import {
8
8
  CodebaseIndex,
9
9
  DEFAULT_INDEX_MAX_DEPTH,
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  DEFAULT_TASK_TTL_MS,
23
23
  clampTaskTtl
24
- } from "./chunk-5HHF7O7T.js";
24
+ } from "./chunk-UOYS6IQ4.js";
25
25
  import {
26
26
  executeExpert
27
27
  } from "./chunk-RVPB3BHL.js";
@@ -55,7 +55,7 @@ import {
55
55
  toJobSummary,
56
56
  updateStage,
57
57
  writeJobCancelled
58
- } from "./chunk-3PMSY3OI.js";
58
+ } from "./chunk-Q7O7SACB.js";
59
59
  import {
60
60
  allOf,
61
61
  anyOf
@@ -75,7 +75,7 @@ import {
75
75
  } from "./chunk-JOP5NFAQ.js";
76
76
  import {
77
77
  withPrerequisite
78
- } from "./chunk-2DLBUEWQ.js";
78
+ } from "./chunk-OKSGCMDV.js";
79
79
  import {
80
80
  NOOP_NOTIFIER,
81
81
  RateLimiter,
@@ -100,7 +100,7 @@ import {
100
100
  withAuditTrail,
101
101
  withProgressHeartbeat,
102
102
  wrapToolWithTimeout
103
- } from "./chunk-DG3IK7AM.js";
103
+ } from "./chunk-FTOJAN24.js";
104
104
  import {
105
105
  createAuditTrail,
106
106
  createGraphAuditBridge,
@@ -46140,7 +46140,7 @@ function buildVotingInput(plan, config) {
46140
46140
  }
46141
46141
  async function executeSingleVote(plan, config, log) {
46142
46142
  try {
46143
- const { executeVoting } = await import("./consensus-vote-NTV2KWAE.js");
46143
+ const { executeVoting } = await import("./consensus-vote-TAZ2YBDV.js");
46144
46144
  const input = buildVotingInput(plan, config);
46145
46145
  const result = await executeVoting(input, log);
46146
46146
  return parseVotingResult(result);
@@ -47935,7 +47935,7 @@ ${contextBlock}`;
47935
47935
  const strategy = config.votingStrategy ?? "higher_order";
47936
47936
  await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
47937
47937
  try {
47938
- const { executeVoting } = await import("./consensus-vote-NTV2KWAE.js");
47938
+ const { executeVoting } = await import("./consensus-vote-TAZ2YBDV.js");
47939
47939
  const votingResult = await executeVoting(
47940
47940
  {
47941
47941
  proposal: buildVoteProposal(plan, research),
@@ -48418,7 +48418,7 @@ function createAnalyzeStageWrapper() {
48418
48418
  true
48419
48419
  );
48420
48420
  }
48421
- const { analyzeGitHubRepo: analyzeGitHubRepo2 } = await import("./repo-analyze-R6WFDFBV.js");
48421
+ const { analyzeGitHubRepo: analyzeGitHubRepo2 } = await import("./repo-analyze-LNZ3Y6BR.js");
48422
48422
  const analysis = await analyzeGitHubRepo2({ repo: slug, depth: "deep" });
48423
48423
  const summary = `Language: ${String(analysis.language)}, Framework: ${String(analysis.framework)}, CI: ${String(analysis.ciProvider)}, Security: ${analysis.securityTooling.join(", ") || "none"}`;
48424
48424
  return output(PIPELINE_STATE_KEYS.RESEARCH, summary, getTimeProvider().now() - start, true);
@@ -48437,7 +48437,7 @@ function createScanStageWrapper() {
48437
48437
  try {
48438
48438
  const slug = ctx.task.match(/([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+)/)?.[1];
48439
48439
  if (slug !== void 0) {
48440
- const { generateSecurityPlan: generateSecurityPlan2 } = await import("./repo-security-plan-S6F4U76D.js");
48440
+ const { generateSecurityPlan: generateSecurityPlan2 } = await import("./repo-security-plan-4JKIYRQH.js");
48441
48441
  const plan = await generateSecurityPlan2({ repo: slug, maxScanners: 10 });
48442
48442
  const recs = plan.recommendations.slice(0, 5).map((r) => `${r.priority}: ${r.displayName} (${r.category})`).join("; ");
48443
48443
  return output(PIPELINE_STATE_KEYS.FINDINGS, recs, getTimeProvider().now() - start, true);
@@ -56676,4 +56676,4 @@ export {
56676
56676
  startPipelineEventBridge,
56677
56677
  shutdownPipelineEventBridge
56678
56678
  };
56679
- //# sourceMappingURL=chunk-MD5GZDWZ.js.map
56679
+ //# sourceMappingURL=chunk-KVWEVIPU.js.map