generated from coulomb/repo-seed
engine and lifecycle
This commit is contained in:
167
tests/test_engine_boundary.py
Normal file
167
tests/test_engine_boundary.py
Normal file
@@ -0,0 +1,167 @@
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from infospace_bench import add_artifact, create_infospace, load_infospace, register_artifact
|
||||
from infospace_bench.engine import (
|
||||
LocalAssetRepository,
|
||||
engine_capability_contract,
|
||||
plan_asset_sync,
|
||||
sync_assets,
|
||||
)
|
||||
|
||||
|
||||
def cli_env() -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
env["PYTHONPATH"] = "src:/home/worsch/markitect-tool/src"
|
||||
return env
|
||||
|
||||
|
||||
def make_engine_infospace(tmp_path: Path) -> Path:
|
||||
infospace = create_infospace(tmp_path, "pilot", name="Pilot")
|
||||
source = tmp_path / "chapter.md"
|
||||
source.write_text("# Chapter\n\nSource text.\n", encoding="utf-8")
|
||||
add_artifact(infospace.root, source, kind="source", title="Chapter")
|
||||
|
||||
generated = infospace.root / "artifacts" / "generated" / "chapter-summary.md"
|
||||
generated.parent.mkdir(parents=True, exist_ok=True)
|
||||
generated.write_text("# Chapter Summary\n\nGenerated text.\n", encoding="utf-8")
|
||||
register_artifact(
|
||||
infospace.root,
|
||||
artifact_id="generated/chapter-summary.md",
|
||||
path="artifacts/generated/chapter-summary.md",
|
||||
kind="generated",
|
||||
title="Chapter Summary",
|
||||
provenance={
|
||||
"workflow_id": "source-summary",
|
||||
"stage_id": "render-summary",
|
||||
"input_artifact_id": "source/chapter.md",
|
||||
},
|
||||
relationships=[
|
||||
{"type": "generated_from", "target": "source/chapter.md"},
|
||||
],
|
||||
)
|
||||
return infospace.root
|
||||
|
||||
|
||||
def test_engine_capability_contract_keeps_application_boundary_explicit() -> None:
|
||||
contract = engine_capability_contract()
|
||||
|
||||
assert "asset_identity" in contract.engine_backed
|
||||
assert "artifact_manifest" in contract.file_backed
|
||||
assert "markdown_parsing" not in contract.engine_backed
|
||||
assert contract.assumptions["source"] == "kontextual-engine/INTENT.md"
|
||||
assert contract.review_required == [
|
||||
"apply_sync",
|
||||
"engine_client_configuration",
|
||||
"permission_changes",
|
||||
]
|
||||
|
||||
|
||||
def test_plan_asset_sync_is_dry_run_and_maps_artifacts_to_assets(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
root = make_engine_infospace(tmp_path)
|
||||
repository_path = root / "output" / "engine" / "assets.yaml"
|
||||
|
||||
plan = plan_asset_sync(root)
|
||||
|
||||
assert plan.dry_run is True
|
||||
assert repository_path.exists() is False
|
||||
assert [action.action for action in plan.actions] == ["create", "create"]
|
||||
assert plan.actions[0].artifact_id == "source/chapter.md"
|
||||
assert plan.actions[0].asset_id == "infospace:pilot:artifact:source/chapter.md"
|
||||
assert len(plan.actions[0].digest) == 64
|
||||
assert plan.actions[1].workflow_id == "source-summary"
|
||||
|
||||
|
||||
def test_sync_assets_apply_persists_to_local_repository_and_detects_updates(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
root = make_engine_infospace(tmp_path)
|
||||
|
||||
applied = sync_assets(root, dry_run=False)
|
||||
repository = LocalAssetRepository(root / "output" / "engine" / "assets.yaml")
|
||||
assets = repository.list_assets()
|
||||
unchanged = plan_asset_sync(root)
|
||||
|
||||
source_path = root / "artifacts" / "sources" / "chapter.md"
|
||||
source_path.write_text("# Chapter\n\nChanged text.\n", encoding="utf-8")
|
||||
updated = plan_asset_sync(root)
|
||||
|
||||
assert applied.status == "completed"
|
||||
assert len(assets) == 2
|
||||
assert repository.get_asset("infospace:pilot:artifact:source/chapter.md") is not None
|
||||
assert [action.action for action in unchanged.actions] == [
|
||||
"unchanged",
|
||||
"unchanged",
|
||||
]
|
||||
assert updated.actions[0].action == "update"
|
||||
assert updated.actions[0].previous_digest != updated.actions[0].digest
|
||||
|
||||
|
||||
def test_cli_engine_inspect_plan_sync_and_apply(tmp_path: Path) -> None:
|
||||
root = make_engine_infospace(tmp_path)
|
||||
|
||||
inspected = subprocess.run(
|
||||
[sys.executable, "-m", "infospace_bench", "engine", "inspect", str(root)],
|
||||
check=False,
|
||||
env=cli_env(),
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
planned = subprocess.run(
|
||||
[sys.executable, "-m", "infospace_bench", "engine", "plan-sync", str(root)],
|
||||
check=False,
|
||||
env=cli_env(),
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
dry_run_sync = subprocess.run(
|
||||
[sys.executable, "-m", "infospace_bench", "engine", "sync", str(root)],
|
||||
check=False,
|
||||
env=cli_env(),
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
applied = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"infospace_bench",
|
||||
"engine",
|
||||
"sync",
|
||||
str(root),
|
||||
"--apply",
|
||||
],
|
||||
check=False,
|
||||
env=cli_env(),
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
assert inspected.returncode == 0, inspected.stderr
|
||||
assert planned.returncode == 0, planned.stderr
|
||||
assert dry_run_sync.returncode == 0, dry_run_sync.stderr
|
||||
assert applied.returncode == 0, applied.stderr
|
||||
assert json.loads(inspected.stdout)["contract"]["integration_posture"] == "optional"
|
||||
assert json.loads(planned.stdout)["dry_run"] is True
|
||||
assert json.loads(dry_run_sync.stdout)["dry_run"] is True
|
||||
assert json.loads(applied.stdout)["status"] == "completed"
|
||||
assert (root / "output" / "engine" / "assets.yaml").is_file()
|
||||
|
||||
|
||||
def test_file_backed_infospace_remains_authoritative_after_engine_sync(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
root = make_engine_infospace(tmp_path)
|
||||
|
||||
sync_assets(root, dry_run=False)
|
||||
loaded = load_infospace(root)
|
||||
|
||||
assert [artifact.id for artifact in loaded.artifacts] == [
|
||||
"source/chapter.md",
|
||||
"generated/chapter-summary.md",
|
||||
]
|
||||
Reference in New Issue
Block a user