Introduce identity model and reconcile upstream imports
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a070b5-4994-7271-bd8b-7c3dbcedec4b
This commit is contained in:
parent
a2b254786e
commit
361c944325
38 changed files with 1014 additions and 123 deletions
|
|
@ -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"] == 77
|
||||
assert payload["infospace"]["artifact_count"] == 78
|
||||
|
||||
|
||||
def test_cli_missing_profile_uses_structured_error(capsys) -> None:
|
||||
|
|
|
|||
26
tests/test_identity_boundary.py
Normal file
26
tests/test_identity_boundary.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
from info_tech_canon.generation import concept_ownership
|
||||
from info_tech_canon.service import load_context
|
||||
|
||||
|
||||
def test_identity_does_not_own_its_upstream_imports():
|
||||
context = load_context()
|
||||
rows = concept_ownership(context)["concepts"]
|
||||
owned = {r["concept"] for r in rows if r["owner"] == "model/identity" and r["source"] == "frontmatter.owned_concepts"}
|
||||
assert len(owned) == 23
|
||||
assert owned.isdisjoint({"Actor", "Person", "Agent", "Organization", "Group", "Role", "Membership", "Subject", "Principal", "Relationship Tuple", "Evidence", "Evidence Source", "Authority", "Responsibility", "Ownership"})
|
||||
for concept in owned:
|
||||
assert {r["owner"] for r in rows if r["concept"] == concept} == {"model/identity"}
|
||||
|
||||
|
||||
def test_incumbent_definition_anchors_are_imports():
|
||||
root = load_context().infospace_root
|
||||
for path, concept, anchor in [
|
||||
("models/organization/InfoTechCanonOrganizationModel.md", "Delegation", "## 10.18 Delegation"),
|
||||
("models/information-space/InfoTechCanonInformationSpaceModel.md", "Identifier", "## 11.37 Identifier"),
|
||||
]:
|
||||
text = (root / path).read_text()
|
||||
assert anchor in text
|
||||
assert f"**{concept}** is" not in text
|
||||
assert "../identity/InfoTechCanonIdentityModel.md" in text
|
||||
access = (root / "models/access-control/InfoTechCanonAccessControlModel.md").read_text()
|
||||
assert "ITC-IDENT" in access.split("## 3.5 Boundary with Identity and Authentication", 1)[1].split("## ", 1)[0]
|
||||
45
tests/test_import_reviews.py
Normal file
45
tests/test_import_reviews.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
from types import SimpleNamespace
|
||||
import yaml
|
||||
|
||||
from info_tech_canon.import_reviews import reviewed_import_cycles
|
||||
|
||||
|
||||
def fixture(tmp_path):
|
||||
(tmp_path / "validation").mkdir()
|
||||
(tmp_path / "review.md").write_text("Distinct concept owners reviewed.")
|
||||
edges = [["a", "uses", "b"], ["b", "uses", "a"]]
|
||||
(tmp_path / "validation/model-import-reviews.yaml").write_text(yaml.safe_dump(
|
||||
{"reviews": [{"boundary_review": "review.md", "edges": edges}]}))
|
||||
return [SimpleNamespace(id="a", kind="model", relationships=[{"type": "uses", "target": "b"}]),
|
||||
SimpleNamespace(id="b", kind="model", relationships=[{"type": "uses", "target": "a"}])]
|
||||
|
||||
|
||||
def test_exact_review_preserves_reciprocal_imports(tmp_path):
|
||||
artifacts = fixture(tmp_path)
|
||||
assert len(reviewed_import_cycles(artifacts, tmp_path)) == 1
|
||||
assert artifacts[0].relationships == [{"type": "uses", "target": "b"}]
|
||||
|
||||
|
||||
def test_new_internal_edge_or_type_is_not_excused(tmp_path):
|
||||
artifacts = fixture(tmp_path)
|
||||
artifacts[0].relationships.append({"type": "defines", "target": "b"})
|
||||
assert reviewed_import_cycles(artifacts, tmp_path) is None
|
||||
|
||||
|
||||
def test_new_component_member_is_not_excused(tmp_path):
|
||||
artifacts = fixture(tmp_path)
|
||||
artifacts[0].relationships.append({"type": "uses", "target": "c"})
|
||||
artifacts.append(SimpleNamespace(id="c", kind="model", relationships=[{"type": "uses", "target": "a"}]))
|
||||
assert reviewed_import_cycles(artifacts, tmp_path) is None
|
||||
|
||||
|
||||
def test_missing_rationale_is_not_excused(tmp_path):
|
||||
artifacts = fixture(tmp_path)
|
||||
(tmp_path / "review.md").unlink()
|
||||
assert reviewed_import_cycles(artifacts, tmp_path) is None
|
||||
|
||||
|
||||
def test_unreviewed_second_cycle_is_not_excused(tmp_path):
|
||||
artifacts = fixture(tmp_path)
|
||||
artifacts.append(SimpleNamespace(id="c", kind="model", relationships=[{"type": "uses", "target": "c"}]))
|
||||
assert reviewed_import_cycles(artifacts, tmp_path) is None
|
||||
|
|
@ -25,7 +25,7 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
|
||||
assert payload["ok"] is True
|
||||
assert payload["infospace"]["slug"] == "canon"
|
||||
assert payload["infospace"]["artifact_count"] == 77
|
||||
assert payload["infospace"]["artifact_count"] == 78
|
||||
assert payload["infospace"]["kinds"] == {
|
||||
"access-descriptor-set": 1,
|
||||
"alignment-review-kit": 1,
|
||||
|
|
@ -53,7 +53,7 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
"kernel": 2,
|
||||
"mapping": 3,
|
||||
"mapping-expectation": 1,
|
||||
"model": 13,
|
||||
"model": 14,
|
||||
"model-extension": 1,
|
||||
"model-selection-guide": 1,
|
||||
"native-concept-map": 1,
|
||||
|
|
@ -70,7 +70,7 @@ def test_inspect_canon_counts_artifact_kinds() -> None:
|
|||
|
||||
|
||||
def test_model_and_standard_lists_are_filtered() -> None:
|
||||
assert list_models()["count"] == 13
|
||||
assert list_models()["count"] == 14
|
||||
assert list_standards()["count"] == 4
|
||||
|
||||
|
||||
|
|
@ -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"] == 77
|
||||
assert payload["details"]["artifact_count"] == 78
|
||||
|
||||
|
||||
def test_graph_exports_relationship_summary() -> None:
|
||||
payload = artifact_graph()
|
||||
|
||||
assert payload["ok"] is True
|
||||
assert payload["graph"]["node_count"] == 77
|
||||
assert payload["graph"]["node_count"] == 78
|
||||
assert payload["graph"]["edge_count"] > 15
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue