All checks were successful
Deploy Development / deploy (push) Successful in 43s
Test Suite / pytest-backend (push) Successful in 3m13s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 13s
om_capabilities-Pruefung blockierte Methodenwechsel auf initiative.generic; Gate-Slices reichen fuer Meilenstein-Steuerung. Co-authored-by: Cursor <cursoragent@cursor.com>
133 lines
4.5 KiB
Python
133 lines
4.5 KiB
Python
"""AP2.4 — Steering elements and method contract."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from steering.elements.registry import validate_steering_element_keys
|
|
from steering.methods.registry import get_method, list_compatible_methods, ui_features_as_dict
|
|
from steering.graph.profiles import get_graph_profile
|
|
|
|
|
|
def test_all_methods_have_valid_steering_elements():
|
|
from steering.methods.registry import list_methods
|
|
|
|
for method in list_methods():
|
|
validate_steering_element_keys(method.steering_elements)
|
|
|
|
|
|
def test_sequential_dependency_contract():
|
|
method = get_method("sequential_dependency")
|
|
assert method is not None
|
|
assert "critical_path" in method.steering_elements
|
|
assert "criticalPathControl" in method.ui_features
|
|
assert get_graph_profile("sequential_dependency").enforce_gate_blocking is True
|
|
|
|
|
|
def test_continuous_product_ui_features_from_method():
|
|
method = get_method("continuous_product")
|
|
assert method is not None
|
|
features = ui_features_as_dict(method.ui_features)
|
|
assert features["continuousProductWorkMode"] is True
|
|
assert features["steeringSnapshotOnWorkSprint"] is True
|
|
|
|
|
|
def test_list_compatible_methods_linear_includes_queue_pull():
|
|
methods = list_compatible_methods("initiative.linear_project")
|
|
keys = {m.key for m in methods}
|
|
assert "sequential_dependency" in keys
|
|
assert "queue_pull" in keys
|
|
|
|
|
|
def test_list_compatible_methods_product_excludes_maturity():
|
|
methods = list_compatible_methods("initiative.product")
|
|
keys = {m.key for m in methods}
|
|
assert "continuous_product" in keys
|
|
assert "maturity_progression" not in keys
|
|
|
|
|
|
def test_product_milestone_driven_compatible_with_generic():
|
|
from steering.methods.registry import list_compatible_methods
|
|
|
|
methods = list_compatible_methods("initiative.generic")
|
|
keys = {m.key for m in methods}
|
|
assert "product_milestone_driven" in keys
|
|
|
|
|
|
def test_operating_context_includes_method_contract(client):
|
|
from tests.factories import provision_user_in_tenant
|
|
from tests.test_initiatives_actions import _auth, _create_initiative, _login
|
|
|
|
user = provision_user_in_tenant(tenant_role="member")
|
|
token = _login(client, user)
|
|
|
|
created = _create_initiative(
|
|
client,
|
|
token,
|
|
title="Linear Contract",
|
|
archetype_key="initiative.linear_project",
|
|
)
|
|
initiative_id = created.json()["id"]
|
|
|
|
res = client.get(
|
|
f"/api/initiatives/{initiative_id}/operating-context",
|
|
headers=_auth(token),
|
|
)
|
|
assert res.status_code == 200
|
|
body = res.json()
|
|
assert "critical_path" in body["steering_elements"]
|
|
assert body["ui_features"].get("criticalPathControl") is True
|
|
assert "graph_profile" in body
|
|
assert body["compatible_methods"]
|
|
assert any(m["key"] == "sequential_dependency" for m in body["compatible_methods"])
|
|
|
|
|
|
def test_steering_methods_filtered_by_archetype(client):
|
|
from tests.factories import provision_user_in_tenant
|
|
from tests.test_initiatives_actions import _auth, _login
|
|
|
|
user = provision_user_in_tenant(tenant_role="member")
|
|
token = _login(client, user)
|
|
|
|
res = client.get(
|
|
"/api/steering/methods",
|
|
params={"archetype_key": "initiative.product"},
|
|
headers=_auth(token),
|
|
)
|
|
assert res.status_code == 200
|
|
keys = {m["key"] for m in res.json()}
|
|
assert "continuous_product" in keys
|
|
assert "maturity_progression" not in keys
|
|
product = next(m for m in res.json() if m["key"] == "continuous_product")
|
|
assert "steering_elements" in product
|
|
assert product["is_default"] is True
|
|
|
|
|
|
def test_queue_pull_on_linear_changes_steering_elements(client):
|
|
from tests.factories import provision_user_in_tenant
|
|
from tests.test_initiatives_actions import _auth, _create_initiative, _login
|
|
|
|
user = provision_user_in_tenant(tenant_role="member")
|
|
token = _login(client, user)
|
|
|
|
created = _create_initiative(
|
|
client,
|
|
token,
|
|
title="Linear Queue",
|
|
archetype_key="initiative.linear_project",
|
|
)
|
|
initiative_id = created.json()["id"]
|
|
|
|
client.patch(
|
|
f"/api/steering/initiatives/{initiative_id}/context",
|
|
json={"method_key": "queue_pull"},
|
|
headers=_auth(token),
|
|
)
|
|
|
|
ctx = client.get(
|
|
f"/api/initiatives/{initiative_id}/operating-context",
|
|
headers=_auth(token),
|
|
)
|
|
body = ctx.json()
|
|
assert "queue_inbox" in body["steering_elements"]
|
|
assert "critical_path" not in body["steering_elements"]
|
|
assert body["ui_features"].get("criticalPathControl") is not True
|