Some checks failed
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Failing after 4m15s
Test Suite / k6 /api/health Baseline (push) Has been skipped
Test Suite / playwright-smoke (push) Has been skipped
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
K-Ext-4/P8 deklarative Agent-Slots; P7 tech_debt Read Model und Vokabular; Review-Attention in den Kernel verlagert. Co-authored-by: Cursor <cursoragent@cursor.com>
139 lines
4.2 KiB
Python
139 lines
4.2 KiB
Python
"""Unit tests for agent slot providers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta, timezone
|
|
from types import SimpleNamespace
|
|
|
|
from steering.agent_slots.guardrail_review import resolve_guardrail_review_slots
|
|
from steering.agent_slots.recurring_due import resolve_recurring_due_slots
|
|
from steering.agent_slots.review_due import resolve_review_due_slots
|
|
from steering.agent_slots.registry import compute_agent_slots
|
|
from steering.kernel.models import HorizonMarker
|
|
|
|
|
|
def _ctx(**kwargs):
|
|
defaults = {
|
|
"initiative_id": "init-1",
|
|
"horizon": HorizonMarker(kind="none"),
|
|
"operating_context": {
|
|
"data_slices": ["reviews", "recurring", "roadmap"],
|
|
"steering_elements": ["gate_fulfillment", "recurring_rhythm"],
|
|
"agent_slot_config": {},
|
|
},
|
|
"_reviews": [],
|
|
"_recurring_elements": [],
|
|
"_actions": [],
|
|
}
|
|
defaults.update(kwargs)
|
|
|
|
class FakeCtx:
|
|
initiative_id = defaults["initiative_id"]
|
|
horizon = defaults["horizon"]
|
|
operating_context = defaults["operating_context"]
|
|
|
|
@property
|
|
def steering_elements(self):
|
|
return frozenset(self.operating_context.get("steering_elements") or [])
|
|
|
|
@property
|
|
def data_slices(self):
|
|
return list(self.operating_context.get("data_slices") or [])
|
|
|
|
@property
|
|
def agent_slot_config(self):
|
|
return dict(self.operating_context.get("agent_slot_config") or {})
|
|
|
|
@property
|
|
def reviews(self):
|
|
return defaults["_reviews"]
|
|
|
|
@property
|
|
def recurring_elements(self):
|
|
return defaults["_recurring_elements"]
|
|
|
|
@property
|
|
def actions(self):
|
|
return defaults["_actions"]
|
|
|
|
return FakeCtx()
|
|
|
|
|
|
def test_review_due_slot_for_overdue_planned_review():
|
|
past = (datetime.now(timezone.utc) - timedelta(days=1)).isoformat()
|
|
ctx = _ctx(
|
|
_reviews=[
|
|
{
|
|
"id": "rev-1",
|
|
"title": "Architektur-Review",
|
|
"status": "planned",
|
|
"due_at": past,
|
|
}
|
|
]
|
|
)
|
|
slots = resolve_review_due_slots(ctx)
|
|
assert len(slots) == 1
|
|
assert slots[0]["slot_key"] == "review.due"
|
|
assert slots[0]["scope_id"] == "rev-1"
|
|
assert slots[0]["actor_role_hint"] == "reviewer"
|
|
|
|
|
|
def test_recurring_due_slot():
|
|
past = (datetime.now(timezone.utc) - timedelta(hours=2)).isoformat()
|
|
ctx = _ctx(
|
|
_recurring_elements=[
|
|
{
|
|
"id": "rec-1",
|
|
"title": "Sprint-Retro",
|
|
"status": "active",
|
|
"next_due_at": past,
|
|
}
|
|
]
|
|
)
|
|
slots = resolve_recurring_due_slots(ctx)
|
|
assert len(slots) == 1
|
|
assert slots[0]["slot_key"] == "recurring.due"
|
|
|
|
|
|
def test_guardrail_slot_when_gate_has_planning_debt():
|
|
ctx = _ctx(
|
|
horizon=HorizonMarker(
|
|
kind="gate",
|
|
gate_roadmap_item_id="gate-1",
|
|
gate_title="G3 Architektur",
|
|
),
|
|
_reviews=[],
|
|
)
|
|
read_models = {
|
|
"planning_debt": [{"roadmap_item_id": "gate-1", "title": "G3"}],
|
|
}
|
|
slots = resolve_guardrail_review_slots(ctx, read_models)
|
|
assert len(slots) == 1
|
|
assert slots[0]["slot_key"] == "review.guardrail"
|
|
assert slots[0]["guardrail_pack"] == "default_v0"
|
|
|
|
|
|
def test_compute_agent_slots_respects_enabled_slots_filter():
|
|
past = (datetime.now(timezone.utc) - timedelta(days=1)).isoformat()
|
|
ctx = _ctx(
|
|
operating_context={
|
|
"data_slices": ["reviews", "recurring", "roadmap"],
|
|
"steering_elements": ["gate_fulfillment", "recurring_rhythm"],
|
|
"agent_slot_config": {"enabled_slots": ["review.due"]},
|
|
},
|
|
_reviews=[
|
|
{"id": "rev-1", "title": "Review", "status": "planned", "due_at": past}
|
|
],
|
|
_recurring_elements=[
|
|
{
|
|
"id": "rec-1",
|
|
"title": "Retro",
|
|
"status": "active",
|
|
"next_due_at": past,
|
|
}
|
|
],
|
|
)
|
|
slots = compute_agent_slots(ctx, read_models={}, proposals={})
|
|
assert len(slots) == 1
|
|
assert slots[0]["slot_key"] == "review.due"
|