docs(scheduler-core): mark task 12.5 complete with fresh verification evidence

Task 12.5 (REPL live-operator-testing fixes) was implemented and its bugs
fixed in an earlier commit, but the tasks.md checkbox was never flipped and
carried no _Verified: line, unlike every other completed task in this spec.
Ran /kiro-verify-completion against it with fresh evidence rather than
trusting the earlier self-report: fresh build+full suite (41/42, only the
pre-existing unrelated bug-1560 failing), a live subprocess smoke test of
the real xce_scheduler binary for all five amendment gaps (including a
hand-built .replay fixture with resource data to close the one gap the
first pass left unit-tested-only), and direct source inspection of each
fix. All five confirmed correct; checkbox flipped, _Verified: line added.
This commit is contained in:
Rongsong Shen 2026-08-19 11:01:04 +00:00
parent 1bc65d2c47
commit aa42752d35
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
2 changed files with 3 additions and 2 deletions

View file

@ -1,7 +1,7 @@
{
"feature_name": "scheduler-core",
"created_at": "2026-07-27T00:00:00Z",
"updated_at": "2026-08-07T00:00:00Z",
"updated_at": "2026-08-19T00:00:00Z",
"language": "en",
"phase": "implementation-complete",
"parent_spec": "scheduler-framework",

View file

@ -389,12 +389,13 @@
- _Depends: 12.2, 12.3_
- _Verified: 2026-08-07 — TEST-ONLY task, no new production code. New test_repl_equivalence.c (683 lines) runs the SAME sched_sim_driver_run() (sim_loop.c) against ONE hand-built `.replay` fixture (two queues at different priorities "high"=5/"normal"=1, four jobs split across THREE ReplaySession boundaries) twice: once in batch mode (interactive=false, straight through), once REPL-driven (interactive=true, stdin freopen()'d from a scripted "step 1\ncontinue\n" -- exactly 2 lines, sufficient and safe regardless of session count since CONTINUE mode never re-reads stdin once entered, avoiding the readline()-EOF-triggers-exit(0) trap). This is a DIFFERENT comparison than task 11.6's test_sim_equivalence.c (which compares normal-mode driver vs simulation driver) -- here both sides are the identical simulation driver, differing only in `sim->interactive`. Both runs set `sched_sim_args_t.output_path` directly (confirmed unconditional on `interactive` by reading sim.c's `args->output_path != NULL` gate), so both write a full `.replay`-format decision stream to their own file with no `set output` REPL command needed. Since the fixture has THREE session boundaries (not task 11.6's one), decoding uses a new decode_all_sessions() that scans the whole output file structurally via sim.c's shared `msg_root_has_shape()` (ReplaySession's distinct (1,2) word/pointer-count shape) rather than a fixed message-skip count. Comparator reuses sim_verify.c's leaf-level structural comparators (`sim_verify_job_alloc_eq()`/`sim_verify_job_preason_eq()`, both `static` but visible via white-box #include) through a duplicated `replay_decision_content_eq()`, same technique test_sim_equivalence.c's own function of that name establishes. Non-tautology guards: session 1 asserted to have EXACTLY 2 decisions (an unambiguous floor -- only 2 jobs could possibly be pending that early), job 501 independently pinned as present in session 1's batch-side content, total batch decisions asserted >= 4, and every decision's type independently pinned as PEND (matching sim_picker_thread_fn()'s documented DISPATCH gap) BEFORE the cross-run equality check -- so a buggy always-`return 1` comparator could not pass silently. Observed (not hand-predicted) that a PEND'd job persists as a picker candidate into later sessions (session 1: jobs 501/502 -> 2 decisions; session 2: 501/503/502 -> 3; session 3: 501/503/502/504 -> 4; total 9 on both sides), confirming the fixture is genuinely non-trivial without needing a fragile hardcoded per-session prediction. Synthetic RED-phase probe: analysis first showed that defeating `repl_should_pause()` (task 12.1's own already-verified probe target) would NOT turn this test red, because that only changes *when* stdin is read/control returns, never *what* gets processed -- every session still eventually completes regardless of pause timing, and this file's own CONTINUE-is-sticky script design tolerates any pause schedule. The correct probe for THIS invariant ("never alters ... what events are processed") had to touch content, and only under `sim->interactive`: temporarily added one line to `xce_repl_on_event()` (repl_break.c) -- which takes a non-const `xce_core_event_t*` and fires (via repl.h's `sim->interactive`-gated wrapper) strictly before an event joins the batch `xce_core_push_events()` later applies -- corrupting a JOBS_PUSH job's jobid (`+= 1000000`) whenever interactive. Rebuilt, ran the full scheduler suite: exactly 4/37 failed (this new test plus three pre-existing REPL tests that also exercise JOBS_PUSH under interactive mode -- sched_repl_execution_control_test, sched_repl_snapshot_params_test, sched_repl_breakpoints_inspection_test -- all correctly detecting the same real divergence), all 33 others stayed green. This test's own failure output: "REPL step/continue-to-completion must produce a byte-identical decision to batch mode at this session and position" (jobid 501 on the batch side vs 1000501 on the REPL side, directly visible in the two runs' printed PEND lines). Reverted (diff-confirmed byte-identical to the pre-probe file), rebuilt, reconfirmed 37/37 scheduler suite (was 36/36), whole-project build clean.
- [ ] 12.5 REPL live-operator-testing fixes (Requirement 5.22 amendment)
- [x] 12.5 REPL live-operator-testing fixes (Requirement 5.22 amendment)
- Fix the five gaps a live operator session surfaced (see requirements.md's AC 22 "Amendment (2026-08-19)" for the full rationale on each): (1) `continue` reaching EOF with no breakpoint hit re-enters the REPL instead of exiting the process; (2) `step`/`continue` issued after replay is already complete re-prompt with a message instead of being treated as "hand control to a driver loop"; (3) `step`/`continue` echo each input event (not just decisions) as it is processed, in real event/decision order; (4) `info resource <name>|all` reports resource definition metadata restricted to `XCE_RESF_GLOBAL`/`XCE_RESF_SHARED` resources, reading the shared value from `core->sharedInst` instead of aggregating host-based resources across every worker; (5) `repl_split_tokens()` strips one matching pair of surrounding quote characters from each token.
- Observable: `--sim --interactive` against a replay file with no breakpoints set, driven by `continue`, stays at the `(sim) ` prompt after "[sim] replay complete" instead of the process exiting -- `info summary`/`info job`/etc. still work at that point, and only `quit` (or stdin EOF) ends the process; a `step` while events are pending prints each event's own one-line summary before that session's decisions; `info resource all` lists only global/shared resources with metadata fields, never a host-based resource's fabricated total/available; `info job "<jobid>"` (quoted) parses identically to the unquoted form.
- _Requirements: 5.22_
- _Depends: 12.4_
- _Bugs: bug-1593 (info resource host-vs-shared), bug-1594 (continue/no-quit exit), bug-1595 (events not echoed in step/continue), bug-1596 (quoted REPL argument parsing)_
- _Verified: 2026-08-19 — Independently re-verified via `/kiro-verify-completion` (fresh evidence, not a prior self-report) across three layers. **(1) Fresh build + full suite**: `xce-build.sh scheduler asan --incremental` compiled clean; scheduler meson suite 41/42 (the one failure, `test_recordstart_symlink_escape_replies_error`, is the pre-existing unrelated bug-1560). Every task-12.5 unit test confirmed PASS by exact name in the fresh testlog: `test_continue_with_no_breakpoints_stays_alive_after_replay_complete`, `test_continue_after_replay_complete_reprompts_instead_of_exiting`, `test_step_echoes_events_before_session_decisions`, `test_info_resource_all_lists_only_global_shared_resources`, `test_info_resource_named_lookup_reports_host_based_note`, `test_info_resource_reports_string_value`, `test_info_job_accepts_quoted_jobid_argument`. **(2) Live subprocess smoke test of the real `xce_scheduler` binary** (fork/exec, real stdin/stdout, not the compiled-in test harness) for all five gaps: gaps 1/2 confirmed via a no-breakpoint replay driven by `continue`/`step` past completion -- process stays at the prompt, `info summary` still answers, `quit` exits 0; gap 3 confirmed via a fixture with `QUEUE_UPDATE`/`JOB_PUSH`/two `JOB_STATE_CHANGE` events -- all four event lines printed before `[sim] replay complete`, in file order; gap 5 confirmed via `info job <id>` issued unquoted, double-quoted, and single-quoted against a real pushed job -- byte-identical output all three ways; gap 4 confirmed via a hand-built `.replay` fixture (`RESOURCES_PUSH` defining a `XCE_RESF_SHARED` resource `licenses` and a host-based resource `mem`, `RESVALS_FULL` giving `licenses=8.0`) -- real captured output: `info resource licenses` → metadata + `value=8.00` read from `core->sharedInst`; `info resource mem` → metadata + "host-based resource -- see 'info worker <name>' for per-host values", no fabricated value; `info resource all` → lists `licenses` only, never `mem`. **(3) Direct source inspection** confirmed all five fixes present and correct in current on-disk code: `xce_repl_on_replay_complete()`/`repl_dispatch()`'s `replay_complete` guard (repl.c), `repl_print_event_summary()` called before the breakpoint check in `xce_repl_on_event()` (repl_break.c), the GLOBAL/SHARED filter + `sharedInst` read in `repl_info_resource_one()` (repl_info.c), and the single-pair quote-strip in `repl_split_tokens()` (repl.c). First verification pass returned NOT_VERIFIED solely because this checkbox/line hadn't been written yet and one live check (gap 4) was still test-only; both closed by this pass.
- [x] 13. Run full cross-phase HA soak regression
- Run sequential and chaotic HA soak rounds against the complete feature (all three phases integrated), confirming zero job loss, divergence, or liveness stall attributable to this feature across the full run