Implement canon conformance and maintenance optimizations
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06e82-3e08-7042-a79d-438ac6eed8db
This commit is contained in:
parent
a2e7f22d8d
commit
b081d39da1
64 changed files with 4491 additions and 373 deletions
|
|
@ -62,4 +62,4 @@ def test_api_route_validates_small_saas_profile() -> None:
|
|||
|
||||
assert status == HTTPStatus.OK
|
||||
assert payload["ok"] is True
|
||||
assert payload["details"]["artifact_count"] == 14
|
||||
assert payload["details"]["artifact_count"] == 15
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ def test_cli_inspect_emits_json(capsys) -> None:
|
|||
assert exit_code == 0
|
||||
payload = json.loads(capsys.readouterr().out)
|
||||
assert payload["ok"] is True
|
||||
assert payload["infospace"]["artifact_count"] == 71
|
||||
assert payload["infospace"]["artifact_count"] == 76
|
||||
|
||||
|
||||
def test_cli_missing_profile_uses_structured_error(capsys) -> None:
|
||||
|
|
|
|||
59
tests/test_emission_cadence.py
Normal file
59
tests/test_emission_cadence.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from jsonschema import Draft202012Validator
|
||||
import yaml
|
||||
|
||||
from info_tech_canon.service import DEFAULT_INFOSPACE_ROOT
|
||||
|
||||
|
||||
SCHEMA_PATH = DEFAULT_INFOSPACE_ROOT / "schemas" / "emission-cadence.schema.yaml"
|
||||
EXAMPLE_PATH = (
|
||||
DEFAULT_INFOSPACE_ROOT
|
||||
/ "standards"
|
||||
/ "emission-cadence"
|
||||
/ "examples"
|
||||
/ "qonto-assistant.yaml"
|
||||
)
|
||||
|
||||
|
||||
def _load_yaml(path):
|
||||
return yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _validator() -> Draft202012Validator:
|
||||
schema = _load_yaml(SCHEMA_PATH)
|
||||
Draft202012Validator.check_schema(schema)
|
||||
return Draft202012Validator(schema)
|
||||
|
||||
|
||||
def test_worked_example_validates() -> None:
|
||||
assert list(_validator().iter_errors(_load_yaml(EXAMPLE_PATH))) == []
|
||||
|
||||
|
||||
def test_expected_rate_requires_one_window_representation() -> None:
|
||||
payload = deepcopy(_load_yaml(EXAMPLE_PATH))
|
||||
rate = payload["sources"][0]
|
||||
rate.pop("window")
|
||||
|
||||
assert list(_validator().iter_errors(payload))
|
||||
|
||||
rate["window"] = "PT24H"
|
||||
rate["window_seconds"] = 86400
|
||||
assert list(_validator().iter_errors(payload))
|
||||
|
||||
|
||||
def test_heartbeat_form_accepts_either_mechanism_but_not_neither() -> None:
|
||||
payload = deepcopy(_load_yaml(EXAMPLE_PATH))
|
||||
intermittent = payload["sources"][1]
|
||||
intermittent.pop("heartbeat")
|
||||
assert list(_validator().iter_errors(payload)) == []
|
||||
|
||||
intermittent.pop("reconciliation")
|
||||
assert list(_validator().iter_errors(payload))
|
||||
|
||||
|
||||
def test_profile_fields_must_be_namespaced_extensions() -> None:
|
||||
payload = deepcopy(_load_yaml(EXAMPLE_PATH))
|
||||
payload["sources"][1]["evidence_class"] = "load-bearing"
|
||||
|
||||
assert list(_validator().iter_errors(payload))
|
||||
116
tests/test_maintenance.py
Normal file
116
tests/test_maintenance.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
from copy import deepcopy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import tarfile
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from info_tech_canon.cli import main
|
||||
from info_tech_canon.maintenance import check_generated, export_emission_bundle, source_evidence
|
||||
from info_tech_canon.service import DEFAULT_INFOSPACE_ROOT, load_context, validate_canon
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def corpus(tmp_path):
|
||||
root = tmp_path / "infospace"
|
||||
shutil.copytree(DEFAULT_INFOSPACE_ROOT, root)
|
||||
return root
|
||||
|
||||
|
||||
def test_emission_cli_checks_versions_duplicates_and_bad_types(tmp_path, capsys):
|
||||
source = DEFAULT_INFOSPACE_ROOT / "standards/emission-cadence/examples/qonto-assistant.yaml"
|
||||
valid = yaml.safe_load(source.read_text())
|
||||
path = tmp_path / "declaration.yaml"
|
||||
path.write_text(yaml.safe_dump(valid))
|
||||
assert main(["emission-review", str(path)]) == 0
|
||||
assert json.loads(capsys.readouterr().out)["operational_truth_assessed"] is False
|
||||
for change in ("version", "duplicate", "bad_type"):
|
||||
data = deepcopy(valid)
|
||||
if change == "version":
|
||||
data["schema_version"] = "99.0"
|
||||
elif change == "duplicate":
|
||||
data["sources"].append(deepcopy(data["sources"][0]))
|
||||
else:
|
||||
data["sources"][0]["source_id"] = ["unhashable"]
|
||||
path.write_text(yaml.safe_dump(data))
|
||||
assert main(["emission-review", str(path)]) == 1
|
||||
payload = json.loads(capsys.readouterr().out)
|
||||
assert payload["errors"]
|
||||
if change == "duplicate":
|
||||
assert payload["errors"][0]["code"] == "duplicate_emission_cadence_source_id"
|
||||
|
||||
|
||||
def test_freshness_detects_missing_and_stale_without_repair(corpus):
|
||||
from info_tech_canon import generation
|
||||
context = load_context(corpus)
|
||||
for render in (generation.generate_indexes, generation.generate_tree, generation.generate_agent_briefs):
|
||||
render(context)
|
||||
assert check_generated(context)["ok"]
|
||||
stale = corpus / "views/by-concept.md"
|
||||
stale.write_text("stale\n")
|
||||
missing = corpus / "agent/retrieval-index.json"
|
||||
missing.unlink()
|
||||
result = check_generated(context)
|
||||
assert not result["ok"]
|
||||
assert "views/by-concept.md" in result["stale"]
|
||||
assert "agent/retrieval-index.json" in result["stale"]
|
||||
assert stale.read_text() == "stale\n"
|
||||
assert not missing.exists()
|
||||
|
||||
|
||||
def test_bundle_is_reproducible_and_refuses_corruption(tmp_path):
|
||||
first = export_emission_bundle(DEFAULT_INFOSPACE_ROOT, tmp_path)
|
||||
second = export_emission_bundle(DEFAULT_INFOSPACE_ROOT, tmp_path)
|
||||
assert first == second
|
||||
path = Path(first["path"])
|
||||
assert hashlib.sha256(path.read_bytes()).hexdigest() == first["sha256"]
|
||||
with tarfile.open(path) as archive:
|
||||
for name, digest in first["manifest"]["files"].items():
|
||||
assert hashlib.sha256(archive.extractfile(name).read()).hexdigest() == digest
|
||||
path.write_bytes(b"corrupted")
|
||||
with pytest.raises(ValueError, match="Refusing"):
|
||||
export_emission_bundle(DEFAULT_INFOSPACE_ROOT, tmp_path)
|
||||
|
||||
|
||||
def test_mapping_schema_and_explicit_ownership_are_enforced(corpus):
|
||||
from info_tech_canon.contracts import bound_artifact_errors
|
||||
mapping = corpus / "mappings/capability-anchors.yaml"
|
||||
data = yaml.safe_load(mapping.read_text())
|
||||
del data["target"]
|
||||
mapping.write_text(yaml.safe_dump(data))
|
||||
assert bound_artifact_errors(load_context(corpus))[0]["code"] == "schema_violation"
|
||||
pattern = corpus / "patterns/AgenticDrivesFunctional.md"
|
||||
text = pattern.read_text()
|
||||
# Reuse another artifact's title as an owned concept to create a real conflict.
|
||||
owner = next(a.title for a in load_context(corpus).infospace.artifacts if a.kind == "kernel")
|
||||
text = text.replace("owned_concepts:", f"owned_concepts:\n - {owner}")
|
||||
pattern.write_text(text)
|
||||
assert any(e["code"] == "concept_ownership_conflict" for e in validate_canon(corpus)["errors"])
|
||||
|
||||
|
||||
def test_evidence_digest_tracks_content_but_excludes_reports(corpus):
|
||||
before = source_evidence(corpus)
|
||||
(corpus / "validation/latest.json").write_text("{}")
|
||||
assert source_evidence(corpus)["corpus_sha256"] == before["corpus_sha256"]
|
||||
(corpus / "mappings/README.md").write_text("changed")
|
||||
assert source_evidence(corpus)["corpus_sha256"] != before["corpus_sha256"]
|
||||
assert before["generated_at"]
|
||||
|
||||
|
||||
def test_explicit_root_controls_capability_catalog(corpus, tmp_path):
|
||||
from info_tech_canon.service import review_capability_record, CanonServiceError
|
||||
(corpus / "models/capability/capabilities.yaml").unlink()
|
||||
record = tmp_path / "record.json"
|
||||
record.write_text('{"record_id":"example", "requires":[], "provisions":[]}')
|
||||
with pytest.raises(CanonServiceError, match="catalog"):
|
||||
review_capability_record(record, corpus)
|
||||
|
||||
|
||||
def test_missing_mapping_schema_is_a_validation_finding(corpus):
|
||||
(corpus / "schemas/mapping.schema.yaml").unlink()
|
||||
payload = validate_canon(corpus)
|
||||
assert not payload["ok"]
|
||||
assert any(e["code"] == "mapping_schema_unreadable" for e in payload["errors"])
|
||||
|
|
@ -25,11 +25,11 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
|
||||
assert payload["ok"] is True
|
||||
assert payload["infospace"]["slug"] == "canon"
|
||||
assert payload["infospace"]["artifact_count"] == 71
|
||||
assert payload["infospace"]["artifact_count"] == 76
|
||||
assert payload["infospace"]["kinds"] == {
|
||||
"access-descriptor-set": 1,
|
||||
"alignment-review-kit": 1,
|
||||
"assimilation": 1,
|
||||
"assimilation": 2,
|
||||
"alignment-review-schema": 1,
|
||||
"alignment-review-workflow": 1,
|
||||
"alignment-scorecard": 1,
|
||||
|
|
@ -47,11 +47,11 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
"consumer-workplan-template": 1,
|
||||
"evaluation-pack": 1,
|
||||
"evaluation-question-set": 1,
|
||||
"example": 1,
|
||||
"example": 2,
|
||||
"extension-candidate-set": 1,
|
||||
"interface-card-expectation": 1,
|
||||
"kernel": 2,
|
||||
"mapping": 2,
|
||||
"mapping": 3,
|
||||
"mapping-expectation": 1,
|
||||
"model": 12,
|
||||
"model-extension": 1,
|
||||
|
|
@ -63,15 +63,15 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
"practice-pattern-scheme": 1,
|
||||
"profile-alignment": 1,
|
||||
"profile": 1,
|
||||
"profile-artifact": 13,
|
||||
"standard": 3,
|
||||
"profile-artifact": 14,
|
||||
"standard": 4,
|
||||
"visualization-example-set": 1,
|
||||
}
|
||||
|
||||
|
||||
def test_model_and_standard_lists_are_filtered() -> None:
|
||||
assert list_models()["count"] == 12
|
||||
assert list_standards()["count"] == 3
|
||||
assert list_standards()["count"] == 4
|
||||
|
||||
|
||||
def test_review_kit_exports_workflow_and_template() -> None:
|
||||
|
|
@ -99,14 +99,14 @@ def test_validate_canon_passes_scaffold() -> None:
|
|||
assert payload["ok"] is True
|
||||
assert payload["errors"] == []
|
||||
assert "warnings" in payload
|
||||
assert payload["details"]["artifact_count"] == 71
|
||||
assert payload["details"]["artifact_count"] == 76
|
||||
|
||||
|
||||
def test_graph_exports_relationship_summary() -> None:
|
||||
payload = artifact_graph()
|
||||
|
||||
assert payload["ok"] is True
|
||||
assert payload["graph"]["node_count"] == 71
|
||||
assert payload["graph"]["node_count"] == 76
|
||||
assert payload["graph"]["edge_count"] > 15
|
||||
|
||||
|
||||
|
|
@ -180,6 +180,21 @@ def test_small_saas_profile_graph_exports_slice() -> None:
|
|||
assert "small-saas/service/billing-portal" in payload["graph"]["nodes"]
|
||||
|
||||
|
||||
def test_small_saas_capability_requirements_meet_maturity_floors() -> None:
|
||||
path = (
|
||||
DEFAULT_INFOSPACE_ROOT
|
||||
/ "profiles"
|
||||
/ "small-saas"
|
||||
/ "artifacts"
|
||||
/ "capability-requirements.yaml"
|
||||
)
|
||||
payload = review_capability_record(path)
|
||||
|
||||
assert payload["ok"] is True
|
||||
assert {item["status"] for item in payload["requirements"]} == {"met"}
|
||||
assert len(payload["provisions"]) == 4
|
||||
|
||||
|
||||
def test_generators_write_expected_assets(tmp_path) -> None:
|
||||
root = tmp_path / "infospace"
|
||||
shutil.copytree(DEFAULT_INFOSPACE_ROOT, root)
|
||||
|
|
@ -214,6 +229,7 @@ def test_generators_write_expected_assets(tmp_path) -> None:
|
|||
root / "agent" / "briefs" / "benchmark-caring-kubernetes-rbac.md"
|
||||
).is_file()
|
||||
assert (root / "agent" / "briefs" / "review-kit-alignment.md").is_file()
|
||||
assert (root / "agent" / "briefs" / "standard-emission-cadence.md").is_file()
|
||||
assert (
|
||||
root / "agent" / "templates" / "consumer-alignment-workplan.template.md"
|
||||
).is_file()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue