"""Steps for TDD bug-capture scenario #989. This scenario intentionally fails until the bugfix branch for #989 adds corruption-specific handling around automation profile JSON decoding. """ from __future__ import annotations import json from datetime import UTC, datetime from typing import Any from behave import given, then, when from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from cleveragents.infrastructure.database.models import ( AutomationProfileModel, Base, ) from cleveragents.infrastructure.database.repositories import ( AutomationProfileRepository, ) def _now_iso() -> str: return datetime.now(UTC).isoformat() @given("an automation profile repository row with corrupt safety_json for bug 989") def step_given_corrupt_safety_json_row(context: Any) -> None: """Persist a row that reproduces the malformed JSON decode path in _to_domain.""" engine = create_engine("sqlite+pysqlite:///:memory:", future=True) Base.metadata.create_all(bind=engine) factory = sessionmaker(bind=engine, expire_on_commit=False, future=True) now_iso = _now_iso() with factory() as session: session.add( AutomationProfileModel( name="bug-989-corrupt-json", description="Corrupt JSON regression fixture", schema_version="1.0", auto_strategize=0.0, auto_execute=0.0, auto_apply=0.0, auto_decisions_strategize=0.0, auto_decisions_execute=0.0, auto_validation_fix=0.0, auto_strategy_revision=0.0, auto_reversion_from_apply=0.0, auto_child_plans=0.0, auto_retry_transient=0.0, auto_checkpoint_restore=0.0, require_sandbox=True, require_checkpoints=True, allow_unsafe_tools=False, # Deliberately malformed JSON (missing closing brace) safety_json='{"require_sandbox": true', guards_json=None, created_at=now_iso, updated_at=now_iso, ) ) session.commit() context.tdd_989_repo = AutomationProfileRepository(factory) context.tdd_989_error = None @when("the corrupt automation profile is fetched by name for bug 989") def step_when_fetch_corrupt_profile(context: Any) -> None: """Execute repository get path that currently leaks JSONDecodeError.""" repo: AutomationProfileRepository = context.tdd_989_repo try: repo.get_by_name("bug-989-corrupt-json") except Exception as exc: context.tdd_989_error = exc @then( "a corruption-specific domain error should be raised instead of JSONDecodeError for bug 989" ) def step_then_domain_specific_error(context: Any) -> None: """Assert expected post-fix behavior (fails today while bug exists).""" err = context.tdd_989_error assert err is not None, ( "Expected a corruption-specific domain error, but no error was raised" ) assert not isinstance(err, json.JSONDecodeError), ( "Expected a domain-specific corruption error, " f"but raw JSONDecodeError leaked: {err}" ) name_or_message = f"{type(err).__name__} {err}".lower() assert "corrupt" in name_or_message, ( "Expected corruption-specific error semantics (type/message containing 'corrupt'), " f"got {type(err).__name__}: {err}" )