diff --git a/scripts/smoke-resistance-openness-db.py b/scripts/smoke-resistance-openness-db.py index f3d7b95..8098552 100644 --- a/scripts/smoke-resistance-openness-db.py +++ b/scripts/smoke-resistance-openness-db.py @@ -195,6 +195,43 @@ def _summarize( } +def _openness_curve(api_results: list[dict[str, Any]]) -> list[float]: + return [float(item.get("effective_openness") or 0.0) for item in api_results] + + +def _stage_curve(api_results: list[dict[str, Any]]) -> list[str]: + return [str(item.get("stage") or "") for item in api_results] + + +def _assert_turn_sequence(label: str, api_results: list[dict[str, Any]], expected_count: int) -> None: + if len(api_results) != expected_count: + raise SmokeError(f"{label} API returned {len(api_results)} turns, expected {expected_count}") + expected_turns = list(range(1, expected_count + 1)) + actual_turns = [int(item.get("turn_seq") or 0) for item in api_results] + if actual_turns != expected_turns: + raise SmokeError(f"{label} API turn sequence mismatch: {actual_turns} != {expected_turns}") + flagged_turns = [item.get("turn_seq") for item in api_results if item.get("safety_flagged")] + if flagged_turns: + raise SmokeError(f"{label} API unexpectedly triggered safety flags on turns {flagged_turns}") + + +def _assert_db_storage(label: str, db_result: dict[str, Any], expected_state_turn_seq: int) -> None: + state = db_result.get("session_state") or {} + if int(state.get("turn_seq") or 0) != expected_state_turn_seq: + raise SmokeError(f"{label} DB session_state turn_seq mismatch: {state}") + + turns = db_result.get("turns") or [] + expected_turn_rows = expected_state_turn_seq * 2 + if len(turns) != expected_turn_rows: + raise SmokeError(f"{label} DB stored {len(turns)} turns, expected {expected_turn_rows}") + + state_rows = [row for row in turns if row.get("client_states")] + if len(state_rows) < expected_state_turn_seq: + raise SmokeError( + f"{label} DB stored {len(state_rows)} turn_client_state rows, expected at least {expected_state_turn_seq}" + ) + + async def run(args: argparse.Namespace) -> dict[str, Any]: _load_api_env() dsn = args.database_url or os.environ.get("DATABASE_URL") @@ -221,15 +258,39 @@ async def run(args: argparse.Namespace) -> dict[str, Any]: empathy_db = await _fetch_curve(dsn, empathy_session) advice_db = await _fetch_curve(dsn, advice_session) + expected_turns = len(EMPATHIC_UTTERANCES) + if len(ADVICE_JUMP_UTTERANCES) != expected_turns: + raise SmokeError("empathy/advice utterance sets must have the same turn count") + + _assert_turn_sequence("empathy", empathy_results, expected_turns) + _assert_turn_sequence("advice_jump", advice_results, expected_turns) + _assert_db_storage("empathy", empathy_db, expected_turns) + _assert_db_storage("advice_jump", advice_db, expected_turns) + + empathy_curve = _openness_curve(empathy_results) + advice_curve = _openness_curve(advice_results) + empathy_stages = _stage_curve(empathy_results) + advice_stages = _stage_curve(advice_results) + empathy_final = float((empathy_db.get("session_state") or {}).get("effective_openness") or 0.0) advice_final = float((advice_db.get("session_state") or {}).get("effective_openness") or 0.0) empathy_stage = str((empathy_db.get("session_state") or {}).get("stage") or "") advice_stage = str((advice_db.get("session_state") or {}).get("stage") or "") + if empathy_stages[2:] != ["탐색"] * (expected_turns - 2): + raise SmokeError(f"expected empathy stage 탐색 from turn 3, got {empathy_stages}") + if empathy_curve[2] <= 0 or empathy_curve[-1] <= empathy_curve[2]: + raise SmokeError(f"expected empathy openness to open from turn 3 and keep rising, got {empathy_curve}") + if advice_stages != ["라포"] * expected_turns: + raise SmokeError(f"expected advice_jump stage 라포 throughout, got {advice_stages}") + if any(value != 0.0 for value in advice_curve): + raise SmokeError(f"expected advice_jump openness to stay at 0.0, got {advice_curve}") if empathy_final <= advice_final: raise SmokeError(f"expected empathy openness > advice openness, got {empathy_final} <= {advice_final}") - if empathy_stage == advice_stage and empathy_final < 0.1: - raise SmokeError(f"empathy curve did not open enough: stage={empathy_stage}, openness={empathy_final}") + if empathy_stage != "탐색" or empathy_final < 0.1: + raise SmokeError(f"empathy DB curve did not open enough: stage={empathy_stage}, openness={empathy_final}") + if advice_stage != "라포" or advice_final != 0.0: + raise SmokeError(f"advice_jump DB curve did not stay closed: stage={advice_stage}, openness={advice_final}") return { "ok": True, @@ -242,6 +303,9 @@ async def run(args: argparse.Namespace) -> dict[str, Any]: "advice_final_openness": advice_final, "empathy_stage": empathy_stage, "advice_stage": advice_stage, + "empathy_api_curve": empathy_curve, + "advice_jump_api_curve": advice_curve, + "db_turn_rows_per_session": expected_turns * 2, }, }