140 lines
5.3 KiB
Python
140 lines
5.3 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from opc.core.config import OPCConfig, RoleConfig
|
|
from opc.layer2_organization.org_engine import OrgEngine
|
|
from opc.layer2_organization.org_work_item_planner import (
|
|
build_company_work_item_runtime_plan,
|
|
build_custom_org_work_item_blueprint,
|
|
)
|
|
|
|
|
|
def _custom_config(*roles: RoleConfig, final_decider_role_id: str | None = "ceo") -> OPCConfig:
|
|
config = OPCConfig()
|
|
config.org.company_profile = "custom"
|
|
config.org.final_decider_role_id = final_decider_role_id
|
|
config.org.roles = list(roles)
|
|
return config
|
|
|
|
|
|
def test_custom_org_blueprint_uses_roles_teams_seats_and_skills() -> None:
|
|
config = _custom_config(
|
|
RoleConfig(
|
|
id="ceo",
|
|
name="CEO",
|
|
responsibility="Owns final decisions",
|
|
reports_to="owner",
|
|
can_spawn=["cto"],
|
|
prompt_refs=["ceo-prompt"],
|
|
skill_refs=["strategy"],
|
|
),
|
|
RoleConfig(
|
|
id="cto",
|
|
name="CTO",
|
|
responsibility="Coordinates engineering",
|
|
reports_to="ceo",
|
|
can_spawn=["engineer"],
|
|
prompt_refs=["cto-prompt"],
|
|
skill_refs=["architecture"],
|
|
),
|
|
RoleConfig(
|
|
id="engineer",
|
|
name="Engineer",
|
|
responsibility="Builds the deliverable",
|
|
reports_to="cto",
|
|
prompt_refs=["eng-prompt"],
|
|
skill_refs=["coding"],
|
|
),
|
|
)
|
|
org = OrgEngine(config)
|
|
|
|
blueprint = build_custom_org_work_item_blueprint(
|
|
org,
|
|
runtime_topology=org.build_runtime_delegation_topology(),
|
|
original_request="Ship the product",
|
|
)
|
|
payload = blueprint.to_dict()
|
|
|
|
assert payload["profile"] == "custom"
|
|
assert payload["final_decider_role_id"] == "ceo"
|
|
assert payload["root_projection_id"] == "custom::intake::ceo"
|
|
seeds = {seed["role_id"]: seed for seed in payload["seeds"]}
|
|
assert seeds["ceo"]["turn_type"] == "intake"
|
|
assert seeds["cto"]["allowed_delegate_role_ids"] == ["engineer"]
|
|
assert seeds["engineer"]["skill_refs"] == ["coding"]
|
|
assert seeds["engineer"]["prompt_refs"] == ["eng-prompt"]
|
|
assert any(link["link_type"] == "delegates_to" for link in payload["collaboration_links"])
|
|
|
|
|
|
def test_custom_blueprint_requires_final_decider_for_multiple_top_level_roles() -> None:
|
|
config = _custom_config(
|
|
RoleConfig(id="ceo", name="CEO", responsibility="Strategy", reports_to="owner"),
|
|
RoleConfig(id="coo", name="COO", responsibility="Operations", reports_to="owner"),
|
|
final_decider_role_id=None,
|
|
)
|
|
org = OrgEngine(config)
|
|
|
|
with pytest.raises(ValueError, match="final_decider_role_id"):
|
|
build_custom_org_work_item_blueprint(
|
|
org,
|
|
runtime_topology=org.build_runtime_delegation_topology(),
|
|
)
|
|
|
|
|
|
def test_custom_runtime_definition_generation_api_is_removed() -> None:
|
|
config = _custom_config(
|
|
RoleConfig(id="ceo", name="CEO", responsibility="Strategy", reports_to="owner"),
|
|
)
|
|
org = OrgEngine(config)
|
|
|
|
assert not hasattr(org, "build_" + "work" + "flow_definition")
|
|
|
|
|
|
def test_company_work_item_runtime_plan_serializes_projection_policies() -> None:
|
|
config = _custom_config(
|
|
RoleConfig(id="ceo", name="CEO", responsibility="Strategy", reports_to="owner", can_spawn=["cto"]),
|
|
RoleConfig(id="cto", name="CTO", responsibility="Engineering", reports_to="ceo", skill_refs=["architecture"]),
|
|
)
|
|
org = OrgEngine(config)
|
|
|
|
plan = build_company_work_item_runtime_plan(
|
|
org,
|
|
profile="custom",
|
|
runtime_topology=org.build_runtime_delegation_topology(),
|
|
original_request="Build the product",
|
|
)
|
|
payload = plan.to_dict()
|
|
|
|
assert payload["runtime_model"] == "multi_team_org"
|
|
assert payload["root_projection_id"] == "custom::intake::ceo"
|
|
projections = {item["role_id"]: item for item in payload["projections"]}
|
|
assert projections["ceo"]["turn_type"] == "intake"
|
|
assert projections["cto"]["turn_type"] == "execute"
|
|
assert projections["cto"]["skill_refs"] == ["architecture"]
|
|
assert projections["cto"]["gate_policy"]["rework_projection_id"] == projections["cto"]["projection_id"]
|
|
|
|
|
|
def test_company_work_item_runtime_plan_has_no_obsolete_bridge_properties() -> None:
|
|
config = _custom_config(
|
|
RoleConfig(id="ceo", name="CEO", responsibility="Strategy", reports_to="owner", can_spawn=["cto"]),
|
|
RoleConfig(id="cto", name="CTO", responsibility="Engineering", reports_to="ceo"),
|
|
)
|
|
org = OrgEngine(config)
|
|
|
|
plan = build_company_work_item_runtime_plan(
|
|
org,
|
|
profile="custom",
|
|
runtime_topology=org.build_runtime_delegation_topology(),
|
|
original_request="Build the product",
|
|
)
|
|
cto_projection = next(item for item in plan.projections if item.role_id == "cto")
|
|
|
|
assert not hasattr(plan, "stages")
|
|
old_projection_attr = "sta" + "ge_id"
|
|
for obsolete_attr in (old_projection_attr, "description", "dependencies", "gate"):
|
|
assert not hasattr(cto_projection, obsolete_attr)
|
|
assert plan.projection_order_map()[plan.root_projection_id] == 0
|
|
assert plan.dependencies_for(cto_projection.projection_id) == [plan.root_projection_id]
|
|
assert cto_projection.projection_id in plan.dependent_projection_ids(plan.root_projection_id)
|