chore(core): stage 1 contracts — dialog, API schemas + fixtures, integrations, monitoring, modules
CI / ruff · pytest (pull_request) Successful in 22s
CI / ruff · pytest (pull_request) Successful in 22s
Freeze interfaces between lanes A (bot), B (backend), C (dashboard) so three developers work in parallel without touching each other's files: dialog Event/Reply + engine registry with echo stub, integration protocols with in-memory defaults, MonitoringService with noop stub, /api/v1 schemas with fixture-backed routes, frozen main.py wiring, config/modules.yaml + due_scales(), DAR-5, tzdata, Andrey trajectory, lanes in WORKFLOW, ADR-010. Refs #34 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+5
-15
@@ -60,9 +60,7 @@ def test_yaml_loads_and_every_rule_has_evaluator() -> None:
|
||||
|
||||
def test_unknown_rule_id_rejected() -> None:
|
||||
with pytest.raises(ValidationError):
|
||||
RulesConfig.model_validate(
|
||||
{"rules": [{"id": "nope", "actions": [{"type": "alert", "level": "info"}]}]}
|
||||
)
|
||||
RulesConfig.model_validate({"rules": [{"id": "nope", "actions": [{"type": "alert", "level": "info"}]}]})
|
||||
|
||||
|
||||
def test_alert_without_level_rejected() -> None:
|
||||
@@ -134,9 +132,7 @@ def test_cssrs_levels() -> None:
|
||||
(None, "moderate", None, False),
|
||||
],
|
||||
)
|
||||
def test_weapon_access_with_risk(
|
||||
weapon: bool | None, cssrs: str | None, item9: int | None, fires: bool
|
||||
) -> None:
|
||||
def test_weapon_access_with_risk(weapon: bool | None, cssrs: str | None, item9: int | None, fires: bool) -> None:
|
||||
scales = [] if item9 is None else [ScalePoint(scale="phq9", ts=at(5, 20), total=10, item9=item9)]
|
||||
s = snap(5, weapon_access=weapon, cssrs_risk=cssrs, scale_results=scales)
|
||||
assert ("weapon_access_risk" in codes(evaluate(s), "crisis")) is fires
|
||||
@@ -188,9 +184,7 @@ def test_future_scale_results_ignored() -> None:
|
||||
assert evaluate(s) == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("sex", "total", "fires"), [("m", 4, True), ("m", 3, False), ("f", 3, True), ("f", 2, False)]
|
||||
)
|
||||
@pytest.mark.parametrize(("sex", "total", "fires"), [("m", 4, True), ("m", 3, False), ("f", 3, True), ("f", 2, False)])
|
||||
def test_auditc_by_sex(sex: str, total: int, fires: bool) -> None:
|
||||
s = snap(1, sex=sex, scale_results=[ScalePoint(scale="auditc", ts=at(0), total=total)])
|
||||
acts = evaluate(s)
|
||||
@@ -212,9 +206,7 @@ def test_quit_intent_voiced() -> None:
|
||||
|
||||
|
||||
def test_quit_intent_followed_by_skipped_dose() -> None:
|
||||
s = snap(
|
||||
7, checkins=[ci(5, med_taken=True, quit_intent=True), ci(6, med_taken=True), ci(7, med_taken=False)]
|
||||
)
|
||||
s = snap(7, checkins=[ci(5, med_taken=True, quit_intent=True), ci(6, med_taken=True), ci(7, med_taken=False)])
|
||||
assert "quit_intent" in codes(evaluate(s), "alert")
|
||||
no_intent = snap(7, checkins=[ci(6, med_taken=True), ci(7, med_taken=False)])
|
||||
assert "quit_intent" not in codes(evaluate(no_intent))
|
||||
@@ -303,9 +295,7 @@ def test_silence_over_3_days() -> None:
|
||||
assert evaluate(snap(10, last_patient_message_at=at(7, 21))) == [] # exactly 3 days
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("age", "day", "fires"), [(23, 8, True), (24, 28, True), (25, 8, False), (23, 29, False)]
|
||||
)
|
||||
@pytest.mark.parametrize(("age", "day", "fires"), [(23, 8, True), (24, 28, True), (25, 8, False), (23, 29, False)])
|
||||
def test_young_adult_enhanced_monitoring(age: int, day: int, fires: bool) -> None:
|
||||
acts = evaluate(snap(day, age=age))
|
||||
assert (acts == [a for a in acts if a.type == "enhanced_monitoring"] and bool(acts)) is fires
|
||||
|
||||
Reference in New Issue
Block a user