diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e8fd2a..741be95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,138 +1,209 @@ -name: CI - -on: - push: - pull_request: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - lint-and-audit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - python-version: '3.14' - - name: Install dependencies - run: uv sync --all-extras --dev - shell: bash - - name: Check code - run: uv run ruff check . - shell: bash - - name: Format check - run: uv run ruff format --check . - shell: bash - - name: Typecheck - run: uv run mypy src/ tests/ - shell: bash - - name: Audit dependencies - run: uv run deptry src/ - shell: bash - - name: Build docs - run: uv run zensical build - shell: bash - - test-ubuntu: - needs: [lint-and-audit] - if: always() && needs.lint-and-audit.result == 'success' - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.14", "3.14t"] - steps: - - uses: actions/checkout@v4 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - python-version: ${{ matrix.python-version }} - - - name: Configure free-threading execution - if: matrix.python-version == '3.14t' - run: echo "PYTHON_GIL=0" >> "$GITHUB_ENV" - shell: bash - - - name: Install dependencies - run: uv sync --all-extras --dev - shell: bash - - - name: Run tests - run: uv run pytest --cov=src --cov-report=xml - shell: bash - - - name: Build docs - run: uv run zensical build - shell: bash - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false - verbose: true - - test-extended: - needs: [test-ubuntu] - if: always() && needs.test-ubuntu.result == 'success' - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-latest, macos-latest] - python-version: ["3.14", "3.14t"] - exclude: - - os: windows-latest - python-version: "3.14t" - - os: macos-latest - python-version: "3.14t" - steps: - - uses: actions/checkout@v4 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - python-version: ${{ matrix.python-version }} - - - name: Configure free-threading execution - if: matrix.python-version == '3.14t' - run: echo "PYTHON_GIL=0" >> "$GITHUB_ENV" - shell: bash - - - name: Install dependencies - run: uv sync --all-extras --dev - shell: bash - - - name: Run tests - run: uv run pytest --cov=src --cov-report=xml - shell: bash - - reproducible-builds: - name: Determinism Verification - needs: [test-ubuntu, test-extended] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - python-version: "3.14" - - name: Build wheel - run: uv build - shell: bash - - name: Verify SHA256 sum - run: sha256sum dist/*.whl - shell: bash - - +name: CI + +on: + push: + branches: + - main + - develop + pull_request: + +permissions: read-all + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-and-audit: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + steps: + - name: Pre-Flight Workspace Purity + run: sudo chown -R $(whoami):$(whoami) ${{ github.workspace }} || true + + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + enable-cache: true + python-version: '3.14' + + - name: Install dependencies + run: uv sync --all-extras --dev --frozen + shell: bash + + - name: Check code (Ruff) + run: uv run ruff check . + shell: bash + + - name: Format check (Ruff) + run: uv run ruff format --check . + shell: bash + + - name: Typecheck (Mypy) + run: uv run mypy src/ tests/ + shell: bash + + - name: Audit dependencies (Deptry) + run: uv run deptry src/ + shell: bash + + - name: Build docs + run: uv run zensical build + shell: bash + + - name: Substrate Purity Verification + run: git clean -xfd -e .venv -e .uv_cache + + test-ubuntu: + needs: [lint-and-audit] + if: always() && needs.lint-and-audit.result == 'success' + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + matrix: + python-version: ["3.14", "3.14t"] + steps: + - name: Pre-Flight Workspace Purity + run: sudo chown -R $(whoami):$(whoami) ${{ github.workspace }} || true + + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + enable-cache: true + python-version: ${{ matrix.python-version }} + + - name: Configure free-threading execution + if: matrix.python-version == '3.14t' + run: echo "PYTHON_GIL=0" >> "$GITHUB_ENV" + shell: bash + + - name: Install dependencies + run: uv sync --all-extras --dev --frozen + shell: bash + + - name: Run tests + run: uv run pytest --cov=src --cov-report=xml + shell: bash + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + verbose: true + + - name: Substrate Purity Verification + run: git clean -xfd -e .venv -e .uv_cache + + test-extended: + needs: [test-ubuntu] + if: always() && needs.test-ubuntu.result == 'success' + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + matrix: + os: [windows-latest, macos-latest] + python-version: ["3.14", "3.14t"] + exclude: + - os: windows-latest + python-version: "3.14t" + - os: macos-latest + python-version: "3.14t" + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + enable-cache: true + python-version: ${{ matrix.python-version }} + + - name: Configure free-threading execution + if: matrix.python-version == '3.14t' + run: echo "PYTHON_GIL=0" >> "$GITHUB_ENV" + shell: bash + + - name: Install dependencies + run: uv sync --all-extras --dev --frozen + shell: bash + + - name: Run tests + run: uv run pytest --cov=src --cov-report=xml + shell: bash + + reproducible-builds: + name: Determinism Verification + needs: [test-ubuntu, test-extended] + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + enable-cache: true + python-version: "3.14" + + - name: Build wheel (attempt 1) + run: | + export SOURCE_DATE_EPOCH=315532800 + uv build --out-dir dist1 + sha256sum dist1/*.whl | tee /tmp/hash1.txt + shell: bash + + - name: Build wheel (attempt 2) + run: | + export SOURCE_DATE_EPOCH=315532800 + uv build --out-dir dist2 + sha256sum dist2/*.whl | tee /tmp/hash2.txt + shell: bash + + - name: Verify deterministic build + run: | + HASH1=$(awk '{print $1}' /tmp/hash1.txt) + HASH2=$(awk '{print $1}' /tmp/hash2.txt) + echo "Build 1 SHA256: $HASH1" + echo "Build 2 SHA256: $HASH2" + if [ "$HASH1" != "$HASH2" ]; then + echo "::error::CRITICAL: Non-deterministic build detected! Hashes do not match." + exit 1 + fi + echo "✅ Deterministic build verified. SHA256: $HASH1" + shell: bash diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 369cc51..fa03ecf 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,177 +1,193 @@ -name: Release - -on: - push: - tags: - - 'v*.*.*' - - '*.*.*' - release: - types: [published] - workflow_dispatch: - -permissions: - contents: write - id-token: write # Required for PyPI OIDC Trusted Publishing and Sigstore - pages: write # Required for GitHub Pages deployment - attestations: write # Required for SLSA build provenance - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" - -jobs: - release: - runs-on: ubuntu-latest - environment: pypi - steps: - - name: Harden Runner (Endpoint Network Security) - uses: step-security/harden-runner@v2 - with: - egress-policy: audit - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - python-version: "3.14" - - - name: Install dependencies - run: uv sync --all-extras --dev --frozen - - - name: Build Artifacts - run: uv build - - - name: Generate SBOM - uses: anchore/sbom-action@v0 - with: - format: spdx-json - output-file: sbom.spdx.json - upload-release-assets: false - - - name: Generate SLSA Provenance - uses: actions/attest-build-provenance@v2 - with: - subject-path: | - dist/*.whl - dist/*.tar.gz - - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - - - name: Sign Wheel - uses: sigstore/gh-action-sigstore-python@v3.3.0 - with: - inputs: >- - dist/*.whl - dist/*.tar.gz - - source: false - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - files: | - dist/*.whl - dist/*.tar.gz - dist/*.sigstore.json - sbom.spdx.json - - - name: Build Docs - run: uv run zensical build --clean - - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: site - - deploy-pages: - needs: release - runs-on: ubuntu-latest - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - permissions: - pages: write - id-token: write - steps: - - name: Harden Runner (Endpoint Network Security) - uses: step-security/harden-runner@v2 - with: - egress-policy: audit - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 - - publish-container: - needs: release - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - id-token: write - attestations: write - steps: - - name: Harden Runner - uses: step-security/harden-runner@v2 - with: - egress-policy: audit - - - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ github.repository }} - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha - type=raw,value=latest - - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v5 - with: - context: . - push: true - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: Generate SBOM for Container - uses: anchore/sbom-action@v0 - with: - image: ghcr.io/${{ github.repository }}@${{ steps.build-and-push.outputs.digest }} - format: spdx-json - output-file: sbom-container.spdx.json - - - name: Install Cosign - uses: sigstore/cosign-installer@v3.5.0 - - - name: Sign the image with Cosign - run: cosign sign --yes ghcr.io/${{ github.repository }}@${{ steps.build-and-push.outputs.digest }} - - - name: Generate SLSA Provenance for Container - uses: actions/attest-build-provenance@v2 - with: - subject-name: ghcr.io/${{ github.repository }} - subject-digest: ${{ steps.build-and-push.outputs.digest }} - push-to-registry: true +name: Release + +on: + push: + tags: + - 'v*.*.*' + - '*.*.*' + release: + types: [published] + workflow_dispatch: + +permissions: + contents: write + id-token: write # Required for PyPI OIDC Trusted Publishing and Sigstore + pages: write # Required for GitHub Pages deployment + attestations: write # Required for SLSA build provenance + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + release: + runs-on: ubuntu-latest + environment: pypi + steps: + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + enable-cache: true + python-version: "3.14" + + - name: Install dependencies + run: uv sync --all-extras --dev --frozen + + - name: Build Artifacts + run: uv build + + - name: Generate SBOM + uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.18.0 + with: + format: spdx-json + output-file: sbom.spdx.json + upload-release-assets: false + + - name: Generate SLSA Provenance + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.2.3 + with: + subject-path: | + dist/*.whl + dist/*.tar.gz + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 + + - name: Sign Wheel + uses: sigstore/gh-action-sigstore-python@04cffa1d795717b140764e8b640de88853c92acc # v3.3.0 + with: + inputs: >- + dist/*.whl + dist/*.tar.gz + + source: false + + - name: Create GitHub Release + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.1.0 + with: + files: | + dist/*.whl + dist/*.tar.gz + dist/*.sigstore.json + sbom.spdx.json + + - name: Build Docs + run: uv run zensical build --clean + + - name: Upload artifact + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 + with: + path: site + + deploy-pages: + needs: release + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + permissions: + pages: write + id-token: write + steps: + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 + + publish-container: + needs: release + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + attestations: write + steps: + - name: Harden Runner (Endpoint Network Security) + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up QEMU + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.3.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.10.0 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.7.0 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + type=raw,value=latest + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.12.0 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Generate SBOM for Container + uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.18.0 + with: + image: ghcr.io/${{ github.repository }}@${{ steps.build-and-push.outputs.digest }} + format: spdx-json + output-file: sbom-container.spdx.json + + - name: Install Cosign + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.8.1 + + - name: Sign the image with Cosign + run: cosign sign --yes ghcr.io/${{ github.repository }}@${{ steps.build-and-push.outputs.digest }} + + - name: Generate SLSA Provenance for Container + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.2.3 + with: + subject-name: ghcr.io/${{ github.repository }} + subject-digest: ${{ steps.build-and-push.outputs.digest }} + push-to-registry: true + + - name: Publish to MCP Registry + run: | + if [ -f "server.json" ]; then + npx @modelcontextprotocol/publisher publish --config server.json + else + echo "No server.json found, skipping MCP Registry publish." + fi diff --git a/Dockerfile b/Dockerfile index 5f45c94..e98b955 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,27 @@ # Stage 1: Builder FROM python:3.14-slim AS builder +# Install build dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + # Set the working directory WORKDIR /app +# Copy project manifest files +COPY pyproject.toml uv.lock ./ +# Copy .git if it exists for versioning +COPY .gi[t] ./.git/ + # Copy the project files -COPY pyproject.toml . -COPY uv.lock . COPY src/ ./src/ COPY README.md . COPY LICENSE . diff --git a/src/coreason_meta_engineering/forge_orchestrator.py b/src/coreason_meta_engineering/forge_orchestrator.py index 8737943..97e5c64 100644 --- a/src/coreason_meta_engineering/forge_orchestrator.py +++ b/src/coreason_meta_engineering/forge_orchestrator.py @@ -18,6 +18,7 @@ from coreason_meta_engineering.pvv import execute_pvv_pipeline from coreason_meta_engineering.utils.logger import logger +from coreason_meta_engineering.utils.mcp_registry_scaffolder import generate_server_json __all__ = ["DynamicForgeOrchestrator", "dispatch_agent_generation", "orchestrate_generation"] @@ -188,6 +189,11 @@ async def scaffold_ast( target_file.parent.mkdir(parents=True, exist_ok=True) target_file.write_text(valid_code, encoding="utf-8") + # --- Dual-Publish: Generate server.json --- + server_json_content = generate_server_json(geometric_schema) + server_json_path = target_file.parent / "server.json" + server_json_path.write_text(server_json_content, encoding="utf-8") + return valid_code diff --git a/src/coreason_meta_engineering/utils/mcp_registry_scaffolder.py b/src/coreason_meta_engineering/utils/mcp_registry_scaffolder.py new file mode 100644 index 0000000..f166609 --- /dev/null +++ b/src/coreason_meta_engineering/utils/mcp_registry_scaffolder.py @@ -0,0 +1,46 @@ +# Copyright (c) 2026 CoReason, Inc +# +# This software is proprietary and dual-licensed +# Licensed under the Prosperity Public License 3.0 (the "License") +# A copy of the license is available at +# For details, see the LICENSE file +# Commercial use beyond a 30-day trial requires a separate license +# +# Source Code: + +import json +from typing import Any + + +def generate_server_json(geometric_schema: dict[str, Any] | list[dict[str, Any]]) -> str: + """ + Generates an MCP Registry server.json file based on the geometric schema. + This guarantees type isomorphism and prevents LLM hallucination. + """ + if isinstance(geometric_schema, list): + geometric_schema = geometric_schema[0] if geometric_schema else {} + + urn = geometric_schema.get("urn", "urn:coreason:actionspace:unknown:v1") + + # Extract components of URN assuming urn:coreason:actionspace:{type}:{name}:{version} + parts = urn.split(":") + capability_name = parts[4] if len(parts) >= 6 else "unknown_capability" + + server_json = { + "name": capability_name, + "description": geometric_schema.get("description", f"CoReason capabilities for {capability_name}"), + "version": "1.0.0", + "mcp_version": "1.0", + "author": "CoReason, Inc.", + "license": geometric_schema.get("economics", {}).get("license_class", "PROSPERITY_3.0_COMMERCIAL"), + "entrypoint": "mcp-server", + "repository": f"https://github.com/CoReason-AI/{capability_name}", + "registry_metadata": { + "urn": urn, + "epistemic_status": geometric_schema.get("epistemic_status", "DRAFT"), + "billing_tier": geometric_schema.get("economics", {}).get("billing_tier", "TIER_1_STANDARD"), + "validation": geometric_schema.get("validation", {}), + }, + } + + return json.dumps(server_json, indent=2) diff --git a/tests/utils/test_mcp_registry_scaffolder.py b/tests/utils/test_mcp_registry_scaffolder.py new file mode 100644 index 0000000..31ebc3c --- /dev/null +++ b/tests/utils/test_mcp_registry_scaffolder.py @@ -0,0 +1,40 @@ +import json +from coreason_meta_engineering.utils.mcp_registry_scaffolder import generate_server_json + +def test_generate_server_json_dict(): + schema = { + "urn": "urn:coreason:actionspace:solver:test_solver:v1", + "description": "Test description", + "epistemic_status": "PUBLISHED", + "economics": { + "license_class": "OPEN_SOURCE", + "billing_tier": "TIER_0_FREE" + }, + "validation": {} + } + result = generate_server_json(schema) + data = json.loads(result) + assert data["name"] == "test_solver" + assert data["registry_metadata"]["epistemic_status"] == "PUBLISHED" + +def test_generate_server_json_list(): + schema = [{ + "urn": "urn:coreason:actionspace:solver:test_list_solver:v1" + }] + result = generate_server_json(schema) + data = json.loads(result) + assert data["name"] == "test_list_solver" + +def test_generate_server_json_empty_list(): + schema = [] + result = generate_server_json(schema) + data = json.loads(result) + assert data["name"] == "unknown_capability" + +def test_generate_server_json_invalid_urn(): + schema = { + "urn": "invalid_urn" + } + result = generate_server_json(schema) + data = json.loads(result) + assert data["name"] == "unknown_capability" diff --git a/wasm/components/forge/src/app.py b/wasm/components/forge/src/app.py index 593b7e3..6b0002a 100644 --- a/wasm/components/forge/src/app.py +++ b/wasm/components/forge/src/app.py @@ -4,6 +4,7 @@ # Licensed under the Prosperity Public License 3.0 (the "License") import json +import typing import forge_service @@ -11,7 +12,7 @@ # Note: In a real componentization flow, this class would implement # the interface defined in the generated bindings from world.wit class ForgeTool: - def list_tools(self): + def list_tools(self) -> list[dict[str, str]]: return [ { "name": "scaffold_manifest_state", @@ -132,11 +133,11 @@ def list_tools(self): }, ] - def call_tool(self, name, arguments): + def call_tool(self, name: str, arguments: str) -> dict[str, typing.Any]: args = json.loads(arguments) try: if name == "scaffold_manifest_state": - result = forge_service.scaffold_manifest_state(**args) + result: typing.Any = forge_service.scaffold_manifest_state(**args) elif name == "reconcile_manifest_state": result = forge_service.reconcile_manifest_state(**args) elif name == "scaffold_logic_actuator": diff --git a/wasm/components/forge/src/forge_service.py b/wasm/components/forge/src/forge_service.py index bad3649..f0497da 100644 --- a/wasm/components/forge/src/forge_service.py +++ b/wasm/components/forge/src/forge_service.py @@ -173,7 +173,7 @@ def scaffold_manifest_yaml( import pathlib from datetime import UTC, datetime - import hvac + import hvac # type: ignore[import-untyped] import yaml from coreason_manifest.spec.ontology import COREASON_GLOBAL_TENANT_CID