"""Load-bearing tests for doc↔code constant sync (kø-(h)). ``docs/extending.md`` claimed ``SEMANTIC_WEIGHT_DEFAULT = 0.5`` long after the code had lowered it to ``0.25``. The drift was found BY ACCIDENT while editing the neighbouring line; nothing in the suite would ever have caught it. This module is the gate that would have. **Scope is deliberately narrow (90 %).** Only SCREAMING_CASE module constants cited with their value inside an inline code span, and only in LIVE documents. Both bounds were MEASURED, not assumed: * **SCREAMING_CASE discriminates exactly.** Across every numeric ``name = value`` code span in ``docs/`` it selects the 2 real module constants (``SEMANTIC_WEIGHT_DEFAULT``, ``MAX_SAVING_FRACTION``) and rejects all 10 keyword arguments and locals (``max_attempts=3``, ``concurrency=3``, ``realiseringsgrad=0.79``, …). SCREAMING_CASE *is* the claim "this is a module constant"; ordinary prose and kwargs stay editable and never trip the gate. * **Dated documents are observations, not contract.** A spike finding or a July review records what was true when it was measured; rewriting it to track the code would falsify the record. LIVE documents describe the framework as it is NOW, which is what a reader acts on. The gate REFUSES rather than skips, in this repo's fail-closed tradition (``write_concept_file``, ``VerdictFrontmatterError``, ``read_spend``): an unknown constant name is an error, never a silent pass, because a typo that quietly disables a guard is exactly the masking class this repo hunts. For the same reason document classification is fail-closed — a new document that is neither listed LIVE nor recognisably archived goes RED asking to be classified, so coverage cannot quietly rot. Ambiguity is narrowed to what actually makes a lookup unsafe: a name bound in several modules is normal Python re-export (``run`` re-exports ``SEMANTIC_WEIGHT_DEFAULT`` from ``semretrieval``), so only genuinely DIVERGENT values are refused. Measuring this rewrote the rule — a "same name in two modules" check would have been RED on today's code. """ from __future__ import annotations import importlib import pkgutil import re from pathlib import Path import pytest import portfolio_optimiser REPO_ROOT = Path(__file__).resolve().parents[1] DOCS_DIR = REPO_ROOT / "docs" # Documents that describe the framework AS IT IS NOW. Explicit rather than derived: the companion # classification test below goes RED on any document that is neither listed here nor archived, so # this list cannot silently fall behind. _LIVE_DOCS = ( "README.md", "docs/extending.md", "docs/knowledge-base-recipe.md", ) # A dated path segment marks a point-in-time record. ``docs/fase1-spikes/`` is the one archive whose # directory name carries no date — the phase-1 spike findings are dated by their phase, not by # filename. _DATED = re.compile(r"\d{4}-\d{2}") _ARCHIVE_DIRS = ("fase1-spikes",) # A constant citation: SCREAMING_CASE bound to a numeric literal, inside an inline code span. _CITATION = re.compile(r"`\s*([A-Z][A-Z0-9_]{2,})\s*=\s*(-?\d+(?:\.\d+)?)\s*`") def _is_archive(rel_path: str) -> bool: """A document is archived when its path carries a date or sits in a known archive directory.""" return bool(_DATED.search(rel_path)) or any(f"/{d}/" in f"/{rel_path}" for d in _ARCHIVE_DIRS) def _module_constants() -> dict[str, set[float]]: """Map every public numeric SCREAMING_CASE constant in the package to the DISTINCT values it is bound to. A name re-exported across modules yields one value and is unambiguous; only divergent values make a lookup unsafe.""" constants: dict[str, set[float]] = {} for info in pkgutil.iter_modules(portfolio_optimiser.__path__): module = importlib.import_module(f"portfolio_optimiser.{info.name}") for name in dir(module): if not name.isupper() or name.startswith("_"): continue value = getattr(module, name) if isinstance(value, bool) or not isinstance(value, (int, float)): continue constants.setdefault(name, set()).add(float(value)) return constants def _check_citations(text: str, label: str) -> list[str]: """Return one message per citation that does NOT match the code. Unknown and ambiguous names are failures, never skips — the whole point is that a citation cannot quietly stop being checked.""" constants = _module_constants() problems: list[str] = [] for lineno, line in enumerate(text.splitlines(), 1): for name, literal in _CITATION.findall(line): where = f"{label}:{lineno}" values = constants.get(name) if values is None: problems.append( f"{where}: cites `{name} = {literal}` but no public numeric constant named " f"{name} exists in portfolio_optimiser" ) elif len(values) > 1: problems.append( f"{where}: cites `{name}` but it is bound to divergent values " f"{sorted(values)} — the citation cannot be checked safely" ) elif float(literal) != next(iter(values)): problems.append( f"{where}: says `{name} = {literal}` but the code says {next(iter(values))}" ) return problems def _live_doc_paths() -> list[Path]: return [REPO_ROOT / rel for rel in _LIVE_DOCS] @pytest.mark.parametrize("rel_path", _LIVE_DOCS) def test_live_docs_cite_constants_that_match_the_code(rel_path: str) -> None: """THE GATE. Every constant a live document cites with its value must equal what the code actually holds. Goes RED on precisely the drift that shipped undetected: ``extending.md`` saying 0.5 while ``semretrieval.SEMANTIC_WEIGHT_DEFAULT`` is 0.25.""" path = REPO_ROOT / rel_path assert path.is_file(), f"{rel_path} is listed LIVE but does not exist" problems = _check_citations(path.read_text(encoding="utf-8"), rel_path) assert not problems, "documentation cites constants the code contradicts:\n" + "\n".join( problems ) def test_a_drifted_citation_is_caught() -> None: """The gate must FAIL on drift, not merely pass on a clean tree. Uses the real constant so the check is anchored to live code rather than to a fixture's idea of it.""" real = _module_constants()["SEMANTIC_WEIGHT_DEFAULT"] assert len(real) == 1, "test premise: the constant must be unambiguous" wrong = next(iter(real)) + 1.0 problems = _check_citations(f"blends `SEMANTIC_WEIGHT_DEFAULT = {wrong}` today", "synthetic.md") assert len(problems) == 1, problems assert "but the code says" in problems[0] def test_an_unknown_constant_name_is_refused_not_skipped() -> None: """Fail-closed: a name that resolves to nothing is an error. If unknown names were skipped, a typo in a doc — or a constant deleted from the code — would silently retire the check.""" problems = _check_citations("see `NO_SUCH_CONSTANT_HERE = 7` for details", "synthetic.md") assert len(problems) == 1, problems assert "no public numeric constant" in problems[0] def test_prose_and_keyword_arguments_do_not_trip_the_gate() -> None: """The measured bound: ordinary prose, kwargs and lowercase locals stay freely editable. A gate that made routine documentation edits brittle would be switched off, catching nothing.""" text = ( "run with `max_attempts=3` and `concurrency=1`, giving `realiseringsgrad=0.79` " "against a p50 of `p50 = 95443.98966314227`" ) assert _check_citations(text, "synthetic.md") == [] def test_every_document_is_classified_live_or_archive() -> None: """Fail-closed coverage: a new document must be deliberately classified. Without this, adding a live guide would leave it silently unguarded — a hole indistinguishable from a passing gate.""" live = set(_LIVE_DOCS) unclassified = [ rel for path in [REPO_ROOT / "README.md", *sorted(DOCS_DIR.rglob("*.md"))] if (rel := path.relative_to(REPO_ROOT).as_posix()) not in live and not _is_archive(rel) ] assert not unclassified, ( "these documents are neither listed in _LIVE_DOCS nor recognisable as archive — classify " "them (a live guide belongs in _LIVE_DOCS; a point-in-time record needs a dated path):\n" + "\n".join(unclassified) ) def test_the_gate_actually_reaches_a_real_citation() -> None: """Coverage, not vocabulary: a gate that scans only documents containing no citations would be green forever. At least one live document must genuinely exercise the comparison.""" cited = [ (rel, name) for path, rel in ((p, p.relative_to(REPO_ROOT).as_posix()) for p in _live_doc_paths()) for name, _ in _CITATION.findall(path.read_text(encoding="utf-8")) ] assert cited, "no live document cites any constant — the gate would pass vacuously"