From 1fe7eef4ec259ebe33baa3fb165dbd9fa937b4b2 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 10:53:44 +0100 Subject: [PATCH 1/8] chore(deps): make Python Dependabot security-only --- .github/dependabot.yml | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 01effd2..8c94f78 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,5 @@ 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. - package-ecosystem: "pip" directory: "/" schedule: @@ -10,28 +7,13 @@ 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. + # MCP v2 is a deliberate integration migration tracked in #263. ignore: - dependency-name: mcp versions: @@ -39,10 +21,8 @@ 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. - package-ecosystem: "github-actions" directory: "/" schedule: From 98d51a76bd298008109708aa9c1a733139994ca3 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 10:58:12 +0100 Subject: [PATCH 2/8] docs(packaging): advertise tested Python 3.13 and 3.14 --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ea61e03..56b8ffc 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", ] From 7bc9aac3f53d3eec8f700663db081ecd40c8964e Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 10:58:45 +0100 Subject: [PATCH 3/8] ci: prove current Python and dependency floors --- .github/workflows/ci.yml | 69 ++++++++++++---------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e2e8b4..e52af55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,11 +1,6 @@ name: CI -# Contract: this workflow runs the same gate as `make ci` -# (fmt-check -> lint -> type -> test -> example). Each step below invokes a -# Makefile target so the local gate and CI cannot drift (see Makefile and -# docs/agent-context/workflows.md). Change the steps here only by changing the -# Makefile. - +# Contract: this workflow runs the same gate as `make ci`. on: push: branches: ["main", "copilot/**"] @@ -13,13 +8,9 @@ on: branches: ["main"] workflow_call: -# Least-privilege by default; jobs needing more declare it explicitly. permissions: contents: read -# Cancel superseded runs on the same ref so a new push to a PR stops the -# previous run instead of burning runner time. Keyed on the ref so distinct -# branches/PRs stay independent. concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -31,42 +22,33 @@ 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 - - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} cache: pip cache-dependency-path: pyproject.toml - - name: Install dependencies run: pip install -e ".[dev]" - - # Each step is a Makefile target — see the contract note at the top. - name: Format check run: make fmt-check - - name: Lint run: make lint - - name: Type check run: make type - - name: Test run: make test - - name: Examples run: make example - - name: Coverage HTML report if: always() run: python -m coverage html - - name: Upload coverage HTML if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -75,37 +57,47 @@ jobs: path: htmlcov/ if-no-files-found: ignore + floor-deps: + name: "Floor dependencies (Python 3.10)" + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - 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 needs: test permissions: contents: read - steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml - - # No extras: proves the "minimal deps (httpx + pydantic)" claim holds. - name: Install (no extras) run: pip install . - - name: Import the full public API run: | python -c "import weaver_kernel as w; \ missing = [n for n in w.__all__ if not hasattr(w, n)]; \ assert not missing, f'missing public symbols: {missing}'; \ print(f'imported {len(w.__all__)} public symbols')" - - name: Run the README quickstart run: python examples/readme_quickstart.py - - name: Assert optional extras are genuinely absent run: | for mod in mcp yaml opentelemetry tiktoken weaver_contracts; do @@ -115,7 +107,6 @@ jobs: fi done echo "no optional extras leaked into the base install" - - name: Assert the MCP-extra-missing error is helpful run: | python - <<'PY' @@ -134,23 +125,16 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml - - name: Install pip-audit run: pip install pip-audit - - # Resolve weaver-kernel's *runtime* dependency tree in an isolated venv - # (no extras, no pip-audit) and audit exactly that, so pip-audit's own - # dependencies can never cause a failure unrelated to what adopters ship. - name: Resolve runtime dependency tree run: | python -m venv /tmp/runtime @@ -158,10 +142,6 @@ jobs: /tmp/runtime/bin/pip freeze --exclude-editable \ | grep -viE '^(weaver-kernel|pip|setuptools)([=@ ]|$)' > runtime-requirements.txt echo "Auditing:"; cat runtime-requirements.txt - - # Policy: fail on any known vulnerability in the runtime tree. Document a - # false positive by appending `--ignore-vuln ` here with a comment - # (see README "Security automation"). - name: Audit runtime dependencies run: pip-audit --strict --desc --requirement runtime-requirements.txt @@ -171,26 +151,17 @@ jobs: needs: test permissions: contents: read - steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml - - # Real validation (no echo): map kernel Frame/ActionTrace/token onto the - # published weaver-contracts dataclasses and assert they validate. When - # dgenio/weaver-spec#4 ships weaver_contracts.conformance, add its runner - # here as an additional step. - name: Install conformance extra run: pip install ".[conformance]" pytest pytest-asyncio - - name: Report contract version run: python -c "from weaver_kernel.conformance import contract_version; print('weaver-contracts', contract_version())" - - name: Run conformance mapping tests run: python -m pytest tests/test_conformance.py -q From 5b886e301cc289e3aaaa9823958aba6f74cb9593 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 10:59:00 +0100 Subject: [PATCH 4/8] ci: add Python 3.15 compatibility canary --- .github/workflows/python-next.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/python-next.yml 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 From 25daa3069b7767363b4ea8f92224117ac4ffd3dd Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 11:13:09 +0100 Subject: [PATCH 5/8] chore(ci): restore workflow rationale around compatibility lanes --- .github/workflows/ci.yml | 60 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e52af55..36ad5e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,11 @@ name: CI -# Contract: this workflow runs the same gate as `make ci`. +# Contract: this workflow runs the same gate as `make ci` +# (fmt-check -> lint -> type -> test -> example). Each step below invokes a +# Makefile target so the local gate and CI cannot drift (see Makefile and +# docs/agent-context/workflows.md). Change the steps here only by changing the +# Makefile. + on: push: branches: ["main", "copilot/**"] @@ -8,9 +13,13 @@ on: branches: ["main"] workflow_call: +# Least-privilege by default; jobs needing more declare it explicitly. permissions: contents: read +# Cancel superseded runs on the same ref so a new push to a PR stops the +# previous run instead of burning runner time. Keyed on the ref so distinct +# branches/PRs stay independent. concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -28,27 +37,37 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} cache: pip cache-dependency-path: pyproject.toml + - name: Install dependencies run: pip install -e ".[dev]" + + # Each step is a Makefile target — see the contract note at the top. - name: Format check run: make fmt-check + - name: Lint run: make lint + - name: Type check run: make type + - name: Test run: make test + - name: Examples run: make example + - name: Coverage HTML report if: always() run: python -m coverage html + - name: Upload coverage HTML if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -57,20 +76,29 @@ 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 - - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.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 @@ -80,24 +108,31 @@ jobs: needs: test permissions: contents: read + steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml + + # No extras: proves the "minimal deps (httpx + pydantic)" claim holds. - name: Install (no extras) run: pip install . + - name: Import the full public API run: | python -c "import weaver_kernel as w; \ missing = [n for n in w.__all__ if not hasattr(w, n)]; \ assert not missing, f'missing public symbols: {missing}'; \ print(f'imported {len(w.__all__)} public symbols')" + - name: Run the README quickstart run: python examples/readme_quickstart.py + - name: Assert optional extras are genuinely absent run: | for mod in mcp yaml opentelemetry tiktoken weaver_contracts; do @@ -107,6 +142,7 @@ jobs: fi done echo "no optional extras leaked into the base install" + - name: Assert the MCP-extra-missing error is helpful run: | python - <<'PY' @@ -125,16 +161,23 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml + - name: Install pip-audit run: pip install pip-audit + + # Resolve weaver-kernel's *runtime* dependency tree in an isolated venv + # (no extras, no pip-audit) and audit exactly that, so pip-audit's own + # dependencies can never cause a failure unrelated to what adopters ship. - name: Resolve runtime dependency tree run: | python -m venv /tmp/runtime @@ -142,6 +185,10 @@ jobs: /tmp/runtime/bin/pip freeze --exclude-editable \ | grep -viE '^(weaver-kernel|pip|setuptools)([=@ ]|$)' > runtime-requirements.txt echo "Auditing:"; cat runtime-requirements.txt + + # Policy: fail on any known vulnerability in the runtime tree. Document a + # false positive by appending `--ignore-vuln ` here with a comment + # (see README "Security automation"). - name: Audit runtime dependencies run: pip-audit --strict --desc --requirement runtime-requirements.txt @@ -151,17 +198,26 @@ jobs: needs: test permissions: contents: read + steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: pip cache-dependency-path: pyproject.toml + + # Real validation (no echo): map kernel Frame/ActionTrace/token onto the + # published weaver-contracts dataclasses and assert they validate. When + # dgenio/weaver-spec#4 ships weaver_contracts.conformance, add its runner + # here as an additional step. - name: Install conformance extra run: pip install ".[conformance]" pytest pytest-asyncio + - name: Report contract version run: python -c "from weaver_kernel.conformance import contract_version; print('weaver-contracts', contract_version())" + - name: Run conformance mapping tests run: python -m pytest tests/test_conformance.py -q From b2c4cf0cd2abccffbce77b5afb0fe1f244f1ba85 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 11:13:30 +0100 Subject: [PATCH 6/8] docs(deps): preserve automation rationale --- .github/dependabot.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8c94f78..fe076dd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,8 @@ version: 2 updates: + # 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: @@ -13,7 +16,9 @@ updates: applies-to: security-updates patterns: - "*" - # MCP v2 is a deliberate integration migration tracked in #263. + # MCP v2 is a deliberate integration migration tracked in #263. Ignore + # the incompatible versions themselves so the existing <2 contract cannot + # be widened automatically before that migration is implemented. ignore: - dependency-name: mcp versions: @@ -23,6 +28,8 @@ updates: commit-message: prefix: "fix(deps)" + # GitHub Actions are SHA-pinned in workflows. Dependabot advances the pin and + # version comment; unrelated breaking majors are intentionally not grouped. - package-ecosystem: "github-actions" directory: "/" schedule: From ed53d6c6d8173d6a445f4b072e176a357f3b7c64 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 11:27:33 +0100 Subject: [PATCH 7/8] fix(test): raise pytest-asyncio floor for pytest 8 compatibility --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 56b8ffc..ea7cfc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,9 @@ 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", From d287161fd5c4f352937e09a6a92303dcbc0c3c78 Mon Sep 17 00:00:00 2001 From: Diogo Santos Date: Mon, 10 Aug 2026 11:45:29 +0100 Subject: [PATCH 8/8] fix(deps): raise MCP floor to proven FastMCP-compatible release --- pyproject.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ea7cfc3..8c8333a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,15 +62,16 @@ dev = [ "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",