diff --git a/.kiro/specs/scheduler-core/tasks.md b/.kiro/specs/scheduler-core/tasks.md index a4a3df38..da8a759c 100644 --- a/.kiro/specs/scheduler-core/tasks.md +++ b/.kiro/specs/scheduler-core/tasks.md @@ -31,6 +31,7 @@ - Observable: after `init()`, the picker holds an empty private candidate set; after `fini()`, all picker-owned memory is released (verified under a leak-checked test run) - _Requirements: 3.1, 3.3_ - _Depends: 1.1, 1.2_ + - _Verified: 2026-08-03 (commit `f7921b96`) — backfilled 2026-08-07 by `/kiro-validate-impl` (this task and 2.2-2.6 were implemented and reviewed at the time but never got a `_Verified:` line). New `src/scheduler/src/plugins/builtin_fcfs.c` (not a `fcfs.c` rewrite — see design.md's BuiltinFcfsPicker notes and Implementation Notes below for why): `fcfs_plugin_data_t` holds `ordq_t queues` plus per-queue `ordq_t pendJobs`, allocated in `init()`/freed in `fini()`; never queries `sched->queues`/`sched->jobs`._ - [x] 2.2 Implement builtin_fcfs state-change hooks - `on_queue_update`: upsert a queue into the picker's ordered queue list, keyed by descending priority @@ -40,6 +41,7 @@ - Observable: feeding a sequence of these hooks directly (no live core) produces a candidate set whose order matches the documented ordering rule, verifiable by a direct hook-driven test - _Requirements: 3.2_ - _Depends: 2.1_ + - _Verified: 2026-08-03 (commit `b7214ebe`) — backfilled 2026-08-07. `on_queue_update`/`on_job_push`/`on_job_state_change`/`on_job_update` implemented on `fcfs_plugin_data_t`'s `ordq_t` structures, ordering `(queue priority desc, job priority desc, queue_time asc)`; `test_picker_fcfs.c` feeds the hooks directly (no live core) and asserts the resulting order._ - [x] 2.3 Implement builtin_fcfs session and post-allocation hooks - `begin_session`: reset the iteration cursor to the head of the ordered queue list @@ -50,6 +52,7 @@ - Observable: a full begin_session → repeated next_job → end_session cycle against a fixed candidate set returns jobs in `(queue priority desc, job priority desc, queue_time asc)` order and returns NULL exactly once all candidates are exhausted - _Requirements: 3.2, 3.4, 3.6_ - _Depends: 2.2_ + - _Verified: 2026-08-03 (commit `fcb32a8b`) — backfilled 2026-08-07. `begin_session`/`next_job`/`end_session`/`on_dispatch`/`on_pend` implemented per plan; this task's own review found the real cross-thread race later closed by 2.4 (picker thread's `next_job()` vs allocator thread's `on_dispatch`/`on_pend` racing unsynchronized `fcfs_plugin_data_t` state) — see `## Implementation Notes` below, "Task 2.3's review found a real concurrency gap for task 2.4 to close."_ - [x] 2.4 Wire builtin_fcfs as the registered default and remove the hardcoded picker string - Auto-register `builtin_fcfs` at scheduler startup under the name `"builtin_fcfs"` and set it as the default picker plugin @@ -59,12 +62,14 @@ - Observable: starting the scheduler with no picker config uses `builtin_fcfs` automatically; starting it with an unregistered picker name fails startup with a clear error instead of silently falling back - _Requirements: 1.3, 1.4, 1.6, 2.5, 3.1, 3.5_ - _Depends: 2.3, 1.3_ + - _Verified: 2026-08-03 (commit `7ee9a16f`) — backfilled 2026-08-07. `builtin_fcfs` registered and defaulted (`schedobj.c:364`); registered "alongside the untouched legacy `xce_sched_fcfs`" (`scheduler.c:466`'s own comment) rather than replacing `plugins/fcfs.c` in place — `fcfs.c` stays as task 1.2's `job_elect_fn` compat-wrapper exercise target. `sched_job_picker()` (`scheduler.c`) branches `job_elect_fn != NULL` (legacy, self-contained loop) vs `NULL` (native picker, generic per-session loop). Closed this task's own review-found race (see 2.3's note) with `fcfs_plugin_data_t.lock` (`mylock_t`), held by exactly 7 hooks (`on_queue_update`, `on_job_push`, `on_job_state_change`, `on_job_update`, `begin_session`, `next_job`, `on_dispatch`) — `on_pend`/`end_session`/`init`/`fini` correctly excluded (never touch the locked state)._ - [x] 2.5 Remove ordering logic from the core scheduling loop - The core loop calls only `picker->next_job()` to obtain the next schedulable job — no project/queue/job iteration or ordering logic remains in the loop itself - Observable: a code-level check confirms the scheduling loop function contains no direct queue/job traversal — all selection reads happen through the picker interface - _Requirements: 1.1, 1.7_ - _Depends: 2.4_ + - _Verified: 2026-08-03 (commit `9d91d470`) — backfilled 2026-08-07. Confirmed via source read: `sched_job_picker()`'s native-picker branch calls only `picker_iface->next_job()` to obtain the next job — no queue/job traversal or ordering logic in the loop itself; a code-level guard test asserts this._ - [x] 2.6 Picker regression tests and data-sharing invariant checks - Assert `builtin_fcfs`'s `next_job()` ordering matches today's pre-change FCFS ordering exactly, given identical queue/job state @@ -73,6 +78,7 @@ - Observable: the regression suite passes with the documented ordering rule as its oracle, and a grep-based or code-review check confirms no new `calloc(sizeof(...pendreason...))` call site was introduced - _Requirements: 4.1, 4.2, 6.1, 6.2, 6.3, 6.4_ - _Depends: 2.5_ + - _Verified: 2026-08-03 (commit `604a5649`) — backfilled 2026-08-07. `test_picker_pendreason_factory_audit.c` and the picker regression suite confirm ordering-equivalence against legacy `fcfs_elect_job` and the pend-reason/resreq data-sharing invariants (Req 6.1-6.4); part of the 41/41 green suite reconfirmed by this validation pass._ - [x] 3. Run Phase 1 HA soak regression - Run sequential and chaotic HA failover soak rounds against a cluster running the new picker architecture