"""C2 task → Simulation output mapping. apply_task_to_simulation() writes task output into the simulation's execution_result field and marks the task as mapping_applied=True so that the operation is idempotent (safe to call multiple times for the same task). Caller is responsible for committing the session. """ from __future__ import annotations from datetime import UTC, datetime from backend.app.models.c2_task import C2Task from backend.app.models.simulation import Simulation def apply_task_to_simulation(task: C2Task, simulation: Simulation) -> None: """Write task output into simulation.execution_result (append, newline-separated). No-op if task.mapping_applied is already True or task.output is empty. Marks task.mapping_applied = True on completion. """ if task.mapping_applied: return output = (task.output or "").strip() if not output: task.mapping_applied = True return existing = (simulation.execution_result or "").rstrip("\n") if existing: simulation.execution_result = existing + "\n" + output else: simulation.execution_result = output simulation.updated_at = datetime.now(UTC) task.mapping_applied = True