{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["local>promptfoo/renovate-config"],
  "rebaseWhen": "behind-base-branch",
  "separateMajorMinor": true,
  "rangeStrategy": "auto",
  "postUpdateOptions": [],
  "constraints": {
    "npm": ">=11.18.0 <12"
  },
  "npmrc": "registry=https://registry.npmjs.org/\nengine-strict=true\nmin-release-age=10",
  "lockFileMaintenance": {
    "enabled": true,
    "schedule": [
      "before 3am on the first day of the month",
      "before 3am on the 15th day of the month"
    ]
  },
  "ignorePaths": [
    "examples/**/requirements.txt",
    "examples/**/pyproject.toml",
    "examples/**/go.mod",
    "test/**/go.mod"
  ],
  "packageRules": [
    {
      "description": "Disable major Node.js version updates",
      "matchPackageNames": ["node"],
      "matchUpdateTypes": ["major"],
      "enabled": false
    },
    {
      "description": "Preserve the intentionally unsupported Node 20.20.0 and minimum-supported Node 22.22.0 binaries used by CLI runtime-boundary smoke tests; update these pins only when the published runtime support contract changes.",
      "matchManagers": ["github-actions"],
      "matchFileNames": [".github/workflows/main.yml"],
      "matchPackageNames": ["node", "actions/node-versions"],
      "matchCurrentValue": "/^(20\\.20\\.0|22\\.22\\.0)$/",
      "enabled": false
    },
    {
      "description": "Keep Renovate's npm tool constraint on the CI-supported major; npm 12 breaks bundled lockfile maintenance",
      "matchFileNames": ["renovate.json"],
      "matchPackageNames": ["npm"],
      "matchUpdateTypes": ["major"],
      "enabled": false
    },
    {
      "description": "Pin the code-scan workflow's Node to 24.15.0: Node >=24.16.0 has a Linux HTTPS slowdown (~10s/request) that drags the scanner's `npm install -g promptfoo` past the job's 15-minute timeout (see the comment in .github/workflows/promptfoo-code-scan.yml; first fixed in PR #9374, regressed by the blanket bump in PR #9859). Renovate must not re-bump this pin. Re-enable when a newer Node resolves the regression.",
      "matchManagers": ["github-actions"],
      "matchFileNames": [".github/workflows/promptfoo-code-scan.yml"],
      "matchPackageNames": ["node", "actions/node-versions"],
      "enabled": false
    },
    {
      "description": "Group example directory updates as a fallback so package-specific groups still win",
      "matchFileNames": ["examples/**/package.json"],
      "groupName": "Example dependencies",
      "schedule": ["before 6am on the first day of the month"]
    },
    {
      "description": "Group @inquirer packages together",
      "matchPackagePatterns": ["^@inquirer/"],
      "groupName": "@inquirer packages"
    },
    {
      "description": "Group Anthropic packages together across all dependency types",
      "matchPackagePatterns": ["^@anthropic-ai/"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "Anthropic packages"
    },
    {
      "description": "Group AWS SDK packages together across all dependency types",
      "matchPackagePatterns": ["^@aws-sdk/", "^@smithy/"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "AWS SDK packages"
    },
    {
      "description": "Group Azure packages together across all dependency types",
      "matchPackagePatterns": ["^@azure/"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "Azure packages"
    },
    {
      "description": "Group Storybook monorepo packages together",
      "matchPackagePatterns": ["^@storybook/", "^storybook$", "^@chromatic-com/storybook"],
      "groupName": "Storybook monorepo"
    },
    {
      "description": "Group Docusaurus packages together",
      "matchPackagePatterns": ["^@docusaurus/"],
      "groupName": "Docusaurus packages"
    },
    {
      "description": "Keep Docusaurus's react-router-config override on Router v5 until Docusaurus migrates away from it. The app's direct Router v8 dependency remains independently upgradable.",
      "matchManagers": ["npm"],
      "matchFileNames": ["package.json"],
      "matchDepTypes": ["overrides"],
      "matchPackageNames": ["react-router"],
      "allowedVersions": "<6"
    },
    {
      "description": "Group GitHub Actions packages together",
      "matchPackagePatterns": ["^@actions/"],
      "groupName": "GitHub Actions"
    },
    {
      "description": "Use major.minor only for Ruby versions to auto-receive patches",
      "matchManagers": ["github-actions"],
      "matchPackageNames": ["ruby"],
      "extractVersion": "^(?<version>\\d+\\.\\d+)",
      "versioning": "ruby"
    },
    {
      "description": "Group IBM packages together across all dependency types",
      "matchPackagePatterns": ["^@ibm-cloud/", "^ibm-cloud-sdk-core$"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "IBM packages"
    },
    {
      "description": "Group MUI packages together",
      "matchPackagePatterns": ["^@mui/", "^@emotion/"],
      "groupName": "MUI packages"
    },
    {
      "description": "Group Octokit packages together",
      "matchPackagePatterns": ["^@octokit/"],
      "groupName": "Octokit"
    },
    {
      "description": "Group OpenAI packages together across all dependency types",
      "matchPackagePatterns": ["^@openai/", "^openai$"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "OpenAI packages"
    },
    {
      "description": "Group fal.ai packages together across all dependency types",
      "matchPackagePatterns": ["^@fal-ai/"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "fal.ai packages"
    },
    {
      "description": "Group langfuse packages together across all dependency types",
      "matchPackagePatterns": ["^langfuse$"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "langfuse"
    },
    {
      "description": "Group PostHog packages together across all dependency types",
      "matchPackagePatterns": ["^posthog-"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "PostHog packages"
    },
    {
      "description": "Group OpenTelemetry packages together",
      "matchPackagePatterns": ["^@opentelemetry/"],
      "groupName": "OpenTelemetry"
    },
    {
      "description": "Group SWC packages together",
      "matchPackagePatterns": ["^@swc/"],
      "groupName": "SWC"
    },
    {
      "description": "Group TanStack packages together",
      "matchPackagePatterns": ["^@tanstack/"],
      "groupName": "TanStack packages"
    },
    {
      "description": "Keep TanStack Table on v8 until the shared data tables migrate to v9's feature registration, hooks, row models, state APIs, and generic types; the v9 upgrade currently breaks the production build and every shared-table interaction.",
      "matchPackageNames": ["@tanstack/react-table", "@tanstack/table-core"],
      "allowedVersions": "<9"
    },
    {
      "description": "Group Testing Library packages together",
      "matchPackagePatterns": ["^@testing-library/"],
      "groupName": "Testing Library packages"
    },
    {
      "description": "Group Vitest packages together",
      "matchPackagePatterns": ["^vitest$", "^@vitest/"],
      "groupName": "Vitest"
    },
    {
      "description": "Keep Drizzle ORM packages in sync",
      "matchPackageNames": ["drizzle-orm", "drizzle-kit"],
      "groupName": "Drizzle ORM"
    },
    {
      "description": "Keep Playwright packages in sync across all dependency types",
      "matchPackagePatterns": ["^@playwright/", "^playwright$", "^playwright-"],
      "matchDepTypes": [
        "dependencies",
        "devDependencies",
        "optionalDependencies",
        "peerDependencies"
      ],
      "groupName": "Playwright"
    },
    {
      "description": "Keep React packages in sync",
      "matchPackageNames": ["react", "react-dom", "@types/react", "@types/react-dom"],
      "groupName": "React"
    },
    {
      "description": "Keep socket.io packages in sync",
      "matchPackageNames": ["socket.io", "socket.io-client"],
      "groupName": "socket.io"
    },
    {
      "description": "Keep jsdom in sync across all workspaces, and hold it below 30. jsdom 30 requires node ^22.22.2 || ^24.15.0 || >=26.0.0, but this package publishes engines.node >=22.22.0 and .npmrc sets engine-strict=true, so `npm ci` fails EBADENGINE on the Node 22.22.0 lanes that exist precisely to test that floor (see the closed #10311). jsdom is a dev-only Vitest environment, so raising the published runtime floor for it would make promptfoo refuse to start on Node 22.22.0/22.22.1 for no user-facing gain. Lift this cap when engines.node moves past 22.22.2 for an independent reason.",
      "matchPackageNames": ["jsdom"],
      "allowedVersions": "<30",
      "groupName": "jsdom"
    },
    {
      "description": "Keep jsdom's CSS color parser below 7 while promptfoo supports Node 22.22.0. @asamuzakjp/css-color 7 requires node ^22.22.2 || ^24.15.0 || >=26.0.0, so engine-strict clean installs fail on the minimum supported Node version even though jsdom itself remains below 30. Lift this cap when engines.node moves past 22.22.2 for an independent reason.",
      "matchPackageNames": ["@asamuzakjp/css-color"],
      "allowedVersions": "<7"
    },
    {
      "description": "Keep undici in sync across root and code-scan-action, and below 8 until engines.node is >=26. Promptfoo hands undici dispatchers to Node's built-in fetch; on Node 22 and 24 that fetch rejects undici 8 dispatchers and every request hangs (test/fetch.compression.test.ts times out on those CI lanes).",
      "matchPackageNames": ["undici"],
      "groupName": "undici",
      "allowedVersions": "<8"
    },
    {
      "description": "Keep dedent in sync across all workspaces",
      "matchPackageNames": ["dedent"],
      "groupName": "dedent"
    },
    {
      "description": "Group all @types packages together",
      "matchPackagePatterns": ["^@types/"],
      "groupName": "Type definitions",
      "schedule": ["before 6am on Monday"]
    },
    {
      "description": "Keep ModelAudit schema generator pins current",
      "matchManagers": ["pip_requirements"],
      "matchFileNames": ["scripts/modelaudit_schema_requirements.txt"],
      "groupName": "ModelAudit schema generator"
    },
    {
      "description": "ModelAudit schema generator: only modelaudit (the top-level package) drives updates. Its transitive pins (pydantic, pydantic-core, and typing helpers) are a matched set that must move together — pydantic enforces an exact pydantic-core pair at import time, and pydantic-core releases ahead of pydantic stable — so an independent bump of any one creates an incompatible pair. They are refreshed by regenerating the schema when modelaudit bumps.",
      "matchManagers": ["pip_requirements"],
      "matchFileNames": ["scripts/modelaudit_schema_requirements.txt"],
      "matchPackageNames": [
        "pydantic",
        "pydantic-core",
        "annotated-types",
        "typing-extensions",
        "typing-inspection"
      ],
      "enabled": false
    },
    {
      "description": "LLM provider packages: frequent updates with a ten-day stabilization window",
      "matchPackagePatterns": [
        "^@anthropic-ai/",
        "^@aws-sdk/client-bedrock",
        "^@aws-sdk/client-sagemaker",
        "^@azure/ai-",
        "^@azure/openai",
        "^@fal-ai/",
        "^@ibm-cloud/watsonx",
        "^@modelcontextprotocol/",
        "^@openai/",
        "^google-auth-library$",
        "^langfuse$",
        "^openai$"
      ],
      "schedule": ["every weekday"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "All npm packages: wait 10 days, a buffer above the 7-day Socket minimum release age floor",
      "matchDatasources": ["npm"],
      "minimumReleaseAge": "10 days"
    },

    {
      "description": "@opencode-ai/sdk: weekly updates to reduce noise from daily releases",
      "matchPackageNames": ["@opencode-ai/sdk"],
      "schedule": ["before 6am on Monday"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "AWS SDK packages: weekly updates to reduce noise",
      "matchPackagePatterns": ["^@aws-sdk/", "^@smithy/"],
      "schedule": ["before 6am on Monday"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "Biome: weekly updates",
      "matchPackageNames": ["@biomejs/biome"],
      "schedule": ["before 6am on Monday"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "Hold Knip below 6.28 until existing public barrel re-exports have been audited; 6.28 changed ignoreExportsUsedInFile and flags 130 established exports",
      "matchPackageNames": ["knip"],
      "allowedVersions": "<6.28.0"
    },
    {
      "description": "Dev tooling: weekly updates (low urgency)",
      "matchPackageNames": ["hono", "knip"],
      "schedule": ["before 6am on Monday"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "motion: monthly updates (animation library, low urgency)",
      "matchPackageNames": ["motion"],
      "schedule": ["before 6am on the first day of the month"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "satori: monthly updates to reduce noise from frequent patch releases",
      "matchPackageNames": ["satori"],
      "schedule": ["before 6am on the first day of the month"],
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "Vercel AI SDK: monthly updates to reduce noise from frequent patch releases",
      "matchPackageNames": ["ai"],
      "groupName": "Vercel AI SDK",
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "Storybook: monthly updates to reduce noise from frequent patch releases",
      "matchPackagePatterns": ["^@storybook/", "^storybook$", "^@chromatic-com/storybook"],
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "PostHog packages: monthly updates to reduce noise from frequent patch releases",
      "matchPackagePatterns": ["^posthog-"],
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "undici: monthly updates to reduce noise",
      "matchPackageNames": ["undici"],
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "postcss: monthly updates to reduce noise from frequent patch releases",
      "matchPackageNames": ["postcss"],
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    },
    {
      "description": "fast-xml-parser: monthly updates to reduce noise from frequent patch releases",
      "matchPackageNames": ["fast-xml-parser"],
      "schedule": ["before 6am on the first day of the month"],
      "rangeStrategy": "bump",
      "minimumReleaseAge": "10 days"
    }
  ]
}
