generated from coulomb/repo-seed
187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
import importlib.util
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
pytestmark = [pytest.mark.integration, pytest.mark.markitect_tool]
|
|
if importlib.util.find_spec("markitect_tool") is None:
|
|
pytestmark.append(
|
|
pytest.mark.skip(
|
|
reason="Install kontextual-engine[markdown] to run markitect-tool contract tests."
|
|
)
|
|
)
|
|
mkt = None
|
|
else:
|
|
import markitect_tool as mkt
|
|
|
|
EXAMPLE_ROOT = Path(__file__).resolve().parents[1] / "examples" / "markitect-tool-contract"
|
|
ADR = EXAMPLE_ROOT / "corpus" / "adr-0001-context-packages.md"
|
|
INVALID_ADR = EXAMPLE_ROOT / "corpus" / "adr-invalid-missing-decision.md"
|
|
POLICY = EXAMPLE_ROOT / "corpus" / "engineering-policy.md"
|
|
INTERNAL = EXAMPLE_ROOT / "corpus" / "internal-risk-note.md"
|
|
BUNDLE = EXAMPLE_ROOT / "composition" / "context-bundle.md"
|
|
MANIFEST = EXAMPLE_ROOT / "manifests" / "agent-context.yaml"
|
|
CONTRACT = EXAMPLE_ROOT / "contracts" / "decision-record.contract.md"
|
|
SCHEMA = EXAMPLE_ROOT / "schemas" / "adr-proxy.schema.md"
|
|
|
|
|
|
def test_markitect_parser_returns_structured_markdown_document() -> None:
|
|
document = mkt.parse_markdown_file(ADR)
|
|
serialized = document.to_dict()
|
|
|
|
assert serialized["frontmatter"]["status"] == "accepted"
|
|
assert serialized["frontmatter"]["owner"] == "Platform Knowledge"
|
|
assert serialized["source_path"] == str(ADR)
|
|
assert [heading["text"] for heading in serialized["headings"]] == [
|
|
"Use Markitect Context Packages",
|
|
"Context",
|
|
"Decision",
|
|
"Consequences",
|
|
]
|
|
assert any(section["heading"]["text"] == "Decision" for section in serialized["sections"])
|
|
|
|
|
|
def test_markitect_selectors_extract_source_grounded_markdown_units() -> None:
|
|
document = mkt.parse_markdown_file(ADR)
|
|
|
|
status = mkt.extract_document(document, "frontmatter.status")
|
|
matches = mkt.query_document(document, "sections[heading=Decision]")
|
|
extracted = mkt.extract_document(document, "sections[heading=Decision]")
|
|
bullets = mkt.query_document(document, "blocks[type=bullet_list]")
|
|
|
|
assert status == ["accepted"]
|
|
assert len(matches) == 1
|
|
assert matches[0].kind == "section"
|
|
assert matches[0].line is not None
|
|
assert "context-package layer" in matches[0].text
|
|
assert extracted == [
|
|
"## Decision\n\n"
|
|
"We will use markitect-tool as the Markdown syntax, selector, deterministic\n"
|
|
"operation, snapshot, and context-package layer for Markdown-backed assets."
|
|
]
|
|
assert len(bullets) == 1
|
|
assert "Engine assets stay cross-format" in bullets[0].text
|
|
|
|
|
|
def test_markitect_ops_compose_include_transform_and_return_provenance() -> None:
|
|
included = mkt.resolve_includes(
|
|
BUNDLE.read_text(encoding="utf-8"),
|
|
base_dir=EXAMPLE_ROOT,
|
|
current_path=BUNDLE,
|
|
)
|
|
composed = mkt.compose_files(
|
|
[ADR, POLICY],
|
|
title="Combined Markdown Context",
|
|
heading_delta=1,
|
|
)
|
|
transformed = mkt.transform_markdown(
|
|
included.markdown,
|
|
set_frontmatter={"status": "draft", "producer": {"name": "kontextual-engine"}},
|
|
heading_delta=1,
|
|
source_path=str(BUNDLE),
|
|
)
|
|
|
|
assert included.included_paths == [str(ADR.resolve()), str(POLICY.resolve())]
|
|
assert [event.operation for event in included.provenance] == ["include", "include"]
|
|
assert included.provenance[1].metadata["selector"] == "sections[heading=Controls]"
|
|
assert "### Controls" in included.markdown
|
|
assert "{{include:../corpus/internal-risk-note.md}}" in included.markdown
|
|
assert "This internal note should not appear" not in included.markdown
|
|
assert composed.markdown.startswith("# Combined Markdown Context")
|
|
assert "## Use Markitect Context Packages" in composed.markdown
|
|
assert "document_type: adr" not in composed.markdown
|
|
assert "producer:" in transformed.markdown
|
|
assert [event.operation for event in transformed.provenance] == [
|
|
"set_frontmatter",
|
|
"shift_headings",
|
|
]
|
|
|
|
|
|
def test_markitect_snapshot_identity_is_content_addressed_adapter_metadata() -> None:
|
|
first = mkt.snapshot_identity_for_file(ADR, parse_options={"profile": "default"})
|
|
second = mkt.snapshot_identity_for_file(ADR, parse_options={"profile": "default"})
|
|
changed = mkt.snapshot_identity_for_file(ADR, parse_options={"profile": "strict"})
|
|
|
|
assert first.snapshot_id == second.snapshot_id
|
|
assert first.content_hash == second.content_hash
|
|
assert first.parser == "markdown-it-py/commonmark"
|
|
assert first.snapshot_id != changed.snapshot_id
|
|
assert first.to_dict()["source_path"] == str(ADR)
|
|
|
|
|
|
def test_markitect_context_packages_from_manifest_preserve_sources() -> None:
|
|
package = mkt.create_context_package_from_manifest(MANIFEST, root=EXAMPLE_ROOT)
|
|
activation = mkt.activate_context_package(package, target="thread:contract-test")
|
|
|
|
assert package.title == "Kontextual Engine Markdown Adapter Context"
|
|
assert package.namespace.project == "kontextual-engine"
|
|
assert [item.source.path for item in package.items] == [
|
|
"corpus/adr-0001-context-packages.md",
|
|
"corpus/engineering-policy.md",
|
|
]
|
|
assert "Markdown-backed assets" in activation.content
|
|
assert "source paths" in activation.content
|
|
assert activation.metadata["package_title"] == package.title
|
|
|
|
|
|
def test_markitect_context_packages_filter_by_local_policy() -> None:
|
|
package = mkt.create_context_package_from_sources(
|
|
"document",
|
|
[ADR, INTERNAL],
|
|
root=EXAMPLE_ROOT,
|
|
namespace=mkt.MemoryNamespace(project="kontextual-engine", task="boundary"),
|
|
budget=mkt.ContextBudget(max_items=5),
|
|
)
|
|
gateway = mkt.LocalLabelPolicyGateway(
|
|
{
|
|
"id": "kontextual-engine-boundary",
|
|
"subjects": {
|
|
"reader": {
|
|
"allowed_labels": ["public", "engineering"],
|
|
"allowed_actions": ["read", "activate"],
|
|
}
|
|
},
|
|
"default_subject": "reader",
|
|
}
|
|
)
|
|
|
|
activation = mkt.activate_context_package(
|
|
package,
|
|
policy_gateway=gateway,
|
|
subject="reader",
|
|
)
|
|
|
|
assert package.namespace.project == "kontextual-engine"
|
|
assert len(activation.items) == 1
|
|
assert "Use Markitect Context Packages" in activation.content
|
|
assert "Internal Retrieval Risk" not in activation.content
|
|
assert activation.policy["summary"]["denied"] == 1
|
|
|
|
|
|
def test_markitect_document_contracts_accept_valid_and_report_invalid_documents() -> None:
|
|
contract = mkt.load_contract_file(CONTRACT)
|
|
valid = mkt.check_markdown_file(ADR, CONTRACT)
|
|
invalid = mkt.check_markdown_file(INVALID_ADR, CONTRACT)
|
|
invalid_codes = {diagnostic.code for diagnostic in invalid.diagnostics}
|
|
|
|
assert contract.id == "kontextual-decision-record-v1"
|
|
assert valid.valid is True
|
|
assert valid.diagnostics == []
|
|
assert invalid.valid is False
|
|
assert "contract.section.missing" in invalid_codes
|
|
assert "contract.section.forbidden" in invalid_codes
|
|
|
|
|
|
def test_markitect_schema_validation_accepts_markdown_proxy_documents() -> None:
|
|
loaded_schema = mkt.load_schema_file(SCHEMA)
|
|
schema_check = mkt.validate_schema(loaded_schema.schema)
|
|
valid = mkt.validate_markdown_file(ADR, SCHEMA)
|
|
invalid = mkt.validate_markdown_file(INVALID_ADR, SCHEMA)
|
|
|
|
assert loaded_schema.metadata["schema-id"] == "kontextual-engine.markdown-proxy.adr.v1"
|
|
assert schema_check.valid is True
|
|
assert valid.valid is True
|
|
assert invalid.valid is False
|
|
assert any("Decision" in violation.message for violation in invalid.violations)
|