CLI and API polish

This commit is contained in:
2026-05-04 21:56:19 +02:00
parent 6744cc66e9
commit 539bb9b754
15 changed files with 2401 additions and 2 deletions

View File

@@ -12,6 +12,8 @@ def test_builtin_extension_registry_lists_query_processors_and_backend():
assert "processor.identity" in ids
assert "processor.uppercase" in ids
assert "processor.include" in ids
assert "extension.catalog" in ids
assert "docs.generated-reference" in ids
assert "backend.local-sqlite" in ids
assert "workflow.markdown-dataflow" in ids
assert "runtime.context" in ids
@@ -22,6 +24,19 @@ def test_builtin_extension_registry_lists_query_processors_and_backend():
assert "memory.context-package" in ids
def test_builtin_meta_descriptors_expose_extension_and_docs_accesspoints():
registry = builtin_extension_registry()
extension = registry.get("extension.catalog")
docs = registry.get("docs.generated-reference")
assert extension.kind == "extension-registry"
assert "mkt extension commands" in extension.cli["commands"]
assert docs.kind == "documentation"
assert docs.safety["writes_files"] is True
assert docs.cli["commands"] == ["mkt docs cli", "mkt docs api"]
def test_builtin_processor_descriptors_capture_safety_and_provenance():
registry = builtin_extension_registry()

View File

@@ -0,0 +1,65 @@
from click.testing import CliRunner
import markitect_tool as api
from markitect_tool.cli import main
def test_mkt_completion_generates_bash_script():
result = CliRunner().invoke(main, ["completion", "bash"])
assert result.exit_code == 0, result.output
assert "_mkt_completion" in result.output
assert "_MKT_COMPLETE=bash_complete" in result.output
def test_mkt_completion_instructions_are_unix_shell_friendly():
result = CliRunner().invoke(main, ["completion", "zsh", "--instructions"])
assert result.exit_code == 0, result.output
assert "_MKT_COMPLETE=zsh_source mkt" in result.output
assert "~/.zshrc" in result.output
def test_mkt_extension_commands_exposes_builtin_cli_affordances():
result = CliRunner().invoke(main, ["extension", "commands", "--format", "json"])
assert result.exit_code == 0, result.output
assert '"command": "mkt query"' in result.output
assert '"command": "mkt extension commands"' in result.output
assert '"command": "mkt docs api"' in result.output
def test_mkt_extension_inspect_explains_descriptor():
result = CliRunner().invoke(main, ["extension", "inspect", "memory.context-package"])
assert result.exit_code == 0, result.output
assert "memory.context-package" in result.output
assert "mkt context pack" in result.output
def test_mkt_docs_cli_generates_command_reference():
result = CliRunner().invoke(main, ["docs", "cli"])
assert result.exit_code == 0, result.output
assert "# Markitect CLI Reference" in result.output
assert "## `mkt extension commands`" in result.output
assert "## `mkt docs api`" in result.output
def test_mkt_docs_api_generates_public_api_reference():
result = CliRunner().invoke(main, ["docs", "api"])
assert result.exit_code == 0, result.output
assert "# Markitect API Reference" in result.output
assert "query_document_jsonpath" in result.output
assert "ExtensionDescriptor" in result.output
assert "LocalSnapshotStore" in result.output
def test_top_level_api_exports_newer_architecture_surfaces():
assert api.query_document_jsonpath
assert api.extract_document_with_engine
assert api.LocalSnapshotStore
assert api.ExtensionDescriptor
assert api.builtin_extension_registry
assert api.validate_schema

View File

@@ -0,0 +1,205 @@
import json
from pathlib import Path
import pytest
from click.testing import CliRunner
from markitect_tool.cli import main
@pytest.mark.parametrize(
("label", "count"),
[
("small", 1),
("typical", 12),
("large", 80),
],
)
def test_corpus_usecase_pipeline_small_typical_large(tmp_path: Path, label: str, count: int):
docs = tmp_path / "docs"
docs.mkdir()
for index in range(count):
(docs / f"adr-{index:03d}.md").write_text(
f"""---
title: Decision {index}
labels: [public]
trust_zone: public
---
# Decision {index}
## Context
The team needs predictable latency for document operations in the {label} corpus.
## Decision
Use deterministic Markdown contracts, selectors, and cache refresh planning.
## Consequences
Search and context packaging should stay fast as the corpus grows.
""",
encoding="utf-8",
)
runner = CliRunner()
parse = runner.invoke(main, ["parse", str(docs / "adr-000.md"), "--format", "json"])
assert parse.exit_code == 0, parse.output
assert json.loads(parse.output)["headings"][0]["text"] == "Decision 0"
query = runner.invoke(
main,
["query", str(docs / "adr-000.md"), "sections[heading=Decision]", "--format", "json"],
)
assert query.exit_code == 0, query.output
assert json.loads(query.output)["count"] == 1
index = runner.invoke(main, ["cache", "index", str(docs), "--root", str(tmp_path), "--format", "json"])
assert index.exit_code == 0, index.output
index_data = json.loads(index.output)
assert len(index_data["indexed"]) == count
search = runner.invoke(
main,
["search", "latency", "--root", str(tmp_path), "--limit", "5", "--format", "json"],
)
assert search.exit_code == 0, search.output
assert json.loads(search.output)["count"] >= 1
context = runner.invoke(
main,
[
"context",
"pack",
"latency",
"--search",
"--root",
str(tmp_path),
"--max-items",
"3",
"--no-save",
"--format",
"json",
],
)
assert context.exit_code == 0, context.output
assert 1 <= len(json.loads(context.output)["items"]) <= 3
def test_document_pipeline_usecases_from_examples(tmp_path: Path):
runner = CliRunner()
contract = runner.invoke(
main,
[
"contract",
"check",
"examples/documents/adr-valid.md",
"--contract",
"examples/contracts/adr.contract.md",
],
)
assert contract.exit_code == 0, contract.output
assert "valid" in contract.output
template = runner.invoke(
main,
[
"template",
"render",
"examples/templates/adr-summary.template.md",
"--data",
"examples/templates/adr-summary.data.yaml",
],
)
assert template.exit_code == 0, template.output
assert "Use Deterministic Templates" in template.output
function = runner.invoke(main, ["function", "render", "examples/functions/basic-functions.md"])
assert function.exit_code == 0, function.output
assert "DRAFT" in function.output
assert "Generated Section" in function.output
workflow = runner.invoke(
main,
[
"workflow",
"plan",
"examples/workflows/source-snippets.workflow.md",
"--output-dir",
str(tmp_path / "workflow-out"),
],
)
assert workflow.exit_code == 0, workflow.output
assert "valid" in workflow.output
def test_structure_reuse_policy_and_literate_usecases(tmp_path: Path):
runner = CliRunner()
reference = runner.invoke(
main,
[
"ref",
"resolve",
"examples/references/context.md",
"std:clauses.md#payment-terms",
"--root",
"examples/references",
"--format",
"json",
],
)
assert reference.exit_code == 0, reference.output
assert json.loads(reference.output)["count"] == 1
process = runner.invoke(
main,
["process", "examples/references/context.md", "--root", "examples/references"],
)
assert process.exit_code == 0, process.output
assert "payment-example" in process.output
policy = runner.invoke(
main,
[
"policy",
"check",
"public-agent",
"read",
"examples/policy/private/internal-note.md",
"--policy",
"examples/policy/local-label-policy.yaml",
"--path",
"private/internal-note.md",
],
)
assert policy.exit_code == 1
assert "denied" in policy.output
tangle = runner.invoke(
main,
["tangle", "examples/literate/app.md", "--output-dir", str(tmp_path / "tangle")],
)
assert tangle.exit_code == 0, tangle.output
assert (tmp_path / "tangle" / "src" / "app.py").exists()
exploded = tmp_path / "exploded"
explode = runner.invoke(
main,
[
"explode",
"examples/documents/adr-valid.md",
"--output-dir",
str(exploded),
"--format",
"json",
],
)
assert explode.exit_code == 0, explode.output
implode = runner.invoke(main, ["implode", str(exploded), "--format", "markdown"])
assert implode.exit_code == 0, implode.output
assert "# Use Markdown Contracts" in implode.output