scripts.check_native_build_freshness

Reference › scripts › check_native_build_freshness

The native-build freshness gate: a C fix must not be silently discarded by a stale compiled binary. It grades every vendored native extension under scripts/ against its C sources. tests/scripts/test_check_native_build_freshness.py and tests/scripts/test_check_native_build_freshness_edges.py import it.

Invocation: main takes one optional positional argument, the repository root (default the repository containing the script). It prints the count of native source directories found and exits 2 on an analysis error, 1 when a native directory is not registered in the NATIVE_EXTENSIONS table, and 1 when binaries are stale or not importable.

discover_native_dirs finds directories that hold C sources, and _report_unregistered names any that are missing from the registry. _grade resolves each registered extension to its compiled file (resolve_extension, which locates the importable module) and compares the file's modification time with the newest C source (newest_source). An extension whose binary is older than its newest source is reported as stale, and one that cannot be imported is reported as unresolved.

At a glance

Source scripts/check_native_build_freshness.py
Lines of code 200
Classes 1
Functions 6
Imports (internal) none
Imported by none
Tests that import it tests/scripts/test_check_native_build_freshness.py, tests/scripts/test_check_native_build_freshness_edges.py

Class diagram

Class diagram scripts.check_native_build_freshness

Dependency diagram

No internal imports and no importers.

API

Constants

Name Type Value
NATIVE_EXTENSIONS dict[str, str] {'scripts/_cxpt': 'cxpt._native', 'scripts/_ctok': 'ctok._ctok', 'scripts/_janu…

Classes

AnalysisError

Bases: Exception · Line 46

The tree cannot be analysed at all — exit 2, never a silent pass.

Functions

Function Signature Summary
newest_source newest_source(src_dir: Path) -> Path | None Most recently modified .c/.h under src_dir; build output excluded.
resolve_extension resolve_extension(dotted: str) -> Path | None Locate the .so an import of dotted would load — WITHOUT importing it.
discover_native_dirs discover_native_dirs(repo_root: Path) -> list[Path] Every scripts/_* directory that actually contains C sources.
_report_unregistered _report_unregistered(unregistered: list[Path], repo_root: Path) -> None Name every native source dir missing from the registry, and why.
_grade _grade(repo_root: Path) -> tuple[list[str], list[str]] Grade every registered extension, returning (stale, unresolved) reports.
main main(argv: list[str] | None = None) -> int Grade every vendored native extension against its C sources.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/scripts/check_native_build_freshness.py

"""Native-build freshness gate — a C fix must not be silently discarded.

This project vendors four native extensions under ``scripts/_*/`` (cxpt, ctok,
the patched janus-swi, codemod-fast). Editing one of their ``.c`` files and
re-running ``uv pip install`` does NOT reliably ship the new binary: uv keys
its build cache on the package VERSION, and every one of these is pinned at a
version that never changes, so a reinstall can serve a previously-built wheel
and copy a STALE ``.so`` into the venv with a fresh mtime.

Measured 2026-08-05: a fixed ``Server_dealloc`` was rebuilt, reinstalled,
reported as "Built cxpt", and the venv still ran the four-hour-old binary --
the repro kept segfaulting and the fix looked wrong. It was not wrong; it was
not installed. ``rm -rf scripts/_cxpt/build`` + reinstall shipped it.

That failure mode is invisible by construction: the source is right, the tests
that would catch it are the ones running against the stale binary, and the
mtime of the installed file is NEWER than the source. This gate closes it by
comparing the ``.so`` Python would actually import against the newest ``.c`` /
``.h`` in its source tree.

Exit 0 = every native extension is at least as new as its sources.
Exit 1 = at least one is stale (rebuild it).
Exit 2 = the tree cannot be analysed (never a silent pass).
"""

import importlib.util
import sys
from pathlib import Path

#: source dir -> the dotted extension module it builds. EXPLICIT, because the
#: mapping is not derivable: ``scripts/_janus_patched`` builds ``janus_swi``
#: from a ``janus/`` package dir, and ``codemod_fast`` resolves in place rather
#: than from site-packages. The completeness check below fails if a native
#: source dir is missing here, so this cannot silently fall behind the tree.
NATIVE_EXTENSIONS: dict[str, str] = {
    "scripts/_cxpt": "cxpt._native",
    "scripts/_ctok": "ctok._ctok",
    "scripts/_janus_patched": "janus_swi._swipl",
    "scripts/_codemod_fast": "codemod_fast._native",
}

#: Directories whose contents are build OUTPUT, not source.
_BUILD_DIRS = frozenset({"build", ".git", "__pycache__"})


class AnalysisError(Exception):
    """The tree cannot be analysed at all — exit 2, never a silent pass."""


def newest_source(src_dir: Path) -> Path | None:
    """Most recently modified ``.c``/``.h`` under ``src_dir``; build output excluded."""
    candidates = [
        f
        for f in src_dir.rglob("*")
        if f.suffix in (".c", ".h")
        and f.is_file()
        and not _BUILD_DIRS.intersection(f.relative_to(src_dir).parts)
    ]
    if not candidates:
        return None
    return max(candidates, key=lambda f: f.stat().st_mtime)


def resolve_extension(dotted: str) -> Path | None:
    """Locate the ``.so`` an import of ``dotted`` would load — WITHOUT importing it.

    Resolution goes through ``find_spec`` on the TOP-LEVEL package only. That
    imports nothing (``find_spec`` imports parent packages, and a top-level
    name has none), which matters because importing ``janus_swi`` boots an
    SWI-Prolog engine. Calling it on the submodule instead WOULD import the
    parent.

    Going through ``find_spec`` rather than walking ``sys.path`` by hand is
    what makes editable installs resolve: ``codemod_fast`` is served by a
    meta-path finder pointing back into ``scripts/_codemod_fast``, and a
    manual ``sys.path`` scan does not see it.
    """
    package, _, submodule = dotted.partition(".")
    if not submodule:
        raise AnalysisError(f"{dotted!r} names no submodule")
    try:
        spec = importlib.util.find_spec(package)
    except ImportError, ValueError:
        return None
    if spec is None or not spec.submodule_search_locations:
        return None
    for location in spec.submodule_search_locations:
        matches = sorted(Path(location).glob(f"{submodule}*.so"))
        if matches:
            return matches[0]
    return None


def discover_native_dirs(repo_root: Path) -> list[Path]:
    """Every ``scripts/_*`` directory that actually contains C sources."""
    scripts = repo_root / "scripts"
    if not scripts.is_dir():
        raise AnalysisError(f"no scripts/ directory under {repo_root}")
    found = []
    for child in sorted(scripts.glob("_*")):
        if child.is_dir() and newest_source(child) is not None:
            found.append(child)
    return found


def _report_unregistered(unregistered: list[Path], repo_root: Path) -> None:
    """Name every native source dir missing from the registry, and why."""
    for d in unregistered:
        rel = d.relative_to(repo_root)
        print(
            f"  {rel}: builds C sources but is absent from NATIVE_EXTENSIONS "
            f"— add it (with its dotted extension module) so its binary is graded",
            file=sys.stderr,
        )
    print(
        f"FAIL: {len(unregistered)} unregistered native source dir(s).",
        file=sys.stderr,
    )


def _grade(repo_root: Path) -> tuple[list[str], list[str]]:
    """Grade every registered extension, returning (stale, unresolved) reports."""
    stale: list[str] = []
    unresolved: list[str] = []
    for src_rel, dotted in sorted(NATIVE_EXTENSIONS.items()):
        src_dir = repo_root / src_rel
        if not src_dir.is_dir():
            continue
        newest = newest_source(src_dir)
        if newest is None:
            continue
        so = resolve_extension(dotted)
        if so is None:
            unresolved.append(
                f"  {dotted}: not importable from this interpreter's sys.path"
            )
            continue
        if so.stat().st_mtime < newest.stat().st_mtime:
            stale.append(
                f"  {dotted}: built binary predates its source\n"
                f"      binary {so}\n"
                f"      source {newest.relative_to(repo_root)}\n"
                f"      rebuild: rm -rf {src_rel}/build && "
                f"uv pip install --no-build-isolation "
                f"--reinstall-package {dotted.split('.')[0]} {src_rel}"
            )
    return stale, unresolved


def main(argv: list[str] | None = None) -> int:
    """Grade every vendored native extension against its C sources."""
    argv = sys.argv[1:] if argv is None else argv
    repo_root = (
        Path(argv[0]).resolve() if argv else Path(__file__).resolve().parent.parent
    )

    try:
        native_dirs = discover_native_dirs(repo_root)
    except AnalysisError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 2

    print(f"[native-build] {len(native_dirs)} native source dir(s) under scripts/")

    registered = {repo_root / d for d in NATIVE_EXTENSIONS}
    unregistered = [d for d in native_dirs if d not in registered]
    if unregistered:
        _report_unregistered(unregistered, repo_root)
        return 1

    try:
        stale, unresolved = _grade(repo_root)
    except AnalysisError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 2

    for line in unresolved:
        print(line, file=sys.stderr)
    if stale:
        print(
            "[native-build] STALE BINARIES — a C fix in these is NOT running:",
            file=sys.stderr,
        )
        for line in stale:
            print(line, file=sys.stderr)
        print(f"FAIL: {len(stale)} stale native extension(s).", file=sys.stderr)
        return 1
    if unresolved:
        print(
            f"FAIL: {len(unresolved)} native extension(s) not importable.",
            file=sys.stderr,
        )
        return 1

    print("[native-build] OK — every native extension is newer than its sources")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())