import logging
from qitos.engine.hooks import EngineHook, HookContext
from qitos.engine.states import RuntimePhase
logger = logging.getLogger("qitos.lifecycle")
class LifecycleRecorderHook(EngineHook):
"""Records every engine lifecycle event into a structured log."""
def on_run_start(self, task, state, engine):
logger.info("run_start | task=%s", task[:80])
def on_before_step(self, ctx: HookContext, engine):
logger.info("before_step | step=%d phase=%s", ctx.step_id, ctx.phase.value)
def on_after_step(self, ctx: HookContext, engine):
logger.info("after_step | step=%d", ctx.step_id)
def on_before_decide(self, ctx: HookContext, engine):
logger.info("before_decide | step=%d", ctx.step_id)
def on_after_decide(self, ctx: HookContext, engine):
decision = ctx.decision
logger.info("after_decide | step=%d decision=%s", ctx.step_id, type(decision).__name__)
def on_before_act(self, ctx: HookContext, engine):
logger.info("before_act | step=%d", ctx.step_id)
def on_after_act(self, ctx: HookContext, engine):
logger.info("after_act | step=%d results=%d", ctx.step_id, len(ctx.action_results))
def on_before_critic(self, ctx: HookContext, engine):
logger.info("before_critic | step=%d", ctx.step_id)
def on_after_critic(self, ctx: HookContext, engine):
logger.info("after_critic | step=%d", ctx.step_id)
def on_before_reduce(self, ctx: HookContext, engine):
logger.info("before_reduce | step=%d", ctx.step_id)
def on_after_reduce(self, ctx: HookContext, engine):
logger.info("after_reduce | step=%d", ctx.step_id)
def on_before_check_stop(self, ctx: HookContext, engine):
logger.info("before_check_stop | step=%d", ctx.step_id)
def on_after_check_stop(self, ctx: HookContext, engine):
logger.info("after_check_stop | step=%d stop_reason=%s", ctx.step_id, ctx.stop_reason)
def on_recover(self, ctx: HookContext, engine):
logger.warning("recover | step=%d error=%s", ctx.step_id, ctx.error)
def on_run_end(self, result, engine):
logger.info("run_end | steps=%d", result.state.current_step if hasattr(result, 'state') else '?')