generated from coulomb/repo-seed
168 lines
5.4 KiB
Python
168 lines
5.4 KiB
Python
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",
|
|
]
|