Files
ITWorx_MCP_Hub-Public/tests/test_projectbrain_contract_audit.py
T

75 lines
3.0 KiB
Python

from __future__ import annotations
import copy
import json
from pathlib import Path
import pytest
from jsonschema import Draft202012Validator
from scripts.audit_projectbrain_contracts import audit
ROOT = Path(__file__).resolve().parents[1]
SNAPSHOT = ROOT / "tests/fixtures/projectbrain-discovery-20260908.json"
def test_live_discovery_fields_are_available_in_reviewed_catalog() -> None:
result = audit(json.loads(SNAPSHOT.read_text()), ROOT / "catalog")
assert result == {"passed": True, "toolCount": 57, "issues": []}
def test_every_required_projectbrain_argument_has_a_field_definition() -> None:
for path in (ROOT / "catalog/tools").glob("projectbrain-*.yaml"):
schema = json.loads(path.read_text())["spec"]["inputSchema"]
Draft202012Validator.check_schema(schema)
assert set(schema.get("required", [])) <= set(schema.get("properties", {})), path.name
@pytest.mark.parametrize("drift", ["field", "required", "tool", "duplicate", "missing"])
def test_audit_detects_upstream_evolution_without_publishing_it(drift: str) -> None:
discovery = copy.deepcopy(json.loads(SNAPSHOT.read_text()))
tool = discovery["tools"][0]
if drift == "field":
tool["inputSchema"]["properties"]["future_option"] = {"type": "boolean"}
elif drift == "required":
tool["inputSchema"]["required"] = ["future_option"]
elif drift == "tool":
tool["name"] = "projectbrain.unreviewed"
elif drift == "duplicate":
discovery["tools"].append(tool)
else:
discovery["tools"].pop()
assert audit(discovery, ROOT / "catalog")["passed"] is False
def validator(slug: str) -> Draft202012Validator:
spec = json.loads((ROOT / "catalog/tools" / f"projectbrain-{slug}.yaml").read_text())["spec"]
return Draft202012Validator(spec["inputSchema"])
def test_compact_state_and_run_budget_options_are_usable_and_bounded() -> None:
state = validator("autonomy-state-get")
state.validate({"project_id": "demo", "view": "summary", "item_limit": 1, "event_limit": 0})
assert not state.is_valid({"project_id": "demo", "item_limit": 26})
assert not state.is_valid({"project_id": "demo", "view": "everything"})
configure = validator("autonomy-configure")
configure.validate({"project_id": "demo", "max_work_items_per_run": 3, "max_run_minutes": 15})
assert not configure.is_valid({"project_id": "demo", "max_run_minutes": 56})
def test_changeset_contract_rejects_unfenced_update_and_unknown_fields() -> None:
schema = validator("delivery-changeset-apply")
payload = {
"project_id": "demo",
"delivery_id": "delivery-1",
"branch": "chatgpt/demo",
"expected_head_sha": "a" * 40,
"message": "Update docs",
"operations": [{"operation": "update", "path": "docs/example.md", "content": "text"}],
}
assert not schema.is_valid(payload)
payload["operations"][0]["expected_sha"] = "b" * 40
schema.validate(payload)
payload["operations"][0]["unknown_option"] = True
assert not schema.is_valid(payload)