diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 01effd2..fe076dd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,8 @@ version: 2 updates: - # Python dependencies. The library declares ranged requirements on purpose; - # routine minor/patch updates are grouped, while major compatibility changes - # stay separate and explicit. + # Python requirements are published library compatibility ranges. Routine + # releases are exercised by the stable/floor/next CI lanes rather than by + # rewriting those ranges. Dependabot is reserved for vulnerability fixes. - package-ecosystem: "pip" directory: "/" schedule: @@ -10,28 +10,15 @@ updates: day: monday time: "06:00" timezone: Etc/UTC - open-pull-requests-limit: 5 - cooldown: - default-days: 7 + open-pull-requests-limit: 0 groups: - python-nonmajor: - applies-to: version-updates - patterns: - - "*" - update-types: - - minor - - patch - python-security-nonmajor: + python-security: applies-to: security-updates patterns: - "*" - update-types: - - minor - - patch # MCP v2 is a deliberate integration migration tracked in #263. Ignore - # the incompatible versions themselves: Dependabot can otherwise widen a - # requirement range (<2 -> <3) without treating that edit as a SemVer-major - # version update. + # the incompatible versions themselves so the existing <2 contract cannot + # be widened automatically before that migration is implemented. ignore: - dependency-name: mcp versions: @@ -39,7 +26,7 @@ updates: labels: - dependencies commit-message: - prefix: "chore(deps)" + prefix: "fix(deps)" # GitHub Actions are SHA-pinned in workflows. Dependabot advances the pin and # version comment; unrelated breaking majors are intentionally not grouped. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e2e8b4..36ad5e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,8 +31,9 @@ jobs: permissions: contents: read strategy: + fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -75,6 +76,32 @@ jobs: path: htmlcov/ if-no-files-found: ignore + # Prove that each declared >= floor is real rather than aspirational. Resolve + # direct requirements to their lower bounds while allowing transitive + # dependencies to remain solvable, then run the full behavioral suite. + floor-deps: + name: "Floor dependencies (Python 3.10)" + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up Python 3.10 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: "3.10" + + - name: Install uv + run: python -m pip install uv + + - name: Install declared direct floors + run: uv pip install --system --resolution lowest-direct -e ".[dev]" + + - name: Run suite at the floors + run: pytest -q + bare-install: name: "Bare install (no extras)" runs-on: ubuntu-latest diff --git a/.github/workflows/python-next.yml b/.github/workflows/python-next.yml new file mode 100644 index 0000000..e6f3ca4 --- /dev/null +++ b/.github/workflows/python-next.yml @@ -0,0 +1,31 @@ +name: Python Next Canary + +on: + schedule: + - cron: "15 7 * * 3" + workflow_dispatch: + pull_request: + paths: + - "pyproject.toml" + - ".github/workflows/python-next.yml" + +permissions: + contents: read + +jobs: + python-next: + name: Python 3.15 pre-release + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: "3.15" + allow-prereleases: true + - name: Install + run: | + python -m pip install --upgrade pip + pip install -e ".[dev]" + - name: Test + run: pytest -q diff --git a/pyproject.toml b/pyproject.toml index ea61e03..8c8333a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,8 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Security", "Topic :: Software Development :: Libraries :: Python Modules", ] @@ -53,20 +55,23 @@ Changelog = "https://github.com/dgenio/agent-kernel/blob/main/CHANGELOG.md" dev = [ "pytest>=8.0", "pytest-cov>=5.0", - "pytest-asyncio>=0.23", + # 0.23.5 is the first 0.23.x release declaring pytest 8 compatibility. + # The lowest-direct CI lane proves this floor alongside pytest>=8. + "pytest-asyncio>=0.23.5", "hypothesis>=6.100", "ruff>=0.4", "mypy>=1.10", "httpx>=0.27", - # MCP 2.x removes/changes APIs used by the current driver. Keep v1 as the - # supported compatibility line until the deliberate migration in #263. - "mcp>=1.6,<2", + # Floor 1.17: mcp.shared.memory first accepts FastMCP directly and unwraps + # it to the low-level server. The real in-process discover/execute test + # fails on 1.16 and earlier. Ceiling <2 remains migration issue #263. + "mcp>=1.17,<2", "pyyaml>=6.0", "tomli>=2.0; python_version<'3.11'", "types-PyYAML>=6.0", "weaver-contracts>=0.7,<0.8", ] -mcp = ["mcp>=1.6,<2"] +mcp = ["mcp>=1.17,<2"] otel = ["opentelemetry-api>=1.20"] policy = [ "pyyaml>=6.0",