nexus-agents 2.77.2 → 2.77.4

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 (37) hide show
  1. package/dist/{chunk-6UDFAXUI.js → chunk-AFGRQB4H.js} +5 -3
  2. package/dist/{chunk-6UDFAXUI.js.map → chunk-AFGRQB4H.js.map} +1 -1
  3. package/dist/{chunk-BC3M4VLP.js → chunk-BMOPMCFZ.js} +5 -2
  4. package/dist/chunk-BMOPMCFZ.js.map +1 -0
  5. package/dist/{chunk-CPPZCNAS.js → chunk-EEW7VFFF.js} +3 -3
  6. package/dist/{chunk-X3BU5MIG.js → chunk-FYAQBYHM.js} +2 -2
  7. package/dist/{chunk-RFITLMH4.js → chunk-LIY6WZNR.js} +24 -212
  8. package/dist/chunk-LIY6WZNR.js.map +1 -0
  9. package/dist/{chunk-VEF6DCQU.js → chunk-MV4R2ZIJ.js} +204 -4
  10. package/dist/chunk-MV4R2ZIJ.js.map +1 -0
  11. package/dist/{chunk-N3HOBUU4.js → chunk-S6MEYRYZ.js} +30 -21
  12. package/dist/{chunk-N3HOBUU4.js.map → chunk-S6MEYRYZ.js.map} +1 -1
  13. package/dist/{chunk-ZKOBXAPK.js → chunk-WXVN4K3D.js} +2 -2
  14. package/dist/cli.d.ts +2 -0
  15. package/dist/cli.js +30 -17
  16. package/dist/cli.js.map +1 -1
  17. package/dist/{consensus-vote-UR3JU7RI.js → consensus-vote-AWBFYF5S.js} +3 -3
  18. package/dist/{expert-bridge-DWBO2HXZ.js → expert-bridge-NX2MGOBQ.js} +2 -2
  19. package/dist/{factory-LXOVC44K.js → factory-JI6PSWGR.js} +2 -2
  20. package/dist/index.d.ts +0 -2
  21. package/dist/index.js +8 -8
  22. package/dist/{repo-analyze-HWMXSK5C.js → repo-analyze-QGLXEFVJ.js} +2 -2
  23. package/dist/{repo-security-plan-EIL2BV3S.js → repo-security-plan-X5CRZ2YY.js} +3 -3
  24. package/dist/{setup-command-ZIG5JJAE.js → setup-command-DB3DOE6K.js} +4 -4
  25. package/package.json +1 -1
  26. package/dist/chunk-BC3M4VLP.js.map +0 -1
  27. package/dist/chunk-RFITLMH4.js.map +0 -1
  28. package/dist/chunk-VEF6DCQU.js.map +0 -1
  29. /package/dist/{chunk-CPPZCNAS.js.map → chunk-EEW7VFFF.js.map} +0 -0
  30. /package/dist/{chunk-X3BU5MIG.js.map → chunk-FYAQBYHM.js.map} +0 -0
  31. /package/dist/{chunk-ZKOBXAPK.js.map → chunk-WXVN4K3D.js.map} +0 -0
  32. /package/dist/{consensus-vote-UR3JU7RI.js.map → consensus-vote-AWBFYF5S.js.map} +0 -0
  33. /package/dist/{expert-bridge-DWBO2HXZ.js.map → expert-bridge-NX2MGOBQ.js.map} +0 -0
  34. /package/dist/{factory-LXOVC44K.js.map → factory-JI6PSWGR.js.map} +0 -0
  35. /package/dist/{repo-analyze-HWMXSK5C.js.map → repo-analyze-QGLXEFVJ.js.map} +0 -0
  36. /package/dist/{repo-security-plan-EIL2BV3S.js.map → repo-security-plan-X5CRZ2YY.js.map} +0 -0
  37. /package/dist/{setup-command-ZIG5JJAE.js.map → setup-command-DB3DOE6K.js.map} +0 -0
@@ -190,7 +190,10 @@ function analyzeRepo(metadata, topLevelEntries, workflowEntries) {
190
190
  packageManager: detectPackageManager(topLevelEntries),
191
191
  ciProvider,
192
192
  securityTooling: secTooling,
193
- hasDockerfile: topLevelEntries.includes("Dockerfile") || topLevelEntries.includes("docker-compose.yml") || topLevelEntries.includes("docker-compose.yaml"),
193
+ // Match `Dockerfile`, `Dockerfile.<purpose>` (e.g. `Dockerfile.sandbox`),
194
+ // and docker-compose variants. Pre-#2730 the check was exact-match only,
195
+ // so a repo with three legitimate `Dockerfile.*` files reported false.
196
+ hasDockerfile: topLevelEntries.some((e) => e === "Dockerfile" || e.startsWith("Dockerfile.")) || topLevelEntries.includes("docker-compose.yml") || topLevelEntries.includes("docker-compose.yaml"),
194
197
  hasHelmCharts: topLevelEntries.includes("Chart.yaml") || topLevelEntries.includes("charts") || topLevelEntries.includes("helm"),
195
198
  hasMakefile: topLevelEntries.includes("Makefile"),
196
199
  hasTests,
@@ -356,4 +359,4 @@ export {
356
359
  analyzeRepo,
357
360
  analyzeGitHubRepo
358
361
  };
359
- //# sourceMappingURL=chunk-BC3M4VLP.js.map
362
+ //# sourceMappingURL=chunk-BMOPMCFZ.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 type { RepoAnalyzeInput, RepoAnalysis } from './repo-analyze-types.js';\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/** 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 if (entries.includes('.semgrep.yml') || entries.includes('.semgrep')) tools.push('semgrep');\n if (entries.includes('.snyk')) tools.push('snyk');\n if (entries.includes('SECURITY.md')) tools.push('security-policy');\n if (entries.includes('.grype.yaml')) tools.push('grype');\n if (entries.includes('CODEOWNERS')) tools.push('codeowners');\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/** 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'], 'No CODEOWNERS file'],\n [['LICENSE', 'LICENSE.md'], 'No LICENSE file'],\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/** Remove the SAST/SCA gap if any SAST tool was detected (#1674). */\nfunction removeSastGapIfToolDetected(gaps: string[], secTools: readonly string[]): void {\n if (secTools.some((t) => SAST_TOOLS.has(t))) {\n const idx = gaps.indexOf(SAST_GAP_MSG);\n if (idx !== -1) gaps.splice(idx, 1);\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): readonly string[] {\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 // Test detection: uses detectTestInfra for monorepo + co-located pattern support (#1130)\n if (!detectTestInfra(entries)) gaps.push('No test directory detected');\n\n // Remove SAST/SCA gap if workflow-level security was detected (#1674)\n removeSastGapIfToolDetected(gaps, securityTooling ?? []);\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): RepoAnalysis {\n const ciProvider = detectCiProvider(topLevelEntries);\n const secTooling = detectSecurityTooling(topLevelEntries, workflowEntries);\n const hasTests = detectTestInfra(topLevelEntries);\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,\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 };\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/** 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\ntype ExecFileFn = (\n cmd: string,\n args: string[],\n options?: { timeout?: number }\n) => Promise<{ stdout: string }>;\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 metadata: GhRepoMetadata;\n try {\n metadata = JSON.parse(metaJson.trim()) as GhRepoMetadata;\n } catch {\n throw new Error(`Failed to parse repo metadata for ${repoId}: ${metaJson.slice(0, 200)}`);\n }\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/** Fetch workflow filenames from .github/workflows/ (#1674). Best-effort. */\nasync function fetchWorkflowEntries(repoId: string, exec: ExecFileFn): Promise<readonly string[]> {\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 return Array.isArray(parsed) ? parsed.filter((e): e is string => typeof e === 'string') : [];\n } catch {\n return []; // No workflows directory or API error — graceful fallback\n }\n}\n\n/** Fetch repo data from GitHub and produce analysis. */\nexport async function analyzeGitHubRepo(input: RepoAnalyzeInput): Promise<RepoAnalysis> {\n const repoId = normalizeRepoId(input.repo);\n const exec = 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 = entries.includes('LICENSE') || entries.includes('LICENSE.md');\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 workflowEntries = entries.includes('.github')\n ? await fetchWorkflowEntries(repoId, exec)\n : [];\n\n return analyzeRepo(enhanced, entries, workflowEntries);\n}\n"],"mappings":"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","names":[]}
@@ -23,7 +23,7 @@ import {
23
23
  getAvailableClis,
24
24
  isCliAvailable,
25
25
  withTimeout
26
- } from "./chunk-VEF6DCQU.js";
26
+ } from "./chunk-MV4R2ZIJ.js";
27
27
  import {
28
28
  SessionMemory
29
29
  } from "./chunk-3VWMM6UF.js";
@@ -12993,7 +12993,7 @@ async function processVotesWithCascade(engineVotes, opts) {
12993
12993
  var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
12994
12994
  async function runContrarianCheck(proposal, log) {
12995
12995
  try {
12996
- const { executeExpert } = await import("./expert-bridge-DWBO2HXZ.js");
12996
+ const { executeExpert } = await import("./expert-bridge-NX2MGOBQ.js");
12997
12997
  const prompt = [
12998
12998
  "You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
12999
12999
  "Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
@@ -13415,4 +13415,4 @@ export {
13415
13415
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
13416
13416
  registerConsensusVoteTool
13417
13417
  };
13418
- //# sourceMappingURL=chunk-CPPZCNAS.js.map
13418
+ //# sourceMappingURL=chunk-EEW7VFFF.js.map
@@ -38,7 +38,7 @@ function adaptCompositeRouter(compositeRouter) {
38
38
  }
39
39
  async function getRouter() {
40
40
  if (cachedRouter !== null) return cachedRouter;
41
- const { createAllAdapters } = await import("./factory-LXOVC44K.js");
41
+ const { createAllAdapters } = await import("./factory-JI6PSWGR.js");
42
42
  const { createCompositeRouter } = await import("./composite-router-S6E26BCI.js");
43
43
  const adapters = createAllAdapters();
44
44
  if (adapters.size === 0) return null;
@@ -136,4 +136,4 @@ ${prompt}`;
136
136
  export {
137
137
  executeExpert
138
138
  };
139
- //# sourceMappingURL=chunk-X3BU5MIG.js.map
139
+ //# sourceMappingURL=chunk-FYAQBYHM.js.map
@@ -5,13 +5,13 @@ import {
5
5
  resolveInsideRoot
6
6
  } from "./chunk-NUBSJGQZ.js";
7
7
  import {
8
- createAllAdapters
9
- } from "./chunk-VEF6DCQU.js";
8
+ createAllAdapters,
9
+ probeCli
10
+ } from "./chunk-MV4R2ZIJ.js";
10
11
  import {
11
12
  capitalize
12
13
  } from "./chunk-633WH2ML.js";
13
14
  import {
14
- CLI_SUBPROCESS_TIMEOUTS,
15
15
  CliNameSchema,
16
16
  DEFAULT_CAPABILITIES,
17
17
  DEFAULT_COMPOSITE_CONFIG,
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-GOT7OAL5.js";
41
41
 
42
42
  // src/version.ts
43
- var VERSION = true ? "2.77.2" : "dev";
43
+ var VERSION = true ? "2.77.4" : "dev";
44
44
 
45
45
  // src/config/schemas-core.ts
46
46
  import { z } from "zod";
@@ -1297,18 +1297,18 @@ function getConfig(options) {
1297
1297
  }
1298
1298
 
1299
1299
  // src/cli/setup-data-dir.ts
1300
- import { mkdirSync, existsSync as existsSync4 } from "fs";
1301
- import { join as join4 } from "path";
1300
+ import { mkdirSync, existsSync as existsSync3 } from "fs";
1301
+ import { join as join3 } from "path";
1302
1302
 
1303
1303
  // src/cli/doctor.ts
1304
1304
  import {
1305
- existsSync as existsSync3,
1306
- readFileSync as readFileSync3,
1305
+ existsSync as existsSync2,
1306
+ readFileSync as readFileSync2,
1307
1307
  readdirSync,
1308
1308
  accessSync,
1309
1309
  constants as fsConstants
1310
1310
  } from "fs";
1311
- import { join as join3 } from "path";
1311
+ import { join as join2 } from "path";
1312
1312
 
1313
1313
  // src/mcp/server.ts
1314
1314
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -1773,193 +1773,6 @@ function printDoctorResults(result) {
1773
1773
  printDoctorSummary(result);
1774
1774
  }
1775
1775
 
1776
- // src/cli/cli-auth-probe.ts
1777
- import { execFile } from "child_process";
1778
- import { promisify } from "util";
1779
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
1780
- import { homedir } from "os";
1781
- import { join as join2 } from "path";
1782
- var execFileAsync = promisify(execFile);
1783
- var HOME = homedir();
1784
- function claudeNeedsLogin(reason) {
1785
- return {
1786
- cli: "claude",
1787
- state: "needs-login",
1788
- reason,
1789
- fixCommand: "claude /login",
1790
- envFallback: "ANTHROPIC_API_KEY",
1791
- fixUrl: "https://console.anthropic.com/account/keys"
1792
- };
1793
- }
1794
- function probeClaude() {
1795
- if (process.env["ANTHROPIC_API_KEY"] !== void 0 && process.env["ANTHROPIC_API_KEY"] !== "") {
1796
- return { cli: "claude", state: "authenticated", via: "env-var" };
1797
- }
1798
- const credPath = join2(HOME, ".claude", ".credentials.json");
1799
- if (!existsSync2(credPath)) {
1800
- return claudeNeedsLogin(
1801
- "No credentials at ~/.claude/.credentials.json and ANTHROPIC_API_KEY is not set"
1802
- );
1803
- }
1804
- try {
1805
- const parsed = JSON.parse(readFileSync2(credPath, "utf-8"));
1806
- if (!isClaudeCredsShape(parsed)) {
1807
- return claudeNeedsLogin(
1808
- "Credentials file present but not in expected shape (missing claudeAiOauth.accessToken)"
1809
- );
1810
- }
1811
- const expiresAt = parsed.claudeAiOauth.expiresAt;
1812
- if (typeof expiresAt === "number" && expiresAt < Date.now()) {
1813
- return claudeNeedsLogin(`OAuth token expired ${new Date(expiresAt).toISOString()}`);
1814
- }
1815
- return {
1816
- cli: "claude",
1817
- state: "authenticated",
1818
- via: "cli-credentials",
1819
- ...typeof expiresAt === "number" ? { meta: { expiresAt } } : {}
1820
- };
1821
- } catch (e) {
1822
- return {
1823
- cli: "claude",
1824
- state: "error",
1825
- reason: `Failed to read claude credentials: ${e instanceof Error ? e.message : String(e)}`
1826
- };
1827
- }
1828
- }
1829
- function codexNeedsLogin(reason) {
1830
- return {
1831
- cli: "codex",
1832
- state: "needs-login",
1833
- reason,
1834
- fixCommand: "codex login",
1835
- envFallback: "OPENAI_API_KEY",
1836
- fixUrl: "https://platform.openai.com/api-keys"
1837
- };
1838
- }
1839
- function classifyCodexStdout(stdout) {
1840
- if (/not logged/i.test(stdout) || /no.*token/i.test(stdout)) {
1841
- return codexNeedsLogin(stdout.trim().split("\n")[0] ?? "Not logged in");
1842
- }
1843
- return { cli: "codex", state: "authenticated", via: "cli-credentials" };
1844
- }
1845
- async function probeCodex() {
1846
- if (process.env["OPENAI_API_KEY"] !== void 0 && process.env["OPENAI_API_KEY"] !== "") {
1847
- return { cli: "codex", state: "authenticated", via: "env-var" };
1848
- }
1849
- try {
1850
- const { stdout } = await execFileAsync("codex", ["login", "status"], {
1851
- timeout: CLI_SUBPROCESS_TIMEOUTS.spawnMs
1852
- });
1853
- return classifyCodexStdout(stdout);
1854
- } catch (e) {
1855
- const msg = e instanceof Error ? e.message : String(e);
1856
- if (/ENOENT|not found/i.test(msg)) {
1857
- return { cli: "codex", state: "not-installed", reason: "codex binary not on PATH" };
1858
- }
1859
- return codexNeedsLogin("Not logged in (codex login status returned non-zero)");
1860
- }
1861
- }
1862
- function geminiNeedsLogin(reason) {
1863
- return {
1864
- cli: "gemini",
1865
- state: "needs-login",
1866
- reason,
1867
- fixCommand: "gemini",
1868
- envFallback: "GOOGLE_AI_API_KEY",
1869
- fixUrl: "https://aistudio.google.com/apikey"
1870
- };
1871
- }
1872
- function classifyGeminiCreds(parsed) {
1873
- if (!isGeminiCredsShape(parsed)) {
1874
- return geminiNeedsLogin("OAuth credentials file present but not in expected shape");
1875
- }
1876
- if (typeof parsed.expiry_date === "number" && parsed.expiry_date < Date.now()) {
1877
- return geminiNeedsLogin(
1878
- `OAuth access token expired ${new Date(parsed.expiry_date).toISOString()} (refresh may still work)`
1879
- );
1880
- }
1881
- return {
1882
- cli: "gemini",
1883
- state: "authenticated",
1884
- via: "cli-credentials",
1885
- ...typeof parsed.expiry_date === "number" ? { meta: { expiresAt: parsed.expiry_date } } : {}
1886
- };
1887
- }
1888
- function probeGemini() {
1889
- const env = process.env["GOOGLE_AI_API_KEY"] ?? process.env["GEMINI_API_KEY"];
1890
- if (env !== void 0 && env !== "") {
1891
- return { cli: "gemini", state: "authenticated", via: "env-var" };
1892
- }
1893
- const credPath = join2(HOME, ".gemini", "oauth_creds.json");
1894
- if (!existsSync2(credPath)) {
1895
- return geminiNeedsLogin(
1896
- "No OAuth credentials at ~/.gemini/oauth_creds.json and GOOGLE_AI_API_KEY/GEMINI_API_KEY are not set"
1897
- );
1898
- }
1899
- try {
1900
- return classifyGeminiCreds(JSON.parse(readFileSync2(credPath, "utf-8")));
1901
- } catch (e) {
1902
- return {
1903
- cli: "gemini",
1904
- state: "error",
1905
- reason: `Failed to read gemini credentials: ${e instanceof Error ? e.message : String(e)}`
1906
- };
1907
- }
1908
- }
1909
- async function probeOpencode() {
1910
- try {
1911
- const { stdout } = await execFileAsync("opencode", ["auth", "list"], {
1912
- timeout: CLI_SUBPROCESS_TIMEOUTS.spawnMs
1913
- });
1914
- if (/0 credentials/i.test(stdout)) {
1915
- return {
1916
- cli: "opencode",
1917
- state: "needs-login",
1918
- reason: "No providers configured in opencode",
1919
- fixCommand: "opencode auth login",
1920
- fixUrl: "https://opencode.ai/docs/config"
1921
- };
1922
- }
1923
- return { cli: "opencode", state: "authenticated", via: "cli-credentials" };
1924
- } catch (e) {
1925
- const msg = e instanceof Error ? e.message : String(e);
1926
- if (/ENOENT|not found/i.test(msg)) {
1927
- return { cli: "opencode", state: "not-installed", reason: "opencode binary not on PATH" };
1928
- }
1929
- return {
1930
- cli: "opencode",
1931
- state: "error",
1932
- reason: msg.split("\n")[0] ?? "opencode auth list failed"
1933
- };
1934
- }
1935
- }
1936
- function isClaudeCredsShape(v) {
1937
- if (typeof v !== "object" || v === null) return false;
1938
- const oauth = v.claudeAiOauth;
1939
- if (typeof oauth !== "object" || oauth === null) return false;
1940
- return typeof oauth.accessToken === "string";
1941
- }
1942
- function isGeminiCredsShape(v) {
1943
- if (typeof v !== "object" || v === null) return false;
1944
- return typeof v.access_token === "string";
1945
- }
1946
- async function probeCli(cli) {
1947
- switch (cli) {
1948
- case "claude":
1949
- return Promise.resolve(probeClaude());
1950
- case "codex":
1951
- return probeCodex();
1952
- case "gemini":
1953
- return Promise.resolve(probeGemini());
1954
- case "opencode":
1955
- return probeOpencode();
1956
- }
1957
- }
1958
- async function probeAllClis() {
1959
- const clis = ["claude", "gemini", "codex", "opencode"];
1960
- return Promise.all(clis.map((c) => probeCli(c)));
1961
- }
1962
-
1963
1776
  // src/cli/doctor.ts
1964
1777
  var REQUIRED_NODE_MAJOR2 = 22;
1965
1778
  var API_KEY_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY"];
@@ -2088,7 +1901,7 @@ function checkApiKeys() {
2088
1901
  }
2089
1902
  function checkConfigFile() {
2090
1903
  for (const configPath of CONFIG_FILE_PATHS) {
2091
- if (existsSync3(configPath)) {
1904
+ if (existsSync2(configPath)) {
2092
1905
  return { found: true, path: configPath };
2093
1906
  }
2094
1907
  }
@@ -2129,11 +1942,11 @@ function buildRegistryAdvisory(cliResults) {
2129
1942
  function hasPriorUsage() {
2130
1943
  try {
2131
1944
  const root = getNexusDataDir();
2132
- if (!existsSync3(root)) return false;
1945
+ if (!existsSync2(root)) return false;
2133
1946
  for (const sub of ["audit", "learning", "sessions", "voting"]) {
2134
1947
  const p = `${root}/${sub}`;
2135
1948
  try {
2136
- if (existsSync3(p) && readdirSync(p).length > 0) return true;
1949
+ if (existsSync2(p) && readdirSync(p).length > 0) return true;
2137
1950
  } catch {
2138
1951
  }
2139
1952
  }
@@ -2143,13 +1956,13 @@ function hasPriorUsage() {
2143
1956
  }
2144
1957
  }
2145
1958
  function countJsonlLines(filePath) {
2146
- if (!existsSync3(filePath)) return 0;
2147
- return readFileSync3(filePath, "utf-8").split("\n").filter((l) => l.trim().length > 0).length;
1959
+ if (!existsSync2(filePath)) return 0;
1960
+ return readFileSync2(filePath, "utf-8").split("\n").filter((l) => l.trim().length > 0).length;
2148
1961
  }
2149
1962
  function readRulesMetadata(filePath) {
2150
- if (!existsSync3(filePath)) return { count: 0, savedAt: null };
1963
+ if (!existsSync2(filePath)) return { count: 0, savedAt: null };
2151
1964
  try {
2152
- const raw = JSON.parse(readFileSync3(filePath, "utf-8"));
1965
+ const raw = JSON.parse(readFileSync2(filePath, "utf-8"));
2153
1966
  const rules = raw["rules"];
2154
1967
  const saved = raw["savedAt"];
2155
1968
  return {
@@ -2161,7 +1974,7 @@ function readRulesMetadata(filePath) {
2161
1974
  }
2162
1975
  }
2163
1976
  function checkDirAccess(dir) {
2164
- const exists = existsSync3(dir);
1977
+ const exists = existsSync2(dir);
2165
1978
  if (!exists) return { exists: false, writable: false };
2166
1979
  try {
2167
1980
  accessSync(dir, fsConstants.W_OK);
@@ -2221,10 +2034,10 @@ async function checkSqlite() {
2221
2034
  }
2222
2035
  function checkDataDirectory() {
2223
2036
  const rootPath = getNexusDataDir();
2224
- const rootExists = existsSync3(rootPath);
2037
+ const rootExists = existsSync2(rootPath);
2225
2038
  const subdirectories = DATA_SUBDIRECTORIES.map((name) => {
2226
- const fullPath = join3(rootPath, name);
2227
- const exists = existsSync3(fullPath);
2039
+ const fullPath = join2(rootPath, name);
2040
+ const exists = existsSync2(fullPath);
2228
2041
  return { name, path: fullPath, exists, writable: exists && isWritable(fullPath) };
2229
2042
  });
2230
2043
  return { rootExists, rootPath, subdirectories };
@@ -2308,7 +2121,7 @@ async function runDoctorFix(result) {
2308
2121
  writeLine2("\u2500".repeat(40));
2309
2122
  let fixCount = 0;
2310
2123
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2311
- const { runSetup } = await import("./setup-command-ZIG5JJAE.js");
2124
+ const { runSetup } = await import("./setup-command-DB3DOE6K.js");
2312
2125
  const setupResult = runSetup({
2313
2126
  skipMcp: true,
2314
2127
  skipRules: true,
@@ -2355,7 +2168,7 @@ function initDataDirectories(dryRun = false) {
2355
2168
  ensureDir(NEXUS_DATA_DIR, dryRun, created, alreadyExisted);
2356
2169
  for (const subdir of DATA_SUBDIRECTORIES) {
2357
2170
  const mode = RESTRICTED_DIRS.has(subdir) ? 448 : void 0;
2358
- ensureDir(join4(NEXUS_DATA_DIR, subdir), dryRun, created, alreadyExisted, mode);
2171
+ ensureDir(join3(NEXUS_DATA_DIR, subdir), dryRun, created, alreadyExisted, mode);
2359
2172
  }
2360
2173
  return { success: true, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: null };
2361
2174
  } catch (error) {
@@ -2364,7 +2177,7 @@ function initDataDirectories(dryRun = false) {
2364
2177
  }
2365
2178
  }
2366
2179
  function ensureDir(dirPath, dryRun, created, alreadyExisted, mode) {
2367
- if (existsSync4(dirPath)) {
2180
+ if (existsSync3(dirPath)) {
2368
2181
  alreadyExisted.push(dirPath);
2369
2182
  return;
2370
2183
  }
@@ -2406,7 +2219,6 @@ export {
2406
2219
  filterAvailableModels,
2407
2220
  DEFAULT_TASK_TTL_MS,
2408
2221
  clampTaskTtl,
2409
- probeAllClis,
2410
2222
  DATA_SUBDIRECTORIES,
2411
2223
  checkApiKeys,
2412
2224
  checkSqlite,
@@ -2419,4 +2231,4 @@ export {
2419
2231
  startStdioServer,
2420
2232
  closeServer
2421
2233
  };
2422
- //# sourceMappingURL=chunk-RFITLMH4.js.map
2234
+ //# sourceMappingURL=chunk-LIY6WZNR.js.map