Files
state-hub/tests/test_classification.py
tegwick 0949d4c0d8 feat(classification-spine): implement STATE-WP-0065 repo-anchored model
Replace the ad-hoc coordination-domain spine with the Repo Classification
Standard: 14 market domains, classification columns on managed_repos, and
workplans anchored by repo_id (topic_id optional).

- Add Alembic migration d8e9f0a1b2c3 with data backfill and workstream→workplan rename
- Add api/classification.py validation and register-from-classification tooling
- Expose workplan-first REST/MCP surface with legacy workstream aliases
- Add C-24 consistency rule and legacy domain frontmatter mapping
- Update dashboard repos page with category/capability/stake filters
- Update orientation docs; mark STATE-WP-0065 finished
2026-06-22 13:52:13 +02:00

67 lines
2.4 KiB
Python

"""Tests for api.classification validation module (STATE-WP-0065 P2)."""
from __future__ import annotations
import pytest
from api.classification import (
ClassificationData,
validate_classification,
)
def _valid_block(**overrides) -> dict:
base = {
"category": "tooling",
"domain": "infotech",
"secondary_domains": [],
"capability_tags": ["platform"],
"business_stake": ["technology", "operations"],
"business_mechanics": ["coordination"],
}
base.update(overrides)
return base
class TestValidateClassification:
def test_valid_block_passes(self):
errors, warnings = validate_classification(_valid_block())
assert errors == []
def test_missing_category_fails(self):
block = _valid_block()
del block["category"]
errors, _ = validate_classification(block)
assert any("category" in err for err in errors)
def test_invalid_category_fails(self):
errors, _ = validate_classification(_valid_block(category="not-a-category"))
assert any("category" in err for err in errors)
def test_invalid_domain_fails(self):
errors, _ = validate_classification(_valid_block(domain="not-a-domain"))
assert any("domain" in err for err in errors)
def test_unknown_capability_tag_warns(self):
_, warnings = validate_classification(_valid_block(capability_tags=["totally-made-up-tag"]))
assert any("capability_tag" in warn for warn in warnings)
def test_invalid_business_stake_fails(self):
errors, _ = validate_classification(_valid_block(business_stake=["not-a-stake"]))
assert any("business_stake" in err for err in errors)
def test_secondary_domain_repeats_primary_fails(self):
errors, _ = validate_classification(
_valid_block(domain="infotech", secondary_domains=["infotech"])
)
assert any("repeats the primary domain" in err for err in errors)
class TestClassificationData:
def test_round_trip_dict(self):
block = _valid_block(classified_at="2026-06-22", classified_by="human", version="1.0")
data = ClassificationData.from_block(block)
payload = data.to_dict()
assert payload["category"] == "tooling"
assert payload["domain"] == "infotech"
assert payload["classified_by"] == "human"
assert payload["standard_version"] == "1.0"