--- id: "bug-1595" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "scheduler" severity: "unknown" timestamp: "2026-08-19T08:00:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/scheduler/src/repl_break.c (xce_repl_on_event)"] tags: ["scheduler", "repl", "step", "continue", "event-visibility", "ux"] related: [] legacy: true --- # bug-1595: User-reported: in each `step`, it would be better to show the decisions/events that occur in the… ## Description User-reported: in each `step`, it would be better to show the decisions/events that occur in the current session in the sequence they actually occur -- currently only decisions are printed, input events (JOB_PUSH, JOB_STATE_CHANGE, WORKERS_PUSH, etc.) are completely silent unless a breakpoint happens to match one. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause sim_loop.c already calls xce_repl_check_event()/xce_repl_on_event() for every decoded ReplayEvent, in stream order, strictly before it joins the batch xce_core_push_events() later applies -- but xce_repl_on_event() (repl_break.c) only ever prints anything when a breakpoint matches; there is no unconditional per-event echo. sim_print_decision() (sim_loop.c), by contrast, IS called unconditionally for every drained decision. Net effect: an operator using `step`/`continue` without breakpoints sees decisions appear with no visible cause -- the events that produced them (a job arriving, a job's state changing, a worker reporting in) are invisible. ## Fix Fixed as part of task 12.5. xce_repl_on_event() (repl_break.c) now unconditionally prints a one-line human-readable summary of every event before running the (unchanged) breakpoint-match check -- e.g. "[sim] event: JOB_PUSH njobs=2 jobids=[, ]", "[sim] event: JOB_STATE_CHANGE jobid= state=RUN", "[sim] event: WORKERS_PUSH nworkers=1 names=[worker-1]", one line per xce_core_event_type_t kind. Since xce_repl_on_event() is only ever invoked when sim->interactive (via repl.h's existing gate), this adds zero output to batch `--sim` mode. repl_job_state_name() (repl_info.c) was made non-static and declared in repl_internal.h so both repl_info.c's `info job` and repl_break.c's new event summary render the same state name for JOB_STATE_CHANGE. Printed order is now event(s) (as decoded) -> BEGIN_ROUND -> decision(s) (as drained), matching sim_loop.c's actual processing order. New tests in test_repl_breakpoints_inspection.c step through a fixture with a JOBS_PUSH and a JOB_STATE_CHANGE event and assert both event summary lines appear, in order, before the resulting decision line. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._