26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
117 lines
4.1 KiB
Python
Executable File
117 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Render the SDK conformance matrix (GL #395).
|
|
|
|
Reads the per-SDK scorecards written by the conformance suites
|
|
(``conformance-{python,typescript,rust}.json``) and renders the publishable
|
|
matrix ``docs/reference/sdk-conformance-matrix.md``: SDK version x engine
|
|
version x per-check status. Run by ``scripts/sdk-conformance.sh`` and the
|
|
``sdk-conformance`` CI job on every release candidate.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import datetime as dt
|
|
import json
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
SDK_VERSIONS = {
|
|
"python": ("clients/python/leanctx/__init__.py", r'__version__ = "([^"]+)"'),
|
|
"typescript": ("cookbook/sdk/package.json", r'"version":\s*"([^"]+)"'),
|
|
"rust": ("clients/rust/lean-ctx-client/Cargo.toml", r'^version = "([^"]+)"'),
|
|
}
|
|
|
|
|
|
def sdk_version(root: pathlib.Path, sdk: str) -> str:
|
|
rel, pattern = SDK_VERSIONS[sdk]
|
|
text = (root / rel).read_text(encoding="utf-8")
|
|
m = re.search(pattern, text, re.MULTILINE)
|
|
return m.group(1) if m else "unknown"
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("matrix_dir", type=pathlib.Path)
|
|
parser.add_argument("--engine-version", required=True)
|
|
parser.add_argument("--out", type=pathlib.Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
root = pathlib.Path(__file__).resolve().parent.parent
|
|
cards = {}
|
|
for sdk in ("python", "typescript", "rust"):
|
|
path = args.matrix_dir / f"conformance-{sdk}.json"
|
|
if path.is_file():
|
|
cards[sdk] = json.loads(path.read_text(encoding="utf-8"))
|
|
|
|
if not cards:
|
|
print("no scorecards found — did the suites run?", file=sys.stderr)
|
|
return 1
|
|
|
|
check_names: list[str] = []
|
|
for card in cards.values():
|
|
for check in card["checks"]:
|
|
if check["name"] not in check_names:
|
|
check_names.append(check["name"])
|
|
|
|
lines = [
|
|
"# SDK Conformance Matrix",
|
|
"",
|
|
"Status of every first-party SDK against the frozen `/v1` contract",
|
|
"(`run_conformance`, GL #395). Generated by `scripts/sdk-conformance.sh`",
|
|
"against a real `lean-ctx serve` instance — regenerate, never edit.",
|
|
"",
|
|
f"- **Engine:** `{args.engine_version}`",
|
|
f"- **Generated:** {dt.datetime.now(dt.timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}",
|
|
"",
|
|
"| SDK | Package | Version | Conformance |",
|
|
"|---|---|---|---|",
|
|
]
|
|
packages = {
|
|
"python": "`lean-ctx-client` (PyPI)",
|
|
"typescript": "`lean-ctx-client` (npm)",
|
|
"rust": "`lean-ctx-client` (crates.io)",
|
|
}
|
|
for sdk, card in cards.items():
|
|
verdict = "PASS" if card["all_passed"] else "FAIL"
|
|
lines.append(
|
|
f"| {sdk} | {packages[sdk]} | {sdk_version(root, sdk)} "
|
|
f"| {verdict} ({card['passed']}/{card['total']}) |"
|
|
)
|
|
|
|
lines += ["", "## Checks", "", "| Check | " + " | ".join(cards) + " |"]
|
|
lines.append("|---|" + "---|" * len(cards))
|
|
for name in check_names:
|
|
row = [name]
|
|
for card in cards.values():
|
|
check = next((c for c in card["checks"] if c["name"] == name), None)
|
|
if check is None:
|
|
row.append("—")
|
|
elif check["passed"]:
|
|
row.append("pass")
|
|
else:
|
|
detail = check.get("detail", "")
|
|
row.append(f"FAIL {detail}".strip())
|
|
lines.append("| " + " | ".join(row) + " |")
|
|
|
|
lines += [
|
|
"",
|
|
"## SemVer coupling",
|
|
"",
|
|
"Every SDK declares the `http_mcp` contract versions it speaks",
|
|
"(`SUPPORTED_HTTP_CONTRACT_VERSIONS`); the `engine_compat` check fails when",
|
|
"a server speaks a contract the SDK release does not support. SDK majors",
|
|
"follow the engine contract major (CONTRACTS.md § Versioning rules).",
|
|
"",
|
|
]
|
|
|
|
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
args.out.write_text("\n".join(lines), encoding="utf-8")
|
|
print(f"wrote {args.out}")
|
|
return 0 if all(c["all_passed"] for c in cards.values()) else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|