# Requirements Document ## Project Description (Input) **Who has the problem:** operators of an XCE cluster, through the load on the controller and its HA standbys. Every pend-reason push becomes a durable, Raft-replicated log entry. **Current situation:** the scheduler publishes every PEND decision in every scheduling session. `xce_sched_driver_on_decision()` (`src/scheduler/src/driver.c:914-919`) wraps the decision and calls `sched_publish_pend_reason()` (`scheduler.c:1913`) without comparing it with what was pushed before. On the controller each push goes through `set_preason()` (`src/controller/job.c`) and `persist_job_hook_fun`'s `HOOK_DETAIL_SETPREASON` arm, which appends a pend-reason WAL record (`src/include/wal_types.h` ~235-265, bug-1692) that is replicated to the standbys. A job that stays pending for hours with the same reason therefore costs one network push plus one durable, replicated WAL write per session, multiplied by every pending job. **What should change:** when a job's pend reason in the current session is identical to the one last successfully pushed for it (full structural match, libxce `job_preason_eq()`, `preason.h`), the scheduler skips the push. Only real changes reach the controller. Questions to settle in requirements: - **Baseline:** the last reason the controller *accepted* for the job, not merely the last one computed. A failed or retried push must not update it. - **Losing the baseline:** after a scheduler restart or failover, or a controller failover or resync, the baseline starts empty, so every pending job is pushed once. - **Controller-side clears:** `do_clr_preason()` (dispatch, requeue, other state changes) must invalidate the baseline so the next PEND is pushed even if it matches the old reason. - **Memory:** cost per pending job — keep a deep copy (exact compare) or a hash (cheaper, tiny collision risk). - **Where the baseline lives:** on the scheduler's job object, or in the driver. - **Simulator and replay:** the decision stream, the decision trace and `--sim-verify` must still see every PEND decision; only the publish to the controller is skipped. - **Observability:** count skipped pushes (log or stats). - **Defense in depth (optional):** a controller-side guard that skips the WAL append when the incoming reason equals the stored one. Related: bug-1932 (session-level unsatisfiable-request cache, which skips repeated computation within one session), bug-1927 (pend reasons recorded once per job), spec `libxce-alloc-preason-equality` (`job_preason_eq`). Status: initialized only; requirements to be discussed with the user before `/kiro-spec-requirements`. ## Requirements