generated from coulomb/repo-seed
Round out IB-WP-0014 with the remaining archive operations and docs. - restore_archive() and `infospace-bench restore <pkg> --target <dir>` round-trip a finalized package's bytes back to disk. Refuses to overwrite a non-empty target unless --force. --from <infospace-root> resolves the store location. - archive-list CLI with --with-retention flag; annotate_retention() opens the per-infospace registry and joins each record with its current retention state (effective class, expires, holds, eligibility). - docs/archive-integration.md covers when to archive, the include set, retention classes, storage layout, credentials policy, and the explicit non-goal that S3/git backends live in artifact-store. - SCOPE.md cross-links the new doc. - Workplan flipped to status: done. Full pytest suite: 72 passed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
110 lines
3.3 KiB
Python
110 lines
3.3 KiB
Python
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def run_cli(*args: str) -> subprocess.CompletedProcess[str]:
|
|
env = os.environ.copy()
|
|
env["PYTHONPATH"] = "src:/home/worsch/markitect-tool/src"
|
|
return subprocess.run(
|
|
[sys.executable, "-m", "infospace_bench", *args],
|
|
check=False,
|
|
env=env,
|
|
text=True,
|
|
capture_output=True,
|
|
)
|
|
|
|
|
|
def test_cli_create_inspect_and_add_artifact(tmp_path: Path) -> None:
|
|
create = run_cli(
|
|
"create",
|
|
str(tmp_path),
|
|
"pilot",
|
|
"--name",
|
|
"Pilot Infospace",
|
|
"--topic-domain",
|
|
"Test Domain",
|
|
)
|
|
assert create.returncode == 0, create.stderr
|
|
assert json.loads(create.stdout)["slug"] == "pilot"
|
|
|
|
source = tmp_path / "source.md"
|
|
source.write_text("# Source\n", encoding="utf-8")
|
|
add = run_cli(
|
|
"add-artifact",
|
|
str(tmp_path / "infospaces" / "pilot"),
|
|
str(source),
|
|
"--kind",
|
|
"source",
|
|
"--title",
|
|
"Source",
|
|
)
|
|
assert add.returncode == 0, add.stderr
|
|
assert json.loads(add.stdout)["artifact"]["id"] == "source/source.md"
|
|
|
|
inspect = run_cli("inspect", str(tmp_path / "infospaces" / "pilot"))
|
|
assert inspect.returncode == 0, inspect.stderr
|
|
payload = json.loads(inspect.stdout)
|
|
assert payload["config"]["topic"]["domain"] == "Test Domain"
|
|
assert payload["artifacts"][0]["title"] == "Source"
|
|
|
|
|
|
def test_cli_returns_structured_error(tmp_path: Path) -> None:
|
|
result = run_cli("inspect", str(tmp_path / "missing"))
|
|
|
|
assert result.returncode == 2
|
|
payload = json.loads(result.stderr)
|
|
assert payload["error"]["code"] == "missing_infospace"
|
|
|
|
|
|
def test_cli_archive_list_and_restore(tmp_path: Path) -> None:
|
|
create = run_cli(
|
|
"create",
|
|
str(tmp_path),
|
|
"cli-archive",
|
|
"--name",
|
|
"CLI Archive",
|
|
)
|
|
assert create.returncode == 0, create.stderr
|
|
root = tmp_path / "infospaces" / "cli-archive"
|
|
|
|
source = tmp_path / "src.md"
|
|
source.write_text("# src\n", encoding="utf-8")
|
|
add = run_cli(
|
|
"add-artifact", str(root), str(source), "--kind", "source", "--title", "Src",
|
|
)
|
|
assert add.returncode == 0, add.stderr
|
|
|
|
archive = run_cli("archive", str(root), "--note", "via cli")
|
|
assert archive.returncode == 0, archive.stderr
|
|
record = json.loads(archive.stdout)
|
|
assert record["note"] == "via cli"
|
|
assert record["manifest_digest"].startswith("blake3:")
|
|
|
|
listing = run_cli("archive-list", str(root))
|
|
assert listing.returncode == 0, listing.stderr
|
|
assert json.loads(listing.stdout)["archives"][0]["package_id"] == record["package_id"]
|
|
|
|
listing_with_retention = run_cli(
|
|
"archive-list", str(root), "--with-retention",
|
|
)
|
|
assert listing_with_retention.returncode == 0, listing_with_retention.stderr
|
|
annotated = json.loads(listing_with_retention.stdout)["archives"]
|
|
assert annotated[0]["retention"]["effective_class"] == "release-evidence"
|
|
|
|
target = tmp_path / "restored"
|
|
restore = run_cli(
|
|
"restore",
|
|
record["package_id"],
|
|
"--target",
|
|
str(target),
|
|
"--from",
|
|
str(root),
|
|
)
|
|
assert restore.returncode == 0, restore.stderr
|
|
result = json.loads(restore.stdout)
|
|
assert result["file_count"] == record["file_count"]
|
|
assert (target / "infospace.yaml").is_file()
|