Skip to content
28 changes: 19 additions & 9 deletions tests/test_completeness.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
from __future__ import annotations

import ast
import importlib.util
import re
import shutil
from pathlib import Path

from conftest import ( # noqa: F401 (sys.path side effect)
BASE_REPO, PINNED_REVISION, FakeGit, REPO_ROOT, staging_fragment, thin_fragment,
BASE_REPO, PINNED_REVISION, FakeGit, REPO_ROOT, carved_module_path,
staging_fragment, thin_fragment,
)

from doc_health import corpus
Expand All @@ -36,7 +38,13 @@
from openxdox import completeness as C
from openxdox.generator import generate_snapshot, live_topic_health

SCRIPTS = REPO_ROOT / "scripts"
# WHERE THE PURITY AND GATING-BOUND CHECKS READ, after the carve (plan 038
# T103). Before it, one import root, openxFactory's `scripts/`, held both the
# scoring module and `doc_health`. Now the scoring module and its importers are
# this leg's, under `src/` (the `openxdox` package's import root), and
# `doc_health` is openxFactory's, read where this process imports it from: the
# composed tree.
SRC = REPO_ROOT / "src"


def _tree(tmp_path: Path) -> Path:
Expand Down Expand Up @@ -174,7 +182,7 @@ def test_the_scoring_module_touches_nothing_outside_its_arguments():
# builtin escape hatch is called either. `doc_health.lines` is admitted
# specifically because IT is itself pure by the same standard (asserted
# below, not assumed): it imports only `re`, and defines no I/O.
tree = ast.parse((SCRIPTS / "ideation_dashboard" / "completeness.py").read_text("utf-8"))
tree = ast.parse(carved_module_path("completeness.py").read_text("utf-8"))
modules: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
Expand All @@ -187,7 +195,8 @@ def test_the_scoring_module_touches_nothing_outside_its_arguments():
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name)}
assert not called & {"open", "eval", "exec", "input", "print", "compile"}, called

lines_tree = ast.parse((SCRIPTS / "doc_health" / "lines.py").read_text("utf-8"))
lines_tree = ast.parse(
Path(importlib.util.find_spec("doc_health.lines").origin).read_text("utf-8"))
lines_modules: set[str] = set()
for node in ast.walk(lines_tree):
if isinstance(node, ast.Import):
Expand Down Expand Up @@ -501,14 +510,15 @@ def test_the_scoring_modules_only_importers_are_the_generator_and_the_guard():
r"|from\s+\.completeness\s+import\b"
r"|import\s+\S*\bcompleteness\b)")
importers = sorted(
p.relative_to(SCRIPTS).as_posix()
for p in SCRIPTS.rglob("*.py")
p.relative_to(SRC).as_posix()
for p in SRC.rglob("*.py")
if p.name != "completeness.py" and import_re.search(p.read_text("utf-8")))
assert importers == ["ideation_dashboard/generator.py",
"ideation_dashboard/kickoff.py"], importers
assert importers == ["openxdox/generator.py",
"openxdox/kickoff.py"], importers
# ...and no doc-health / readiness path consults the score at all: the
# per-document signal produces no finding and feeds no readiness tier.
for module in sorted((SCRIPTS / "doc_health").rglob("*.py")):
[doc_health] = importlib.util.find_spec("doc_health").submodule_search_locations
for module in sorted(Path(doc_health).rglob("*.py")):
text = module.read_text("utf-8")
assert not import_re.search(text), module
assert "topic_health" not in text and "READY_MIN_SCORE" not in text, module
7 changes: 5 additions & 2 deletions tests/test_doxbench_packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import pytest

from conftest import REPO_ROOT # noqa: F401 (sys.path side effect)
from conftest import assert_not_at_this_leg, carved_module_path
from conftest import assert_not_at_this_leg, carved_module_path, openxfactory_root

from opendox import doxbench_knowledge as kn # noqa: E402
from opendox import doxbench_packet as pk # noqa: E402
Expand Down Expand Up @@ -593,7 +593,10 @@ def test_the_status_read_agrees_with_the_repositorys_own_corpus_reader():

assert pk.STATUS_SCAN_LINES == 15
checked = 0
for path in sorted((REPO_ROOT / "docs").rglob("*.md"))[:80]:
# THE REPOSITORY'S OWN CORPUS is openxFactory's, the one its corpus reader
# reads, so it is read from the composed tree (plan 038 T103): this
# checkout's own `docs/` holds too few documents for the check to be one.
for path in sorted((openxfactory_root() / "docs").rglob("*.md"))[:80]:
text = path.read_text(encoding="utf-8", errors="replace")
assert pk.lifecycle_status(text) == parse_status(text), path
checked += 1
Expand Down
42 changes: 30 additions & 12 deletions tests/test_gate_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@
import pytest
import yaml

from conftest import BASE_REPO, PINNED_REVISION, REPO_ROOT, FakeGit, find_openxfactory_validator
from conftest import (
BASE_REPO, PINNED_REVISION, REPO_ROOT, FakeGit, find_openxfactory_validator,
openxfactory_root,
)

from doc_health import families
from openxdox import gate_console as gc
Expand Down Expand Up @@ -867,7 +870,7 @@ def test_the_cli_tells_the_human_the_snapshot_was_preserved(tmp_path, capsys):
_fragment(root).parent.mkdir(parents=True, exist_ok=True)
_fragment(root).write_text(LIVE, encoding="utf-8")

from ideation_dashboard import cli
from opendox import cli

# Through the REAL parser, not a hand-built Namespace: a Namespace's field set
# can drift from the CLI's while the test keeps passing.
Expand Down Expand Up @@ -903,7 +906,9 @@ def test_the_cli_tells_the_human_the_snapshot_was_preserved(tmp_path, capsys):
# demote that returned it.

_SUPPORT_SPEC = importlib.util.spec_from_file_location(
"proposal_support_for_round_trip", REPO_ROOT / "scripts" / "proposal-support.py")
"proposal_support_for_round_trip",
# openxFactory's own forward gate, read from the composed tree (plan 038 T103).
openxfactory_root() / "scripts" / "proposal-support.py")
support = importlib.util.module_from_spec(_SUPPORT_SPEC)
sys.modules[_SUPPORT_SPEC.name] = support
_SUPPORT_SPEC.loader.exec_module(support)
Expand Down Expand Up @@ -1814,7 +1819,7 @@ def test_the_hostile_gate_descriptors_still_reach_the_real_cli(tmp_path):
refuse it — inside the process, which is the layer that can refuse."""
import shlex

from ideation_dashboard import cli
from opendox import cli

out = _hostile_gate_commands(tmp_path)
parser = cli.build_parser()
Expand Down Expand Up @@ -2251,22 +2256,35 @@ def test_new_verb_constants_are_the_contract_spellings():
import subprocess as _subprocess
import sys as _sys

from conftest import CONTRACTS_DIR as _CONTRACTS_DIR
from conftest import find_openxfactory_validator as _find_validator
from openxdox import contracts as _packaged_contracts

_VALIDATOR = _find_validator()
_NEW_VERBS = ("promote-to-staging", "derive-possibles", "research-brief")


def _contract_carries_the_new_verbs() -> bool:
"""True once the reachable openxFactory contract enumerates the new verbs."""
if _VALIDATOR is None:
return False
schemas = _VALIDATOR.parent.parent / "contracts" / "schemas"
try:
intent = (schemas / "gate-intent.schema.yaml").read_text(encoding="utf-8")
record = (schemas / "gate-action-record.schema.yaml").read_text(encoding="utf-8")
except OSError:
"""True once the reachable openxFactory contract enumerates the new verbs.

Each schema is read where the pinned validator reads it (plan 038 T103,
OQ-R9-3). Before the carve both sat beside the validator; this leg carries
no `contracts/schemas/` there, so that read found nothing and the group
never ran. `gate-action-record`, one of the validator's own three, is the
installed distribution's packaged copy. `gate-intent`, one of the family's
other seven, is in the contracts directory `CONTRACTS_DIR` names, which
only a composed run supplies; a lone checkout has none, and there the
group still skips.

Once a run supplies that directory, a schema it cannot read is a broken
composed source, not an unreleased contract: the read error is left to
fail collection, so the five cases cannot skip green over it."""
if _VALIDATOR is None or _CONTRACTS_DIR is None:
return False
intent = (_CONTRACTS_DIR / "schemas" / "gate-intent.schema.yaml").read_text(
encoding="utf-8")
record = _packaged_contracts.verified_path("gate-action-record").read_text(
encoding="utf-8")
return all(v in intent and v in record for v in _NEW_VERBS)


Expand Down
14 changes: 9 additions & 5 deletions tests/test_round_trip.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import pytest

from conftest import REPO_ROOT
from conftest import carved_module_path, openxfactory_root

from doc_health import families
from openxdox import gate_console as gc
Expand Down Expand Up @@ -461,7 +461,9 @@ def test_round_trip_and_doc_health_agree_about_every_fence(name):
# fenced-flag vector each module computes, which is the thing all four actually
# share.

_MOVER = REPO_ROOT / "scripts" / "proposal-support.py"
# openxFactory's own forward gate, which the carve left in openxFactory: read
# from the composed tree (plan 038 T103).
_MOVER = openxfactory_root() / "scripts" / "proposal-support.py"


def _mover_module():
Expand Down Expand Up @@ -727,9 +729,11 @@ def test_the_shared_predicate_is_spelled_the_same_in_all_three():
"""The algorithm, not just its outcome on these fixtures: all three lstrip (or
trimStart) and then test the literal three backticks. A fixture set can only
ever sample the input space; this pins the rule itself."""
mine = (REPO_ROOT / "scripts/ideation_dashboard/round_trip.py").read_text(
encoding="utf-8")
fam = (REPO_ROOT / "scripts/doc_health/families.py").read_text(encoding="utf-8")
# Each read where its module now lives (plan 038 T103): `round_trip.py` at
# its carved home, this leg's `src/openxdox/`, and `families.py` where this
# process imports it from, openxFactory's composed tree.
mine = carved_module_path("round_trip.py").read_text(encoding="utf-8")
fam = Path(families.__file__).read_text(encoding="utf-8")
js = OUTLINE_MODEL_JS.read_text(encoding="utf-8")
assert 'return line.lstrip().startswith("```")' in mine
assert 'if line.lstrip().startswith("```")' in fam
Expand Down
Loading