Files
zeekay 1b367e2b62 chore: rebase the tree onto upstream master
The tree was a debranded snapshot of upstream taken around 2026-02-20, and
upstream has moved about five months since. This replaces it with upstream
master, mechanically re-derived: bin/debrand does the rename, and the
pipeline and squashed migrations are restored from the shipped tree.

Not a merge. The previous import replaced the tree wholesale in a single
commit, so there is no shared content history to merge against. Reproducing
the rename on the new tree is what actually converges.

What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints,
compose files, LLM.md, and insights/migrations. The squashed initial
migration is load-bearing — the live database records it by name, so
upstream's ~918 individual migrations cannot come back.

Nine products are dropped as unreferenced. Twenty-one more that we do not run
are kept anyway because the core app still imports them; unpicking those is a
refactor and does not belong in a rebase.

This base does not build yet, and the reasons are not in the rename:
upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against
our 4.2, and the dependency manifests still name upstream packages that we
republish under our own names. Those are decisions, not renames.
2026-08-01 15:44:40 -07:00

1733 lines
72 KiB
Python

"""Tests for product lint checks — focused on PackageJsonScriptsCheck."""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from insightscli_commands.product import gh as gh_module
from insightscli_commands.product.checks import (
CheckContext,
FileFolderConflictsCheck,
IsolationChainCheck,
OrphanedTestFilesCheck,
PackageJsonScriptsCheck,
ProductYamlCheck,
ProductYamlOwnersCheck,
_has_test_files,
_is_noop_script,
_names_from_pattern,
_parse_pytest_paths,
has_legacy_interface_leaks,
validate_facade_alternation,
validate_interface_blocks,
validate_tach_references,
)
from insightscli_commands.product.isolation import (
facade_carveout_modules,
facade_class_imports,
has_narrowed_turbo_inputs,
permanent_interface_modules,
routes_in_turbo_inputs,
uncovered_carveout_modules,
uncovered_permanent_modules,
unqualified_permanent_modules,
unwatched_garages,
)
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_product(
tmp_path: Path,
*,
scripts: dict[str, str] | None = None,
has_backend: bool = True,
isolated: bool = False,
test_files: list[str] | None = None,
extra_dirs: list[str] | None = None,
) -> CheckContext:
"""Build a minimal product directory and return a CheckContext for it."""
product_dir = tmp_path / "my_product"
product_dir.mkdir()
backend_dir = product_dir / "backend"
if has_backend:
backend_dir.mkdir()
if isolated:
(backend_dir / "facade").mkdir(parents=True, exist_ok=True)
(backend_dir / "facade" / "contracts.py").write_text("")
(backend_dir / "facade" / "api.py").write_text("def get_thing():\n pass\n")
if scripts is not None:
(product_dir / "package.json").write_text(json.dumps({"scripts": scripts}))
if test_files:
for tf in test_files:
p = backend_dir / tf
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text("")
if extra_dirs:
for d in extra_dirs:
(product_dir / d).mkdir(parents=True, exist_ok=True)
return CheckContext(
name="my_product",
product_dir=product_dir,
backend_dir=backend_dir,
is_isolated=isolated,
structure={},
detailed=False,
)
def _write_facade_product(
tmp_path: Path,
*,
name: str = "my_product",
facade_files: dict[str, str] | None = None,
sources: dict[str, str] | None = None,
turbo_inputs: list[str] | None = None,
) -> tuple[Path, Path]:
"""Build a product with a facade/ package plus arbitrary internal source files.
`facade_files` are written under backend/facade/; `sources` are backend-relative paths
(parents created), used both for the modules a facade re-exports from and for making a
garage directory exist. Returns (product_dir, backend_dir)."""
product_dir = tmp_path / name
backend_dir = product_dir / "backend"
facade = backend_dir / "facade"
facade.mkdir(parents=True)
(facade / "contracts.py").write_text("")
for fname, content in (facade_files or {}).items():
(facade / fname).write_text(content)
for rel, content in (sources or {}).items():
path = backend_dir / rel
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content)
if turbo_inputs is not None:
(product_dir / "turbo.json").write_text(
json.dumps({"tasks": {"backend:contract-check": {"inputs": turbo_inputs}}})
)
return product_dir, backend_dir
check = PackageJsonScriptsCheck()
# ---------------------------------------------------------------------------
# Unit tests for helpers
# ---------------------------------------------------------------------------
class TestParseHelpers:
@pytest.mark.parametrize(
"script, expected",
[
("pytest -c ../../pytest.ini --rootdir ../.. backend/tests -v --tb=short", ["backend/tests"]),
("pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short", ["backend/"]),
(
"pytest -c ../../pytest.ini --rootdir ../.. backend/ stats/tests -v --tb=short",
["backend/", "stats/tests"],
),
("pytest backend/test_max_tools.py", ["backend/test_max_tools.py"]),
("echo 'No backend tests'", []),
("pytest -v", []),
("pytest -c ../../pytest.ini --rootdir ../.. -k 'not slow' backend/tests", ["backend/tests"]),
],
)
def test_parse_pytest_paths(self, script: str, expected: list[str]) -> None:
assert _parse_pytest_paths(script) == expected
@pytest.mark.parametrize(
"script, expected",
[
("echo 'No backend tests'", True),
("echo skip", True),
("true", True),
("exit 0", True),
(":", True),
("pytest backend/tests", False),
("pytest -v", False),
],
)
def test_is_noop_script(self, script: str, expected: bool) -> None:
assert _is_noop_script(script) == expected
def test_has_test_files_true(self, tmp_path: Path) -> None:
(tmp_path / "test_foo.py").write_text("")
assert _has_test_files(tmp_path) is True
def test_has_test_files_nested(self, tmp_path: Path) -> None:
(tmp_path / "tests").mkdir()
(tmp_path / "tests" / "test_bar.py").write_text("")
assert _has_test_files(tmp_path) is True
def test_has_test_files_suffix_convention(self, tmp_path: Path) -> None:
(tmp_path / "foo_test.py").write_text("")
assert _has_test_files(tmp_path) is True
def test_has_test_files_false(self, tmp_path: Path) -> None:
(tmp_path / "models.py").write_text("")
assert _has_test_files(tmp_path) is False
def test_has_test_files_empty_dir(self, tmp_path: Path) -> None:
assert _has_test_files(tmp_path) is False
# ---------------------------------------------------------------------------
# Presence checks
# ---------------------------------------------------------------------------
class TestPresenceChecks:
def test_skip_when_no_backend_dir(self, tmp_path: Path) -> None:
ctx = _make_product(tmp_path, has_backend=False)
result = check.run(ctx)
assert result.skip is True
def test_backend_test_required_when_backend_exists(self, tmp_path: Path) -> None:
ctx = _make_product(tmp_path, scripts={})
result = check.run(ctx)
assert any("missing 'backend:test'" in i for i in result.issues)
def test_backend_test_present_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
extra_dirs=["backend"],
)
result = check.run(ctx)
assert not result.issues
def test_contract_check_required_for_isolated(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
isolated=True,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert any("missing 'backend:contract-check'" in i for i in result.issues)
def test_contract_check_present_for_isolated_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short",
"backend:contract-check": "echo 'Contract files unchanged'",
},
isolated=True,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert not result.issues
def test_invalid_json_returns_issue(self, tmp_path: Path) -> None:
ctx = _make_product(tmp_path, has_backend=True)
(ctx.product_dir / "package.json").write_text("{invalid json")
result = check.run(ctx)
assert any("not valid JSON" in i for i in result.issues)
# ---------------------------------------------------------------------------
# Absence checks
# ---------------------------------------------------------------------------
class TestAbsenceChecks:
def test_contract_check_forbidden_for_non_isolated(self, tmp_path: Path) -> None:
"""Non-isolated product with contract-check causes turbo-discover misclassification."""
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short",
"backend:contract-check": "echo 'Contract files unchanged'",
},
isolated=False,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert result.issues
assert any("turbo-discover" in i for i in result.issues)
def test_no_contract_check_for_non_isolated_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
isolated=False,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert not result.issues
def test_contract_check_forbidden_with_deferred_presentation_entries(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""An isolated product still owing presentation-wave work can't opt into the skip."""
import insightscli_commands.product.isolation as isolation_module
monkeypatch.setattr(isolation_module, "presentation_bypass_entries", lambda *_a, **_k: ["e1", "e2"])
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short",
"backend:contract-check": "echo 'Contract files unchanged'",
},
isolated=True,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert any("presentation-wave ignore_imports" in i for i in result.issues)
# and it must not nag the same product to *add* the script it can't have yet
assert not any("missing 'backend:contract-check'" in i for i in result.issues)
# ---------------------------------------------------------------------------
# Isolation chain: earned-but-not-turned-on enforcement
# ---------------------------------------------------------------------------
_NARROWED_TURBO = {
"extends": ["//"],
"tasks": {
"backend:contract-check": {
"inputs": ["backend/facade/**", "backend/presentation/**"],
"outputs": [],
"cache": True,
}
},
}
_NARROWED_TURBO_WITH_ROUTES = {
"extends": ["//"],
"tasks": {
"backend:contract-check": {
"inputs": ["backend/facade/**", "backend/presentation/**", "backend/routes.py"],
"outputs": [],
"cache": True,
}
},
}
chain_check = IsolationChainCheck()
_WITH_SCRIPT = {
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short",
"backend:contract-check": "echo 'Contract files unchanged'",
}
def _seal_externally(monkeypatch: pytest.MonkeyPatch) -> None:
# The tmp fixture product isn't declared in the repo's real tach.toml/pyproject.toml,
# so force compute_isolation_status to see an externally sealed, internally clean product.
import insightscli_commands.product.isolation as isolation_module
monkeypatch.setattr(isolation_module, "has_tach_interface", lambda *_a, **_k: True)
monkeypatch.setattr(isolation_module, "has_legacy_interface_leaks", lambda *_a, **_k: False)
monkeypatch.setattr(isolation_module, "presentation_bypass_entries", lambda *_a, **_k: [])
class TestIsolationChainTurnOn:
def test_eligible_with_script_but_no_narrowed_turbo_fails(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
result = chain_check.run(ctx)
assert any("inert" in i for i in result.issues)
assert result.file == "products/my_product/turbo.json"
def test_eligible_with_narrowed_turbo_passes(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
assert not result.issues
def test_eligible_without_script_is_not_nagged_to_narrow_turbo(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# Eligible + sealed but the contract-check script isn't added yet: PackageJsonScriptsCheck
# owns nagging for the script, so IsolationChainCheck must not raise the turn-on issue
# (which would falsely claim the product "carries 'backend:contract-check'").
_seal_externally(monkeypatch)
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
isolated=True,
)
result = chain_check.run(ctx)
assert not any("inert" in i for i in result.issues)
def test_not_externally_sealed_does_not_demand_turbo(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
# Without the tach interface the product isn't externally sealed — TachCheck owns that
# failure, so the chain check must not pile on a turbo-narrowing demand.
import insightscli_commands.product.isolation as isolation_module
monkeypatch.setattr(isolation_module, "has_tach_interface", lambda *_a, **_k: False)
monkeypatch.setattr(isolation_module, "has_legacy_interface_leaks", lambda *_a, **_k: False)
monkeypatch.setattr(isolation_module, "presentation_bypass_entries", lambda *_a, **_k: [])
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
result = chain_check.run(ctx)
assert not any("inert" in i for i in result.issues)
class TestIsolationChainRoutes:
def test_narrowed_with_routes_not_in_inputs_fails(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.backend_dir / "routes.py").write_text("")
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
assert any("routes.py" in i for i in result.issues)
assert result.file == "products/my_product/turbo.json"
def test_narrowed_with_routes_in_inputs_passes(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.backend_dir / "routes.py").write_text("")
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO_WITH_ROUTES))
result = chain_check.run(ctx)
assert not result.issues
def test_narrowed_with_routes_package_dir_not_in_inputs_fails(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# routes/ as a package directory (not a routes.py file) is the other form has_routes_module
# accepts — it must be demanded in the inputs the same way.
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.backend_dir / "routes").mkdir()
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
# the message must point at the package glob, not backend/routes.py
assert any("backend/routes/**" in i for i in result.issues)
def test_narrowed_without_routes_module_is_not_demanded(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# No routes.py at all — nothing to watch, so the routes demand must not fire.
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
assert not any("routes.py" in i for i in result.issues)
def test_unnarrowed_with_routes_is_not_demanded(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
# Not narrowed (no turbo.json) — contract-check still watches all of backend/, so routes.py
# is already covered and the routes demand must not fire.
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.backend_dir / "routes.py").write_text("")
result = chain_check.run(ctx)
assert not any("routes.py" in i for i in result.issues)
class TestNarrowedTurboDetection:
@pytest.mark.parametrize(
"inputs, expected",
[
(["backend/facade/**", "backend/presentation/**"], True),
(["backend/facade/**", "backend/presentation/**", "backend/routes.py"], True),
(["backend/presentation/**"], True),
(["backend/facade/**", "!backend/facade/**/__pycache__/**"], True),
# a broad glob alongside a surface glob keeps the skip inert — must not count as narrowed
(["backend/**", "backend/facade/**"], False),
(["backend/**"], False),
(["**/*.py"], False),
([], False),
# near-misses must not pass as surface (anchored on the path separator)
(["backend/facade_legacy/**"], False),
(["backend/routesmap/**"], False),
# a routes input whose path merely contains "presentation" is not a facade/presentation surface
(["backend/routes/presentation_router.py"], False),
],
)
def test_has_narrowed_turbo_inputs(self, tmp_path: Path, inputs: list[str], expected: bool) -> None:
(tmp_path / "turbo.json").write_text(json.dumps({"tasks": {"backend:contract-check": {"inputs": inputs}}}))
assert has_narrowed_turbo_inputs(tmp_path) is expected
class TestRoutesInTurboInputs:
@pytest.mark.parametrize(
"inputs, expected",
[
(["backend/facade/**", "backend/routes.py"], True),
(["backend/routes/**"], True),
(["backend/facade/**", "backend/presentation/**"], False),
# 'routes' substring in an unrelated glob must NOT count as watching the routes module
(["backend/presentation/routes_views.py"], False),
(["backend/logic/routes_helpers/**"], False),
# a negated routes exclusion must NOT count as watched
(["backend/facade/**", "!backend/routes.py"], False),
],
)
def test_routes_in_turbo_inputs(self, tmp_path: Path, inputs: list[str], expected: bool) -> None:
(tmp_path / "turbo.json").write_text(json.dumps({"tasks": {"backend:contract-check": {"inputs": inputs}}}))
assert routes_in_turbo_inputs(tmp_path) is expected
# ---------------------------------------------------------------------------
# Content checks: pytest path validation
# ---------------------------------------------------------------------------
class TestPytestPathValidation:
def test_valid_path_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/tests -v --tb=short"},
test_files=["tests/test_foo.py"],
)
result = check.run(ctx)
assert not result.issues
def test_nonexistent_path_fails(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/typo_tests -v --tb=short"},
)
result = check.run(ctx)
assert any("does not exist" in i for i in result.issues)
assert any("typo_tests" in i for i in result.issues)
def test_multiple_paths_one_missing(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ stats/tests -v --tb=short"},
extra_dirs=["backend"],
)
result = check.run(ctx)
# backend/ exists, stats/tests does not
assert any("stats/tests" in i for i in result.issues)
assert not any("backend/" in i for i in result.issues)
def test_file_path_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/test_max_tools.py -v --tb=short"
},
test_files=["test_max_tools.py"],
)
result = check.run(ctx)
assert not result.issues
# ---------------------------------------------------------------------------
# Content checks: no-op detection
# ---------------------------------------------------------------------------
class TestNoopDetection:
def test_noop_without_test_files_passes(self, tmp_path: Path) -> None:
"""echo 'No backend tests' is fine when there are genuinely no test files."""
ctx = _make_product(
tmp_path,
scripts={"backend:test": "echo 'No backend tests'"},
)
result = check.run(ctx)
assert not result.issues
def test_noop_with_test_files_fails(self, tmp_path: Path) -> None:
"""echo 'No backend tests' is wrong when test files actually exist."""
ctx = _make_product(
tmp_path,
scripts={"backend:test": "echo 'No backend tests'"},
test_files=["tests/test_something.py"],
)
result = check.run(ctx)
assert any("no-op" in i for i in result.issues)
assert any("test files" in i for i in result.issues)
# ---------------------------------------------------------------------------
# Content checks: || true detection
# ---------------------------------------------------------------------------
class TestPipeTrueDetection:
def test_pipe_true_fails(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short || true"},
extra_dirs=["backend"],
)
result = check.run(ctx)
assert any("|| true" in i for i in result.issues)
assert any("swallows" in i for i in result.issues)
def test_pipe_exit_0_fails(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short || exit 0"},
extra_dirs=["backend"],
)
result = check.run(ctx)
assert any("|| exit 0" in i for i in result.issues)
assert any("swallows" in i for i in result.issues)
def test_no_pipe_true_passes(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
extra_dirs=["backend"],
)
result = check.run(ctx)
assert not result.issues
# ---------------------------------------------------------------------------
# Combined scenario: isolated product, all good
# ---------------------------------------------------------------------------
class TestCombinedScenarios:
def test_fully_valid_isolated_product(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/tests -v --tb=short",
"backend:contract-check": "echo 'Contract files unchanged'",
},
isolated=True,
test_files=["tests/test_api.py"],
)
result = check.run(ctx)
assert not result.issues
assert any("✓ ok" in line for line in result.lines)
def test_fully_valid_legacy_product(self, tmp_path: Path) -> None:
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
isolated=False,
extra_dirs=["backend"],
)
result = check.run(ctx)
assert not result.issues
assert any("✓ ok" in line for line in result.lines)
def test_multiple_issues_reported(self, tmp_path: Path) -> None:
"""A product with several problems reports all of them."""
ctx = _make_product(
tmp_path,
scripts={
"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/nonexistent -v --tb=short || true",
"backend:contract-check": "echo 'Contract files unchanged'",
},
isolated=False,
)
result = check.run(ctx)
# Should report: contract-check forbidden, || true, nonexistent path
assert len(result.issues) >= 3
# ---------------------------------------------------------------------------
# has_legacy_interface_leaks
# ---------------------------------------------------------------------------
_TACH_SAMPLE = """\
[[modules]]
path = "products.visual_review"
depends_on = ["insights"]
layer = "modules"
[[modules]]
path = "products.experiments"
depends_on = ["ee", "insights"]
layer = "modules"
[[modules]]
path = "products.mcp_store"
depends_on = ["ee", "insights"]
layer = "modules"
# Facade + views: canonical public surface
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products\\.(experiments|mcp_store|visual_review)",
]
# Legacy leaks — experiments
[[interfaces]]
expose = [
"backend\\.models.*",
"stats\\..*",
]
from = [
"products.experiments",
]
# Legacy leaks — mcp_store
[[interfaces]]
expose = [
"backend\\.models.*",
"backend\\.oauth.*",
]
from = [
"products.mcp_store",
]
"""
class TestLegacyInterfaceLeaks:
@pytest.mark.parametrize(
"module_path, expected",
[
("products.visual_review", False),
("products.experiments", True),
("products.mcp_store", True),
("products.nonexistent", False),
],
)
def test_detection(self, module_path: str, expected: bool) -> None:
assert has_legacy_interface_leaks(_TACH_SAMPLE, module_path) == expected
def test_empty_tach(self) -> None:
assert has_legacy_interface_leaks("", "products.anything") is False
def test_only_facade_block(self) -> None:
tach = """\
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products.clean_product",
]
"""
assert has_legacy_interface_leaks(tach, "products.clean_product") is False
def test_regex_from_does_not_false_positive(self) -> None:
assert has_legacy_interface_leaks(_TACH_SAMPLE, "products.mcp") is False
# ---------------------------------------------------------------------------
# permanent-interface marker
# ---------------------------------------------------------------------------
_TACH_PERMANENT = """\
# Facade + views: canonical public surface
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products\\.(error_tracking|experiments)",
]
# isolation:permanent-interface
# error_tracking exposes its Datastore DDL to core's schema registry + frozen migrations.
[[interfaces]]
expose = [
"backend\\.embedding.*",
"backend\\.indexed_embedding.*",
"backend\\.sql.*",
]
from = [
"products.error_tracking",
]
# Legacy leaks — experiments (unmarked, a real leak)
[[interfaces]]
expose = [
"backend\\.models.*",
]
from = [
"products.experiments",
]
"""
class TestPermanentInterface:
def test_marked_block_is_not_a_leak(self) -> None:
# The DDL exposure carries the marker, so it must not hold the external seal open.
assert has_legacy_interface_leaks(_TACH_PERMANENT, "products.error_tracking") is False
def test_unmarked_block_is_still_a_leak(self) -> None:
# The experiments block exposes internals with no marker — a genuine leak.
assert has_legacy_interface_leaks(_TACH_PERMANENT, "products.experiments") is True
def test_marker_does_not_leak_across_blocks(self) -> None:
# The marker sits above the error_tracking block; the previous block's body separates
# it from the facade block, so the facade block is not mistaken for permanent (and the
# experiments leak below stays a leak — already covered above).
assert permanent_interface_modules(_TACH_PERMANENT, "products.experiments") == set()
def test_exposed_modules_returned(self) -> None:
assert permanent_interface_modules(_TACH_PERMANENT, "products.error_tracking") == {
"backend.embedding",
"backend.indexed_embedding",
"backend.sql",
}
def test_unmarked_exposure_is_not_permanent(self) -> None:
assert permanent_interface_modules(_TACH_SAMPLE, "products.experiments") == set()
@pytest.mark.parametrize(
"inputs, expected",
[
# the three DDL modules + facade satisfy the extended-surface narrowing
(["backend/facade/**", "backend/sql.py", "backend/embedding.py", "backend/indexed_embedding.py"], True),
# facade alone still narrows (permanent modules are allowed, not required, here)
(["backend/facade/**"], True),
# a broad glob alongside still keeps the skip inert
(["backend/**", "backend/sql.py"], False),
# a permanent module without any facade/presentation glob is not a real surface
(["backend/sql.py"], False),
],
)
def test_permanent_modules_count_as_extended_surface(
self, tmp_path: Path, inputs: list[str], expected: bool
) -> None:
(tmp_path / "turbo.json").write_text(json.dumps({"tasks": {"backend:contract-check": {"inputs": inputs}}}))
permanent = frozenset({"backend.sql", "backend.embedding", "backend.indexed_embedding"})
assert has_narrowed_turbo_inputs(tmp_path, permanent) is expected
def test_uncovered_permanent_modules_detected(self, tmp_path: Path) -> None:
(tmp_path / "turbo.json").write_text(
json.dumps({"tasks": {"backend:contract-check": {"inputs": ["backend/facade/**", "backend/sql.py"]}}})
)
permanent = frozenset({"backend.sql", "backend.embedding", "backend.indexed_embedding"})
assert uncovered_permanent_modules(tmp_path, permanent) == {"backend.embedding", "backend.indexed_embedding"}
def test_all_permanent_modules_covered(self, tmp_path: Path) -> None:
(tmp_path / "turbo.json").write_text(
json.dumps(
{
"tasks": {
"backend:contract-check": {
"inputs": ["backend/facade/**", "backend/sql.py", "backend/embedding.py"]
}
}
}
)
)
assert uncovered_permanent_modules(tmp_path, frozenset({"backend.sql", "backend.embedding"})) == set()
def _make_ddl_repo(tmp_path: Path, *, migration_body: str = "", schema_body: str = "") -> Path:
migrations = tmp_path / "insights" / "datastore" / "migrations"
migrations.mkdir(parents=True)
(migrations / "0001_x.py").write_text(migration_body)
(tmp_path / "insights" / "datastore" / "schema.py").write_text(schema_body)
return tmp_path
class TestPermanentInterfaceQualification:
@pytest.mark.parametrize(
"migration_body, schema_body, marked, expected",
[
# DDL module imported by a frozen migration qualifies.
("from products.foo.backend.sql import CREATE_X", "", {"backend.sql"}, set()),
# A reference from the schema registry alone qualifies too.
("", "from products.foo.backend.sql import CREATE_X", {"backend.sql"}, set()),
# A submodule import still counts as a reference to the root.
("from products.foo.backend.sql.tables import CREATE_X", "", {"backend.sql"}, set()),
# The abuse case: an internal marked permanent with no DDL consumer is flagged.
("", "", {"backend.models"}, {"backend.models"}),
# Word boundary: backend.sql_extra must not qualify backend.sql.
("from products.foo.backend.sql_extra import CREATE_X", "", {"backend.sql"}, {"backend.sql"}),
# Leaf import form counts as a reference.
("from products.foo.backend import sql", "", {"backend.sql"}, set()),
# An unrelated leaf-name token on a later line must not qualify the module.
("from products.foo.backend import models\nsql = 1", "", {"backend.sql"}, {"backend.sql"}),
# A path mentioned only in a comment must not qualify — imports come from the AST.
("# depends on products.foo.backend.models\nimport datetime", "", {"backend.models"}, {"backend.models"}),
# Same for a string literal (e.g. DDL text or a log message naming the module).
('TABLE_SQL = "see products.foo.backend.models"', "", {"backend.models"}, {"backend.models"}),
],
)
def test_qualification(
self, tmp_path: Path, migration_body: str, schema_body: str, marked: set[str], expected: set[str]
) -> None:
repo_root = _make_ddl_repo(tmp_path, migration_body=migration_body, schema_body=schema_body)
assert unqualified_permanent_modules("products.foo", frozenset(marked), repo_root=repo_root) == expected
def test_exempt_product_skips_qualification(self, tmp_path: Path) -> None:
# warehouse_sources' marker is justified by a non-DDL channel; dropping the exemption
# would turn product:lint --all red for it.
repo_root = _make_ddl_repo(tmp_path)
assert (
unqualified_permanent_modules(
"products.warehouse_sources", frozenset({"backend.models"}), repo_root=repo_root
)
== set()
)
def test_unqualified_exposure_blocks_isolation_chain(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
# A marked module that no migration/schema-registry imports must hard-block, and the issue
# must point at tach.toml where the bogus marker lives.
_seal_externally(monkeypatch)
import insightscli_commands.product.isolation as isolation_module
monkeypatch.setattr(isolation_module, "permanent_interface_modules", lambda *_a, **_k: {"backend.models"})
# Controlled corpus — don't let the assertion depend on the real repo's migrations.
monkeypatch.setattr(isolation_module, "_datastore_ddl_imports", lambda _root: frozenset())
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
result = chain_check.run(ctx)
assert any("don't qualify as a permanent interface" in i for i in result.issues)
assert result.file == "tach.toml"
# ---------------------------------------------------------------------------
# ProductYamlCheck
# ---------------------------------------------------------------------------
yaml_check = ProductYamlCheck()
owners_check = ProductYamlOwnersCheck()
def _make_yaml_ctx(tmp_path: Path, yaml_content: str | None = None) -> CheckContext:
product_dir = tmp_path / "test_product"
product_dir.mkdir()
backend_dir = product_dir / "backend"
backend_dir.mkdir()
if yaml_content is not None:
(product_dir / "product.yaml").write_text(yaml_content)
return CheckContext(
name="test_product",
product_dir=product_dir,
backend_dir=backend_dir,
is_isolated=False,
structure={},
detailed=False,
)
class TestProductYamlCheck:
def test_missing_file(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path)
result = yaml_check.run(ctx)
assert any("Missing product.yaml" in i for i in result.issues)
def test_valid_yaml(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners:\n - team-foo\n")
result = yaml_check.run(ctx)
assert not result.issues
def test_invalid_yaml(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: [\ninvalid")
result = yaml_check.run(ctx)
assert any("invalid YAML" in i for i in result.issues)
def test_non_dict_yaml(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "- just\n- a\n- list\n")
result = yaml_check.run(ctx)
assert any("must be a YAML mapping" in i for i in result.issues)
def test_missing_name(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "owners:\n - team-foo\n")
result = yaml_check.run(ctx)
assert any("missing 'name'" in i for i in result.issues)
def test_missing_owners(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\n")
result = yaml_check.run(ctx)
assert any("missing 'owners'" in i for i in result.issues)
def test_owners_must_be_list(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners: team-foo\n")
result = yaml_check.run(ctx)
assert any("list of strings" in i for i in result.issues)
def test_owners_must_be_strings(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners:\n - 123\n")
result = yaml_check.run(ctx)
assert any("list of strings" in i for i in result.issues)
def test_name_must_be_string(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: 42\nowners:\n - team-foo\n")
result = yaml_check.run(ctx)
assert any("missing 'name'" in i for i in result.issues)
class TestProductYamlOwnersCheck:
def test_skip_when_no_owners(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\n")
result = owners_check.run(ctx)
assert result.skip
def test_skip_when_owners_wrong_type(self, tmp_path: Path) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners: team-foo\n")
result = owners_check.run(ctx)
assert result.skip
def test_invalid_slug_reported(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners:\n - team-nonexistent\n")
monkeypatch.setattr(gh_module, "_fetch_attempted", True)
monkeypatch.setattr(gh_module, "_team_slugs", {"team-real"})
monkeypatch.setattr(gh_module, "_fetch_err", "")
result = owners_check.run(ctx)
assert any("team-nonexistent" in i for i in result.issues)
def test_valid_slug_passes(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners:\n - team-real\n")
monkeypatch.setattr(gh_module, "_fetch_attempted", True)
monkeypatch.setattr(gh_module, "_team_slugs", {"team-real"})
monkeypatch.setattr(gh_module, "_fetch_err", "")
result = owners_check.run(ctx)
assert not result.issues
def test_gh_unavailable_is_error(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
ctx = _make_yaml_ctx(tmp_path, "name: My product\nowners:\n - team-foo\n")
monkeypatch.setattr(gh_module, "_fetch_attempted", True)
monkeypatch.setattr(gh_module, "_team_slugs", None)
monkeypatch.setattr(gh_module, "_fetch_err", "gh CLI not found")
result = owners_check.run(ctx)
assert result.issues
assert any("gh CLI" in i for i in result.issues)
# ---------------------------------------------------------------------------
# FileFolderConflictsCheck — file vs package twin detection
# ---------------------------------------------------------------------------
# Structure mirrors product_structure.yaml: subdirs (logic/, tasks/, facade/)
# are packages regardless of whether they declare an __init__.py in the
# structure; models can be either a file or folder via can_be_folder.
_CONFLICT_STRUCTURE = {
"backend_files": {
"models.py": {"can_be_folder": True},
"logic/": {"__init__.py": {}},
"tasks/": {"tasks.py": {}}, # no __init__.py declared — namespace package
"facade/": {"api.py": {}, "contracts.py": {}},
},
}
conflict_check = FileFolderConflictsCheck()
def _make_backend(tmp_path: Path, files: list[str]) -> CheckContext:
"""Create a product with the given files/dirs under backend/. Trailing '/' = directory."""
product_dir = tmp_path / "p"
backend = product_dir / "backend"
backend.mkdir(parents=True)
for f in files:
target = backend / f.rstrip("/")
if f.endswith("/"):
target.mkdir(parents=True, exist_ok=True)
else:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text("")
return CheckContext(
name="p",
product_dir=product_dir,
backend_dir=backend,
is_isolated=False,
structure=_CONFLICT_STRUCTURE,
detailed=False,
)
class TestFileFolderConflictsCheck:
def test_skip_when_no_backend(self, tmp_path: Path) -> None:
product_dir = tmp_path / "p"
product_dir.mkdir()
ctx = CheckContext(
name="p",
product_dir=product_dir,
backend_dir=product_dir / "backend",
is_isolated=False,
structure=_CONFLICT_STRUCTURE,
detailed=False,
)
assert conflict_check.run(ctx).skip is True
@pytest.mark.parametrize(
"files, expect_conflicts",
[
# Pattern A (can_be_folder): models.py only / models/ only — both fine
(["models.py"], []),
(["models/"], []),
(["models.py", "models/"], ["models.py"]),
# Pattern B (package init): logic.py only / logic/ only — both fine
(["logic/__init__.py"], []),
(["logic.py"], []),
(["logic/"], []), # half-migrated package without __init__.py
(["logic.py", "logic/__init__.py"], ["logic.py"]),
(["logic.py", "logic/"], ["logic.py"]), # __init__.py absent — still flagged
# Pattern B also covers other canonical packages — stray tasks.py is a mistake
(["tasks/__init__.py"], []),
(["tasks.py", "tasks/__init__.py"], ["tasks.py"]),
# Namespace-package subdir (no __init__.py declared in structure) — stem still detected
(["facade/api.py"], []),
(["facade.py", "facade/api.py"], ["facade.py"]),
# Multiple conflicts at once
(["logic.py", "logic/", "models.py", "models/"], ["logic.py", "models.py"]),
],
)
def test_conflict_detection(self, tmp_path: Path, files: list[str], expect_conflicts: list[str]) -> None:
ctx = _make_backend(tmp_path, files)
result = conflict_check.run(ctx)
if not expect_conflicts:
assert not result.issues, f"unexpected conflicts: {result.issues}"
return
assert len(result.issues) == len(expect_conflicts)
for stem in expect_conflicts:
assert any(f"backend/{stem}" in i and f"backend/{stem[:-3]}/" in i for i in result.issues), result.issues
# ---------------------------------------------------------------------------
# validate_facade_alternation — global tach.toml check
# ---------------------------------------------------------------------------
def _mkproduct(products_dir: Path, name: str, *, isolated: bool) -> None:
p = products_dir / name
(p / "backend").mkdir(parents=True)
(p / "__init__.py").write_text("")
(p / "backend" / "__init__.py").write_text("")
if isolated:
(p / "backend" / "facade").mkdir()
(p / "backend" / "facade" / "contracts.py").write_text("")
_CANONICAL_BLOCK = """\
[[interfaces]]
expose = [
"backend\\\\.facade.*",
"backend\\\\.presentation\\\\.views.*",
]
from = [
"products\\\\.(alpha|beta)",
]
"""
_LEGACY_ONLY_TACH = """\
[[interfaces]]
expose = ["backend\\\\.models.*"]
from = ["products.alpha"]
"""
# Real tach.toml on disk uses literal `\\.` (two backslashes + dot).
# `_CANONICAL_BLOCK` already encodes that form via escaped backslashes in
# the Python source — `\\\\` in source is two literal backslashes at runtime.
# This row uses a non-alternation single-name `from` so the parametrized
# test additionally exercises that branch of `_names_from_pattern`.
_CANONICAL_SINGLE_NAME_TACH = (
"[[interfaces]]\n"
'expose = [\n "backend\\\\.facade.*",\n "backend\\\\.presentation\\\\.views.*",\n]\n'
'from = [\n "products\\\\.alpha",\n]\n'
)
class TestValidateFacadeAlternation:
@pytest.mark.parametrize(
"products, tach, expected_substrings",
[
# Empty tach — nothing to validate.
([], "", []),
# Only a legacy-leak block — TachCheck handles per-product, this
# validator stays quiet.
([("alpha", True)], _LEGACY_ONLY_TACH, []),
# Clean alternation: every listed product exists and is isolated.
([("alpha", True), ("beta", True)], _CANONICAL_BLOCK, []),
# Stale entry: product listed but not on disk.
([("alpha", True)], _CANONICAL_BLOCK, [("beta", "does not exist")]),
# Stale entry: product on disk but missing contracts.py.
(
[("alpha", True), ("beta", False)],
_CANONICAL_BLOCK,
[("beta", "contracts.py")],
),
# On-disk single-name `from` (no alternation) parses.
([("alpha", True)], _CANONICAL_SINGLE_NAME_TACH, []),
# Non-listed isolated products are tolerated — having
# facade/contracts.py is just scaffolding, not a commitment to
# canonical exposure.
(
[("alpha", True), ("beta", True), ("gamma", True)],
_CANONICAL_BLOCK,
[],
),
],
ids=[
"empty_tach",
"legacy_only_block_silent",
"clean_alternation",
"stale_entry_missing_on_disk",
"stale_entry_not_isolated",
"on_disk_single_name_form_parses",
"isolated_but_not_in_alternation_is_tolerated",
],
)
def test_validate(
self,
tmp_path: Path,
products: list[tuple[str, bool]],
tach: str,
expected_substrings: list[tuple[str, ...]],
) -> None:
for name, isolated in products:
_mkproduct(tmp_path, name, isolated=isolated)
issues = validate_facade_alternation(tach, tmp_path)
if not expected_substrings:
assert issues == []
return
for substrings in expected_substrings:
assert any(all(s in issue for s in substrings) for issue in issues), (
f"no issue matched all of {substrings!r}; got {issues!r}"
)
class TestNamesFromPattern:
@pytest.mark.parametrize(
"pattern, expected",
[
("products.experiments", {"experiments"}),
("products\\.experiments", {"experiments"}),
("products\\\\.experiments", {"experiments"}),
("products\\.(a|b|c)", {"a", "b", "c"}),
("products\\\\.(a|b|c)", {"a", "b", "c"}),
("products\\.(experiments|mcp_store|tracing)", {"experiments", "mcp_store", "tracing"}),
("insights.api", set()),
("products.something.deeper", set()),
("", set()),
],
)
def test_extraction(self, pattern: str, expected: set[str]) -> None:
assert _names_from_pattern(pattern) == expected
# ---------------------------------------------------------------------------
# validate_interface_blocks — per-block structural checks
# ---------------------------------------------------------------------------
def _iface(expose: list[str], frm: str = "products.x") -> str:
expose_str = ", ".join(f'"{e}"' for e in expose)
return f'[[interfaces]]\nexpose = [{expose_str}]\nfrom = ["{frm}"]\n'
class TestValidateInterfaceBlocks:
@pytest.mark.parametrize(
"expose, expected_issue",
[
# Pure facade — clean.
(["backend\\\\.facade.*", "backend\\\\.presentation\\\\.views.*"], None),
# Pure legacy — clean.
(["backend\\\\.models.*", "backend\\\\.logic.*"], None),
# Mixed facade + internal — error.
(
["backend\\\\.facade.*", "backend\\\\.models.*"],
"mixes facade/presentation",
),
# Mixed presentation + internal — error.
(
["backend\\\\.presentation\\\\.views.*", "backend\\\\.logic.*"],
"mixes facade/presentation",
),
# Overly broad: backend.* (raw).
(["backend.*"], "overly broad"),
# Overly broad: backend\\..* (tach regex form).
(["backend\\\\..*"], "overly broad"),
# Overly broad: backend.** (globstar).
(["backend\\\\.**"], "overly broad"),
# Specific submodule — not broad.
(["backend\\\\.models.*"], None),
# Facade + routes — routes is public surface, not a mix.
(["backend\\\\.facade.*", "backend\\\\.routes.*"], None),
],
ids=[
"pure_facade",
"pure_legacy",
"mixed_facade_internal",
"mixed_presentation_internal",
"broad_raw",
"broad_tach_regex",
"broad_globstar",
"specific_submodule",
"facade_plus_routes",
],
)
def test_blocks(self, expose: list[str], expected_issue: str | None) -> None:
tach = _iface(expose)
issues = validate_interface_blocks(tach)
if expected_issue is None:
assert issues == [], f"unexpected issues: {issues}"
else:
assert any(expected_issue in i for i in issues), (
f"expected substring {expected_issue!r} in issues; got {issues!r}"
)
# ---------------------------------------------------------------------------
# validate_tach_references — referential integrity
# ---------------------------------------------------------------------------
class TestValidateTachReferences:
@pytest.mark.parametrize(
"tach, expected_substrings",
[
# Clean: interface references existing module.
(
'[[modules]]\npath = "products.alpha"\ndepends_on = []\n\n'
'[[interfaces]]\nexpose = ["backend\\\\.models.*"]\nfrom = ["products.alpha"]\n',
[],
),
# Dangling interface: references nonexistent module.
(
'[[modules]]\npath = "products.alpha"\ndepends_on = []\n\n'
'[[interfaces]]\nexpose = ["backend\\\\.models.*"]\nfrom = ["products.ghost"]\n',
[("products.ghost", "dangling interface")],
),
# Dangling depends_on.
(
'[[modules]]\npath = "products.alpha"\ndepends_on = ["products.ghost"]\n',
[("products.ghost", "dangling dependency")],
),
# Clean depends_on.
(
'[[modules]]\npath = "products.alpha"\ndepends_on = []\n\n'
'[[modules]]\npath = "products.beta"\ndepends_on = ["products.alpha"]\n',
[],
),
# Both dangling.
(
'[[modules]]\npath = "products.a"\ndepends_on = ["products.missing_dep"]\n\n'
'[[interfaces]]\nexpose = ["backend\\\\.x.*"]\nfrom = ["products.missing_iface"]\n',
[("missing_dep", "dangling dependency"), ("missing_iface", "dangling interface")],
),
],
ids=[
"clean_interface",
"dangling_interface",
"dangling_depends_on",
"clean_depends_on",
"both_dangling",
],
)
def test_references(self, tach: str, expected_substrings: list[tuple[str, str]]) -> None:
issues = validate_tach_references(tach)
if not expected_substrings:
assert issues == []
return
for substrings in expected_substrings:
assert any(all(s in issue for s in substrings) for issue in issues), (
f"no issue matched all of {substrings!r}; got {issues!r}"
)
# ---------------------------------------------------------------------------
# validate_facade_alternation — alphabetical sort check
# ---------------------------------------------------------------------------
class TestAlternationSorting:
def test_sorted_passes(self, tmp_path: Path) -> None:
_mkproduct(tmp_path, "alpha", isolated=True)
_mkproduct(tmp_path, "beta", isolated=True)
tach = _iface(
["backend\\\\.facade.*", "backend\\\\.presentation\\\\.views.*"],
"products\\\\.(alpha|beta)",
)
assert validate_facade_alternation(tach, tmp_path) == []
def test_unsorted_fails(self, tmp_path: Path) -> None:
_mkproduct(tmp_path, "alpha", isolated=True)
_mkproduct(tmp_path, "beta", isolated=True)
tach = _iface(
["backend\\\\.facade.*", "backend\\\\.presentation\\\\.views.*"],
"products\\\\.(beta|alpha)",
)
issues = validate_facade_alternation(tach, tmp_path)
assert any("not sorted" in i for i in issues)
# ---------------------------------------------------------------------------
# OrphanedTestFilesCheck — ensures every product test file is reachable by
# either backend:test or a known external runner.
# ---------------------------------------------------------------------------
class TestOrphanedTestFilesCheck:
"""Verifies the lint catches test files left behind by misconfigured scripts."""
_orphan_check = OrphanedTestFilesCheck()
def _ctx(self, tmp_path: Path, *, scripts: dict[str, str] | None = None, name: str = "my_product") -> CheckContext:
product_dir = tmp_path / name
product_dir.mkdir()
backend_dir = product_dir / "backend"
backend_dir.mkdir()
if scripts is not None:
(product_dir / "package.json").write_text(json.dumps({"scripts": scripts}))
return CheckContext(
name=name,
product_dir=product_dir,
backend_dir=backend_dir,
is_isolated=False,
structure={},
detailed=False,
)
def test_skip_when_no_test_files(self, tmp_path: Path) -> None:
ctx = self._ctx(tmp_path)
result = self._orphan_check.run(ctx)
assert result.skip is True
def test_orphan_flagged_when_backend_test_missing(self, tmp_path: Path) -> None:
ctx = self._ctx(tmp_path)
(ctx.backend_dir / "api" / "test").mkdir(parents=True)
(ctx.backend_dir / "api" / "test" / "test_thing.py").write_text("")
result = self._orphan_check.run(ctx)
assert any("backend/api/test/test_thing.py" in line for line in result.lines)
assert result.issues
def test_no_orphans_when_backend_test_covers(self, tmp_path: Path) -> None:
ctx = self._ctx(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
)
(ctx.backend_dir / "api" / "test").mkdir(parents=True)
(ctx.backend_dir / "api" / "test" / "test_thing.py").write_text("")
result = self._orphan_check.run(ctx)
assert not result.issues
def test_specific_file_path_in_pytest_does_not_false_flag(self, tmp_path: Path) -> None:
ctx = self._ctx(
tmp_path,
scripts={"backend:test": "pytest backend/test_max_tools.py -v"},
)
(ctx.backend_dir / "test_max_tools.py").write_text("")
result = self._orphan_check.run(ctx)
assert not result.issues
def test_directory_prefix_does_not_eat_unrelated_paths(self, tmp_path: Path) -> None:
ctx = self._ctx(
tmp_path,
scripts={"backend:test": "pytest backend/api"},
)
(ctx.backend_dir / "api").mkdir()
(ctx.backend_dir / "api" / "test_covered.py").write_text("")
(ctx.backend_dir / "api_v2").mkdir()
(ctx.backend_dir / "api_v2" / "test_uncovered.py").write_text("")
result = self._orphan_check.run(ctx)
assert any("api_v2/test_uncovered.py" in i for i in result.issues)
assert not any("api/test_covered.py" in i for i in result.issues)
def test_dags_tests_exempted_via_external_runner(self, tmp_path: Path) -> None:
# ci-dagster.yml runs `pytest products/**/dags`. The check should not
# flag test files under `dags/` even when backend:test doesn't cover them.
ctx = self._ctx(tmp_path, scripts={"backend:test": "pytest backend/"})
(ctx.product_dir / "dags" / "tests").mkdir(parents=True)
(ctx.product_dir / "dags" / "tests" / "test_thing.py").write_text("")
result = self._orphan_check.run(ctx)
assert not result.issues
def test_per_product_exemption_applied(self, tmp_path: Path) -> None:
# products/tasks/backend/temporal/ is covered by ci-backend.yml Temporal
# segment, not the product matrix.
ctx = self._ctx(
tmp_path,
scripts={"backend:test": "pytest backend/tests backend/services"},
name="tasks",
)
(ctx.backend_dir / "temporal" / "tests").mkdir(parents=True)
(ctx.backend_dir / "temporal" / "tests" / "test_workflow.py").write_text("")
result = self._orphan_check.run(ctx)
assert not result.issues
def test_per_product_exemption_does_not_apply_to_other_products(self, tmp_path: Path) -> None:
ctx = self._ctx(
tmp_path,
scripts={"backend:test": "pytest backend/tests"},
name="not_tasks",
)
(ctx.backend_dir / "temporal" / "tests").mkdir(parents=True)
(ctx.backend_dir / "temporal" / "tests" / "test_workflow.py").write_text("")
result = self._orphan_check.run(ctx)
assert any("backend/temporal/tests/test_workflow.py" in i for i in result.issues)
_IGNORE_IMPORTS_PYPROJECT = """
[tool.importlinter]
root_packages = ["products"]
[[tool.importlinter.contracts]]
name = "presentation must use facade"
type = "forbidden"
source_modules = ["products.*.backend.presentation"]
forbidden_modules = ["products.*.backend"]
ignore_imports = [
"products.**.backend.presentation.** -> products.**.backend.facade.**",
"products.logs.backend.presentation.views.api -> products.logs.backend.runner",
"products.logs.backend.presentation.views.alerts_api -> products.logs.backend.models",
"products.tracing.backend.presentation.views -> products.tracing.backend.logic",
]
"""
@pytest.mark.parametrize(
"name,expected",
[
("logs", 2),
("tracing", 1),
("wizard", 0),
],
)
def test_presentation_bypass_entries(name: str, expected: int) -> None:
from insightscli_commands.product.isolation import presentation_bypass_entries
assert len(presentation_bypass_entries(name, _IGNORE_IMPORTS_PYPROJECT)) == expected
def test_presentation_bypass_entries_handles_broken_toml() -> None:
from insightscli_commands.product.isolation import presentation_bypass_entries
assert presentation_bypass_entries("logs", "not = [valid") == []
# ---------------------------------------------------------------------------
# Wiring couplings — facade class re-exports and garage coverage
# ---------------------------------------------------------------------------
class TestFacadeClassImports:
@pytest.mark.parametrize(
"facade_files, sources, expected",
[
# a pure re-export module hands out every class it imports from a non-garage module
(
{"queries.py": "from ..logic import Thing\n__all__ = ['Thing']\n"},
{"logic.py": "class Thing:\n pass\n"},
{"Thing"},
),
# a class re-exported from a garage is sanctioned wiring, never flagged
(
{"queries.py": "from ..insightsql_queries.runner import Runner\n__all__ = ['Runner']\n"},
{"insightsql_queries/runner.py": "class Runner:\n pass\n"},
set(),
),
# a re-exported function is the designed delegation pattern, never flagged
(
{"helpers.py": "from ..logic import do_it\n__all__ = ['do_it']\n"},
{"logic.py": "def do_it():\n pass\n"},
set(),
),
# a third-party / core source is not product-internal
({"queries.py": "from insights.models import Team\n__all__ = ['Team']\n"}, {}, set()),
# a TYPE_CHECKING import is type-only — nothing crosses at runtime
(
{
"queries.py": "from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n from ..logic import Thing\n"
},
{"logic.py": "class Thing:\n pass\n"},
set(),
),
# a data-capability module (has functions) without __all__ imports an internal class for
# its own use, not to hand out
(
{"api2.py": "from ..logic import Thing\n\n\ndef build():\n return Thing()\n"},
{"logic.py": "class Thing:\n pass\n"},
set(),
),
# ...but the same module hands the class out once it advertises it in __all__
(
{
"api2.py": "from ..logic import Thing\n\n\ndef build():\n return 1\n\n\n__all__ = ['Thing', 'build']\n"
},
{"logic.py": "class Thing:\n pass\n"},
{"Thing"},
),
# ...or re-exports it with the explicit self-alias idiom (which also suppresses F401)
(
{"api2.py": "from ..logic import Thing as Thing\n\n\ndef build():\n return 1\n"},
{"logic.py": "class Thing:\n pass\n"},
{"Thing"},
),
# a renaming alias is a private import for internal use, not the re-export idiom
(
{"api2.py": "from ..logic import Thing as _Thing\n\n\ndef build():\n return _Thing()\n"},
{"logic.py": "class Thing:\n pass\n"},
set(),
),
# a PEP 562 lazy map hands out every class it maps
(
{
"api2.py": "_LAZY = {'Thing': 'logic'}\n\n\ndef __getattr__(name):\n import importlib\n\n return getattr(importlib.import_module('x'), name)\n"
},
{"logic.py": "class Thing:\n pass\n"},
{"Thing"},
),
# a class surfaced through a package __init__ still resolves (one re-export hop)
(
{"queries.py": "from ..logic import Thing\n__all__ = ['Thing']\n"},
{"logic/__init__.py": "from .impl import Thing\n", "logic/impl.py": "class Thing:\n pass\n"},
{"Thing"},
),
],
)
def test_detection(
self, tmp_path: Path, facade_files: dict[str, str], sources: dict[str, str], expected: set[str]
) -> None:
_, backend = _write_facade_product(tmp_path, facade_files=facade_files, sources=sources)
assert {f.class_name for f in facade_class_imports(backend, "my_product")} == expected
def test_carveout_is_not_a_violation_but_is_tracked_for_coverage(self, tmp_path: Path) -> None:
facade = {
"team_extension.py": "from ..models.tcac import TeamCustomerAnalyticsConfig\n__all__ = ['TeamCustomerAnalyticsConfig']\n"
}
sources = {"models/tcac.py": "class TeamCustomerAnalyticsConfig:\n pass\n"}
_, backend = _write_facade_product(tmp_path, name="customer_analytics", facade_files=facade, sources=sources)
assert facade_class_imports(backend, "customer_analytics") == []
assert facade_carveout_modules(backend, "customer_analytics") == {"backend/models/tcac.py"}
def test_carveout_class_is_an_ordinary_violation_for_a_product_that_does_not_own_it(self, tmp_path: Path) -> None:
# the carve-out is keyed (product, class): another product re-exporting the same class name
# gets no free pass.
facade = {
"team_extension.py": "from ..models.tcac import TeamCustomerAnalyticsConfig\n__all__ = ['TeamCustomerAnalyticsConfig']\n"
}
sources = {"models/tcac.py": "class TeamCustomerAnalyticsConfig:\n pass\n"}
_, backend = _write_facade_product(tmp_path, name="unrelated_product", facade_files=facade, sources=sources)
assert {f.class_name for f in facade_class_imports(backend, "unrelated_product")} == {
"TeamCustomerAnalyticsConfig"
}
class TestUnwatchedGarages:
@pytest.mark.parametrize(
"garage_file, turbo_inputs, expected",
[
("tasks/tasks.py", ["backend/facade/**"], {"backend/tasks/"}), # garage present but not watched
("tasks/tasks.py", ["backend/facade/**", "backend/tasks/**"], set()), # watched — satisfied
# un-narrowed: contract-check watches everything, so nothing is "unwatched"
("tasks/tasks.py", None, set()),
# the flat-file garage form is detected and satisfied the same way
("tasks.py", ["backend/facade/**"], {"backend/tasks.py"}),
("tasks.py", ["backend/facade/**", "backend/tasks.py"], set()),
# near-miss prefixes must not count as covering the directory garage
("tasks/tasks.py", ["backend/facade/**", "backend/tasks.py"], {"backend/tasks/"}),
("tasks/tasks.py", ["backend/facade/**", "backend/tasks_extra/**"], {"backend/tasks/"}),
# a flat-file garage needs an exact input, not a shared prefix
("tasks.py", ["backend/facade/**", "backend/tasks.py.bak"], {"backend/tasks.py"}),
],
)
def test_present_garage_coverage(
self, tmp_path: Path, garage_file: str, turbo_inputs: list[str] | None, expected: set[str]
) -> None:
product_dir, _ = _write_facade_product(tmp_path, sources={garage_file: ""}, turbo_inputs=turbo_inputs)
assert unwatched_garages(product_dir) == expected
class TestNarrowedTurboWiringSurface:
@pytest.mark.parametrize(
"inputs, expected",
[
(["backend/facade/**", "backend/insightsql_queries/**"], True), # a garage dir counts as narrowing surface
(["backend/facade/**", "backend/max_tools.py"], True), # a single-file garage counts too
(["backend/facade/**", "backend/tasks.py"], True), # the flat-file tasks garage form
(["backend/insightsql_queries/**"], False), # garage alone isn't a real contract surface
(["backend/facade/**", "backend/logic/**"], False), # a non-wiring dir breaks the narrowing
],
)
def test_garage_inputs_count_as_narrowing(self, tmp_path: Path, inputs: list[str], expected: bool) -> None:
product_dir, _ = _write_facade_product(tmp_path, turbo_inputs=inputs)
assert has_narrowed_turbo_inputs(product_dir) is expected
def test_carveout_module_is_accepted_surface_only_when_declared(self, tmp_path: Path) -> None:
# a carve-out defining module is an odd input (not facade/garage): it only counts as
# narrowing when the caller passes it as a known carve-out module.
product_dir, _ = _write_facade_product(tmp_path, turbo_inputs=["backend/facade/**", "backend/models/tcac.py"])
assert has_narrowed_turbo_inputs(product_dir) is False
assert has_narrowed_turbo_inputs(product_dir, frozenset(), frozenset({"backend/models/tcac.py"})) is True
@pytest.mark.parametrize(
"inputs, expected",
[
(["backend/facade/**", "backend/models/tcac.py"], set()), # covered
(["backend/facade/**"], {"backend/models/tcac.py"}), # missing -> uncovered
],
)
def test_carveout_module_coverage(self, tmp_path: Path, inputs: list[str], expected: set[str]) -> None:
product_dir, _ = _write_facade_product(tmp_path, turbo_inputs=inputs)
assert uncovered_carveout_modules(product_dir, frozenset({"backend/models/tcac.py"})) == expected
def _add_facade_reexport(ctx: CheckContext) -> None:
"""Give the fixture product a wiring violation: a pure re-export facade module handing out a
non-garage internal class."""
(ctx.backend_dir / "facade" / "queries.py").write_text("from ..logic import Thing\n__all__ = ['Thing']\n")
(ctx.backend_dir / "logic.py").write_text("class Thing:\n pass\n")
class TestIsolationChainWiringGate:
def test_narrowed_facade_violation_blocks(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
_add_facade_reexport(ctx)
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
assert any("Thing" in i and "wiring location" in i for i in result.issues)
def test_unnarrowed_facade_violation_warns_and_suppresses_the_narrowing_nag(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# Un-narrowed: the skip is inert, so the leak is a warning, not a block. And the "you're
# eligible, narrow now" nag must be suppressed — the wiring gate would reject that narrowing.
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
_add_facade_reexport(ctx)
result = chain_check.run(ctx)
# the leak is a warning that also explains what blocks narrowing...
assert any("Thing" in w and "narrowing is blocked" in w for w in result.warnings)
assert not any("Thing" in i for i in result.issues)
# ...and the "you're eligible, narrow now" nag is suppressed.
assert not any("inert" in i for i in result.issues)
def test_narrowed_unwatched_garage_blocks(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
(ctx.backend_dir / "tasks").mkdir()
(ctx.backend_dir / "tasks" / "tasks.py").write_text("")
(ctx.product_dir / "turbo.json").write_text(json.dumps(_NARROWED_TURBO))
result = chain_check.run(ctx)
assert any("backend/tasks/" in i and "wiring location" in i for i in result.issues)
class TestPackageJsonScriptsWiringWithheld:
def test_eligible_facade_violation_is_not_nagged_to_add_the_script(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# A demoted product (facade hands out unsanctioned classes) that dropped its script must not
# be told to add it back — it can't soundly narrow.
_seal_externally(monkeypatch)
ctx = _make_product(
tmp_path,
scripts={"backend:test": "pytest -c ../../pytest.ini --rootdir ../.. backend/ -v --tb=short"},
isolated=True,
)
_add_facade_reexport(ctx)
result = check.run(ctx)
assert not any("contract-check" in i for i in result.issues)
def test_eligible_facade_violation_keeps_an_existing_script(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# The un-narrowed script+broad products carry a facade violation too; the absence check keys
# on plain eligibility, so they must not be told to remove the script.
_seal_externally(monkeypatch)
ctx = _make_product(tmp_path, scripts=_WITH_SCRIPT, isolated=True)
_add_facade_reexport(ctx)
result = check.run(ctx)
assert not any("must not have" in i or "remove 'backend:contract-check'" in i for i in result.issues)