import json import os import subprocess import sys from pathlib import Path from infospace_bench import add_artifact, create_infospace from infospace_bench.markdown_adapter import ( extract_section_text, parse_markdown_artifact, validate_infospace_artifacts, ) CONTRACT = """# Source Artifact Contract ```yaml contract id: source-artifact-v1 document: type: source-artifact sections: - id: summary title: Summary presence: required level: 2 - id: evidence title: Evidence presence: required level: 2 ``` """ VALID_SOURCE = """--- document_type: source-artifact status: draft --- # Source A ## Summary This source describes the first artifact. ## Evidence The required evidence section is present. """ INVALID_SOURCE = """--- document_type: source-artifact --- # Source B ## Summary This source is missing evidence. """ def cli_env() -> dict[str, str]: env = os.environ.copy() env["PYTHONPATH"] = "src:/home/worsch/markitect-tool/src" return env def test_parse_markdown_artifact_uses_markitect_tool_sections(tmp_path: Path) -> None: source = tmp_path / "source.md" source.write_text(VALID_SOURCE, encoding="utf-8") parsed = parse_markdown_artifact(source) assert parsed.frontmatter["document_type"] == "source-artifact" assert [heading.text for heading in parsed.headings] == [ "Source A", "Summary", "Evidence", ] assert extract_section_text(parsed, "Summary") == ( "This source describes the first artifact." ) def test_validate_infospace_artifacts_uses_configured_contract(tmp_path: Path) -> None: infospace = create_infospace(tmp_path, "pilot", name="Pilot") contract = infospace.root / "contracts" / "source.contract.md" contract.parent.mkdir() contract.write_text(CONTRACT, encoding="utf-8") config = infospace.root / "infospace.yaml" config.write_text( config.read_text(encoding="utf-8").replace( "schemas: {}\n", "schemas:\n source: contracts/source.contract.md\n" ), encoding="utf-8", ) valid = tmp_path / "valid.md" valid.write_text(VALID_SOURCE, encoding="utf-8") invalid = tmp_path / "invalid.md" invalid.write_text(INVALID_SOURCE, encoding="utf-8") add_artifact(infospace.root, valid, kind="source", title="Valid") add_artifact(infospace.root, invalid, kind="source", title="Invalid") results = validate_infospace_artifacts(infospace.root) by_id = {result.artifact_id: result for result in results} assert by_id["source/valid.md"].valid is True assert by_id["source/invalid.md"].valid is False assert by_id["source/invalid.md"].diagnostics[0].code == "contract.section.missing" def test_cli_validate_outputs_json_results(tmp_path: Path) -> None: infospace = create_infospace(tmp_path, "pilot", name="Pilot") contract = infospace.root / "contracts" / "source.contract.md" contract.parent.mkdir() contract.write_text(CONTRACT, encoding="utf-8") config = infospace.root / "infospace.yaml" config.write_text( config.read_text(encoding="utf-8").replace( "schemas: {}\n", "schemas:\n source: contracts/source.contract.md\n" ), encoding="utf-8", ) source = tmp_path / "invalid.md" source.write_text(INVALID_SOURCE, encoding="utf-8") add_artifact(infospace.root, source, kind="source", title="Invalid") result = subprocess.run( [ sys.executable, "-m", "infospace_bench", "validate", str(infospace.root), ], check=False, env=cli_env(), text=True, capture_output=True, ) assert result.returncode == 1 payload = json.loads(result.stdout) assert payload["valid"] is False assert payload["results"][0]["diagnostics"][0]["code"] == ( "contract.section.missing" )