Files
infospace-bench/tests/test_replacement_readiness.py

162 lines
5.3 KiB
Python

import json
import os
import shutil
import subprocess
import sys
from pathlib import Path
import yaml
from infospace_bench import load_infospace
from infospace_bench.engine import plan_asset_sync
from infospace_bench.evaluation_io import read_history
from infospace_bench.history import read_metrics_file
from infospace_bench.markdown_adapter import validate_infospace_artifacts
from infospace_bench.semantics import list_entities, list_relations
REPO_ROOT = Path(__file__).resolve().parents[1]
BOOTSTRAP = REPO_ROOT / "infospaces" / "bootstrap-pilot"
LEGACY_SLICE = REPO_ROOT / "infospaces" / "wealth-vsm-legacy-slice"
LEGACY_COMMANDS = {
"init",
"status",
"entities",
"chapters",
"evaluate",
"eval-summary",
"relations",
"classify",
"viability",
"check",
"history",
"history-diff",
"bind-discipline",
"process",
"stale-mappings",
"graph",
}
def cli_env() -> dict[str, str]:
env = os.environ.copy()
env["PYTHONPATH"] = str(REPO_ROOT / "src") + ":/home/worsch/markitect-tool/src"
return env
def run_cli(*args: str, cwd: Path | None = None) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[sys.executable, "-m", "infospace_bench", *args],
check=False,
cwd=cwd or REPO_ROOT,
env=cli_env(),
text=True,
capture_output=True,
)
def copy_infospace(source: Path, tmp_path: Path) -> Path:
target = tmp_path / source.name
shutil.copytree(source, target)
return target
def test_legacy_command_parity_guide_covers_required_commands() -> None:
guide = REPO_ROOT / "docs" / "legacy-command-parity.md"
text = guide.read_text(encoding="utf-8")
for command in sorted(LEGACY_COMMANDS):
assert f"`markitect infospace {command}`" in text
assert "replaced" in text
assert "reframed" in text
assert "delegated" in text
assert "deferred" in text
assert "retired" in text
def test_bootstrap_pilot_replacement_gate_cli_round_trip(tmp_path: Path) -> None:
root = copy_infospace(BOOTSTRAP, tmp_path)
status = run_cli("status", str(root))
validation = run_cli("validate", str(root))
check = run_cli("check", str(root))
viability = run_cli("viability", str(root))
graph = run_cli("graph", str(root), "--format", "mermaid")
exported = run_cli("export", str(root))
workflow = run_cli("workflow", "run", str(root), "bootstrap-readiness")
assert status.returncode == 0, status.stderr
assert validation.returncode == 0, validation.stderr
assert check.returncode == 0, check.stderr
assert viability.returncode == 0, viability.stderr
assert graph.returncode == 0, graph.stderr
assert exported.returncode == 0, exported.stderr
assert workflow.returncode == 0, workflow.stderr
status_payload = json.loads(status.stdout)
check_payload = json.loads(check.stdout)
viability_payload = json.loads(viability.stdout)
workflow_payload = json.loads(workflow.stdout)
assert status_payload["slug"] == "bootstrap-pilot"
assert status_payload["artifact_count"] == 4
assert status_payload["artifact_kinds"] == {"generated": 2, "source": 2}
assert check_payload["metrics"]["coverage_ratio"] == 1.0
assert viability_payload["passed"] is True
assert "source/prd-scope.md -->|supports| generated/lifecycle-baseline.md" in (
graph.stdout
)
assert json.loads(exported.stdout)["config"]["slug"] == "bootstrap-pilot"
assert workflow_payload["status"] == "completed"
assert workflow_payload["outputs"][0]["artifact_id"] == (
"generated/prd-scope-readiness.md"
)
metrics = read_metrics_file(root / "output" / "metrics" / "metrics.yaml")
history = read_history(root / "output" / "metrics" / "history.yaml")
assert metrics["coverage_ratio"] == 1.0
assert history[-1].artifact_count == 4
def test_legacy_slice_replacement_gate_exercises_semantics_and_engine() -> None:
infospace = load_infospace(LEGACY_SLICE)
validation = validate_infospace_artifacts(LEGACY_SLICE)
entities = list_entities(LEGACY_SLICE)
relations = list_relations(LEGACY_SLICE)
metrics = read_metrics_file(LEGACY_SLICE / "output" / "metrics" / "metrics.yaml")
history = read_history(LEGACY_SLICE / "output" / "metrics" / "history.yaml")
plan = plan_asset_sync(LEGACY_SLICE)
assert infospace.config.slug == "wealth-vsm-legacy-slice"
assert all(result.valid for result in validation)
assert [entity.slug for entity in entities] == [
"division-of-labour",
"market-extent",
]
assert relations[0].subject_entity_id == "entity/division-of-labour.md"
assert metrics["per_artifact_mean"] == 4.6
assert history[0].snapshot_id == "legacy-slice"
assert [action.action for action in plan.actions] == [
"create",
"create",
"create",
"create",
]
def test_replacement_decision_record_names_residual_owners() -> None:
decision = REPO_ROOT / "docs" / "replacement-readiness-decision.md"
data = yaml.safe_load(
decision.read_text(encoding="utf-8").split("---", maxsplit=2)[1]
)
text = decision.read_text(encoding="utf-8")
assert data["decision"] == "replacement-ready-for-new-in-scope-infospace-work"
assert "markitect-tool" in text
assert "kontextual-engine" in text
assert "infospace-bench" in text
assert "Not a name-for-name CLI clone" in text