Persistent log of the resource-design discussion: the user's proposals (generic supply map incl. provisioned supply; a resource provider proxy between the controller and upstream providers; datasets in the map with staging as data provisioning) with analysis, the user's 2026-10-11 input (duration/decay must-have but future; RBAC in the apiserver, discuss later; OCI containers via application profiles; CSI compatibility preferred; GPU/topology scheduler-first and extensible), the open R1-R9/P1-P9 items and new questions N1-N4, C3. resource-model.md, the provisioner research, roadmap and CLAUDE.md point at it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
88 KiB
Roadmap
Overview
XCE is in the persistence + HA transformation (branch persistent_ha). Governing model: Raft consensus + CP (see product.md key decisions). Active spec work is tracked per-spec in .kiro/specs/; this file is the single consolidated future-work document — the forward-looking queue, long-deferred items, and hardening backlog. It absorbs the former src/docs/FUTURE_WORK.md (2026-05-12, config-replication-design review), which now redirects here.
Long-term direction (user, 2026-10-10): XCE is heading toward a unified platform for applications such as LLM training and deployment (serving), not only classic HPC batch. Features are therefore drawn from IBM LSF and Kubernetes: consumables, rusage, elim, licenses and application profiles from LSF; extended resources, device plugins, CSI volumes, Dynamic Resource Allocation claims and services with replicas from Kubernetes. Designs for resources, providers, job lifecycle and APIs should serve both batch jobs and long-running services. Resource vocabulary: resource-model.md.
In Flight
scheduler-framework — NEW 2026-07-06 (DECOMPOSED 2026-07-27 into three child specs (/kiro-discovery). Iterator-driven allocation architecture: lazy plan iterator + host iterator, combinatorial parallel job allocation, configurable job picker, session-level unsatisfiable resreq cache. Brief:.kiro/specs/scheduler-framework/brief.md..kiro/specs/scheduler-framework/spec.jsonchild_specs): scheduler-core — core/driver separation, pluggable job picker interface, and simulation mode; IMPLEMENTATION-COMPLETE, GO/NO-GO validation 2026-08-07/08 (2 non-blocking follow-ups: (a) tlog logging-integration built but never activated, (b)fcfs.c/builtin_fcfs.cdoc+traceability gap — design.md text was corrected same-day, but tasks 2.1-2.6 intasks.mdstill carry no_Verified:lines, still open), 45/45 sub-tasks done as of that validation. Updated 2026-08-19: task 12.5 (REPL live-operator-testing fixes, Req 5.22 amendment) was added after that validation from live-operator testing gaps (bug-1593/1594/1595/1596) and is now also done, independently re-verified with fresh evidence (/kiro-verify-completion) — seetasks.md's own_Verified:line on that task; this closes follow-up (a) too (the tlog gap is now activated — seedesign.md'sSchedulerCorecomponent andresearch.md). A separate retrospective design review (2026-08-19, unrelated to the original 2026-08-07 follow-ups) additionally found and fixed anOPCode_schedAdminblocking-wait admission gap and extendedcore.c's isolation-boundary test coverage to itscore_events.c/core_session.c/core_clock.csiblings — seeresearch.md's "SUPERSEDES" notes. scheduler-allocation — lazy iterator-driven allocation architecture, parallel job support, session-level unsatisfiable resreq cache; requirements generated,blocked_on: [scheduler-core]— now unblocked. scheduler-preemption — SIGSTP-based victim selection + controller→worker pipeline; requirements generated,blocked_on: [scheduler-core]— now unblocked. The parentscheduler-frameworkspec is retained only for discovery-context provenance and is no longer in flight itself. Next:/kiro-spec-design scheduler-allocationand/kiro-spec-design scheduler-preemption.ha-consistency-invariants — UMBRELLA CONTRACT (requirements + design + research approved/complete). Implementation decomposed 2026-06-11 into the four sub-specs below; the umbrella generates NO tasks itself. Each sub-spec brief references the umbrella docs as authoritative.COMPLETE 2026-07-13 — all four sub-specs (ha-commit-engine, ha-commit-barrier-rollout, ha-single-leader-role, ha-convergence-recovery) implemented; Criterion 2.9 (Facts-Apply invariant) satisfied via raft-apply-decoupling. No longer in flight.ha-wal-replication — implemented except task 5.4 (live 3-node integration test; needstask 5.4 CLOSED 2026-07-18 via/xce-deploy-hacluster); sub-spec 4's E2E extends it/kiro-validate-impl's live 10-round sequential soak (972/972 tests, zero loss). Spec is GO, no longer in flight.libxce-failover — CLIENT-SIDE transparent controller failover (requirements generated 2026-06-16). Wires all libxce production request paths through the (already-built-but-orphaned)IMPLEMENTED, validate-impl GO 2026-07-18 (all 19 tasks were done since 2026-06-18; thexce_request_with_retry()primitive + adds multi-master rotation; classifies on the real controller status taxonomyE_XCE_REDIRECT/E_XCE_NOMASTER/E_XCE_NOT_READY/E_XCE_STANDBY(errnox.h:22-25); bounded retry → distinct cluster-not-ready (no more opaque EINVAL); includes one small controller change so redirect replies carry the primary host/port (schema fields already exist,controller.capnp:598-599, just unpopulated injoin.c). Verified E2E viaxce_test(the original reproduction). Closes the integration gap left byha-config-bootstrapReq 7 (tasks 10/10.1/10.2 shipped only the standalone primitive). See bug-608. Dependencies: ha-config-bootstrap (primitive + error codes), ha-commit-barrier-rollout (write idempotency makes write-retry safe).ready_for_implementationflag was just never flipped — administrative staleness, not a real block). No longer in flight.component-failover-adoption(backlog, below) is the next layer on top of this.
Raft TLA+ Conformance — raft-library enhancement series (NEW 2026-06-21)
Goal: evolve the election-only src/lib/raft/raft.{c,h} into a STRICT implementation of raft/raft.tla (Ongaro canonical) covering the log + commit half, keeping the pure callback-driven design so it stays independently verifiable via the deterministic simulator (raft_sim.c) against the TLA+ invariants (Election Safety, Log Matching, Leader Completeness, State Machine Safety). Motivation: bug-851 — the log protocol is currently hand-rolled across persist.c/repl.c/ha.c/ha_convergence.c and violates the TLA+ log invariants. Gap analysis (six gaps G1–G6): .kiro/specs/ha-term-safety/TLA-gap-analysis.md. Implement in dependency order; each spec lands with simulator coverage. The library core stays pure/synchronous/deterministic — all I/O (async vtask, fan-out replication, the sync commit barrier, snapshot transport) lives in controller-side callback adapters. Preserve as policy (do NOT canonicalize away): PreVote, priority leadership, synchronous commit-barrier + persist-before-ACK durability, "controller never self-terminates".
- raft-log-replication — (specs generated + auto-approved 2026-06-21: 8 reqs, 24 sub-tasks, cross-spec review PASSED. Ready for /kiro-impl.) Extend the library to OWN the replicated log. TLA+ actions:
ClientRequest,AppendEntries,HandleAppendEntriesRequest,UpdateTerm-on-AppendEntries. Per-entry term in the library log model (closes G1);AppendEntrieslogOk=prevLogTermmatch (G2); conflict branch deletes the divergent(term,lsn)suffix (G3); ANY higher-term RPC incl. AppendEntries/heartbeat advancescurrentTermand steps down (G5). New pure callbacks:on_persist_entry,on_get_entry_term(lsn),on_send_append_entries(peer, prevLogIdx, prevLogTerm, entries, commitIdx),on_truncate_from(lsn); controller adapters implement them over the existing WAL/repl transport. Simulator: drive AppendEntries across partitions/restarts, assert Log Matching. Dependencies: raft-library (election core). Closes bug-851 G1/G2/G3/G5. - raft-commit-safety — (specs generated + auto-approved 2026-06-21: 6 reqs, 18 sub-tasks, cross-spec review PASSED.)
AdvanceCommitIndexwith the Figure-8 current-term rule (commitMax(agreeIndexes)only iflog[Max].term == currentTerm) (G4);RequestVote/PreVote freshness becomes(lastLogTerm, lastLogIndex)instead of LSN-only (G6). New callbackon_commit_advanced(lsn)feeds the existing synchronous commit barrier / durability (persist-before-ACK preserved as policy). Simulator: assert Leader Completeness. Dependencies: raft-log-replication. Closes bug-851 G4/G6. - raft-sim-conformance — (specs generated + auto-approved 2026-06-21: 8 reqs, 23 sub-tasks, cross-spec review PASSED.) Extend
raft_sim.cinto a conformance/verification harness driving the library throughraft.tla-action-equivalent transitions (randomized + targeted) and asserting the four Raft safety invariants; optionally trace-check against TLC output ofraft.tla. The "use the verified spec to help" payoff: a regression oracle for the consensus core. Dependencies: raft-log-replication, raft-commit-safety. IMPLEMENTED, validate-impl GO 2026-07-18 (23/23 tasks; 293/293 lib tests, zero ASAN findings; this is the spec this worktree/branch —raft_tla— is named for).
ha-term-safety (
.kiro/specs/ha-term-safety/) is the XCE-side INTEGRATION + REGRESSION umbrella for this family: it wires the controller WAL / commit-barrier into the new raft callbacks (thin adapter — protocol delegated to the library), owns the config-change marker (R7 — config changes as(term,lsn)log markers; bytes via the existing out-of-band config-push transport, hash-verified against the marker), and holds the live bug-851 chaotic-failover regression. Its protocol invariants R1–R6 are realized by the library specs above (not re-implemented in the controller). Scope: R1–R7 only. The former R8 (config-upgrade full-snapshot consistency, bug-857) was descoped 2026-06-21 to the independentconfig-upgrade-snapshotspec (below), because it requires entity-bearing snapshots that do not exist yet. IMPLEMENTED, validate-impl GO 2026-07-17 (20/20 tasks; closed bug-1445, a first-boot promotion-check race with job-array-single-wal-record's Live Apply Resource Fence, as an out-of-boundary follow-up fix).
raft-adapter-conformance (
.kiro/specs/raft-adapter-conformance/) — NEW 2026-07-29, sibling audit to the library-side conformance work above: a systematic, action-by-action pass over the controller's Raft adapter (the wire-level send/receive/reply code inha.c/repl.c/config_repl.c) againstraft.tla's actions — distinct fromraft-sim-conformance's in-process library harness. Motivated by a live-soak finding that the controller'sWalAckReplyconstructor hardcoded success (no failing reply ever reached the primary) plus a standby catch-up streaming-range self-deadlock, both already fixed (bug-1479) before this spec was seeded. This pass found and fixed two more instances of the same defect class: configuration-push rejects previously sent no reply at all (bug-1480), and a vote/PreVote endpoint failure arriving after connect routed through a legacy tally path instead of the production one (extending bug-1423's connect-time fix to that remaining timing window). Also records, as a single explicit decision, whichAppendEntriesmechanism is production-authoritative (repl_broadcast+ha_stream_wal_to_standby; the per-peer index-drivenraft_send_append_entriesstays dormant by documented design, not oversight). Requirements/design/tasks generated and approved, all 15 leaf tasks (1–7.3) checked;src/controller/CLAUDE.md's Protocol Verification Checklist marks the corresponding invariants "postraft-adapter-conformance, landed 2026-07-29" —spec.jsonphase (tasks-generated) has not been flipped to reflect this, same administrative-staleness pattern seen elsewhere in this doc (cf. the former libxce-failover entry above). Dependencies: raft-log-replication, raft-commit-safety, ha-term-safety, raft-sim-conformance (adjacent/informational — this spec fixes the adapter layer those validate underneath).
Raft Apply-Ordering & Hook Decoupling — NEW 2026-06-24 (/kiro-discovery); IMPLEMENTED — see raft-apply-decoupling below
Goal (historical — achieved): make the controller follow canonical Raft ordering — pre-hooks → raft commit → apply → notify — with the raft protocol step lifted OUT of the notification hook fan-out. At the time this family was opened, persist_job_hook_fun (an AFTER_EVENT hook) performed the WAL append + synchronous majority-commit barrier inline, and create_job() mutated in-memory state BEFORE that commit — the structural root of the bug-795/828/851/1060 divergence family. A failed/timed-out commit did not cleanly revert the optimistic mutation. Decision (user, 2026-06-24): apply-after-commit (canonical) — a single shared apply_committed_entry() seam mutates the state machine only after commit, reused by restart replay so online-apply and replay-apply are identical. Hooks demote to notification-only. Decomposed via Path E (2 new specs + touchpoints), delivered as raft-apply-decoupling (IMPLEMENTED 2026-07-07, see below). Current code reflects the fix: persist_job_hook_fun (persist.c ~6509-6553) now explicitly returns early for WAL_MODE_WAIT entries, with a comment noting job-submit durability is invoked directly by handle_jobsubmit — persist_submit_job_payloads_and_commit(), called strictly before any job object is constructed — never from this hook; create_job() is now defined at job.c:48.
Async-drive prerequisites (surfaced 2026-06-25 by blocking audit; thread-role contract now in ha-async-io.md)
The protocol drive is NOT fully event-driven. Root cause: peer_ctrl_msg_handler runs inline on iomgr instead of dispatching to the vtask pool, and delaymgr (the heartbeat driver) was the documented blocking sink. Corrected thread-role contract is now steering (ha-async-io.md, 2026-06-25; SUPERSEDES "delaymgr for blocking ops = Permitted"). Two separable prerequisites (full evidence: .kiro/specs/raft-apply-decoupling/facts-in-raft.md § Keystone + "Two distinct prerequisites" + P2 offload mechanism):
- P1 — commit-barrier async (the commit drive). Convert
repl_wait_majority_ack()from blockingpthread_cond_timedwait(commit.c:359) to event-drivenresolve(lsn,outcome)on the existing commit engine. Dissolves apply-self-deadlock (B), enables reply continuations (C), removes vtask-pool exhaustion. Owned withinraft-apply-decouplingas its keystone (sequenced before its Phase A). - P2 — drive hardening (the transport/timer drive). Now its own spec
raft-drive-async(brief:.kiro/specs/raft-drive-async/brief.md) — promoted because it threatens liveness independently. See the Specs list below.
Specs (dependency order — Raft Drive & Apply Async family)
- raft-drive-async — IMPLEMENTED, validate-impl GO 2026-07-18 (21/21 tasks; the live sequential soak this validation ran surfaced a real crash, bug-1447 — a same-batch endpoint use-after-free in
io_worker's epoll dispatch loop, exposed by this spec's own faster reconnect cadence, seeha-async-io.md; root-caused, fixed, re-soaked clean, re-validated GO same day). Original description retained below for provenance. (was: START FIRST — threatens failover liveness TODAY) — bring the code into compliance with the correctedha-async-io.mdthread-role contract: dispatchpeer_ctrl_msg_handlerto the vtask pool (root-cause fix); snapshot send + config-push off iomgr → admission-capped slow lane (per-peer dedup + WAL coordination); delaymgr peer connect → bounded non-blocking + offloaded (reusexce_probe_config_tagpattern); add a general non-IO vtask-submit path + admission reservation (extendCOMMIT_WAIT_RESERVED). Verify with a partition (unreachable-not-killed) soak: heartbeats to survivors continue, no spurious election. Likely root of the bug-851 chaotic-failover family. Dependencies: none hard (builds on existing commit engine + vtask + the steering contract);election-iomgr-refactoris completed upstream (providesdelay_task_ms/on_connected/non-blocking vote fan-out) — STANDALONE per 2026-06-25 scope-check (ADJACENT-SAME-AREA: it fixed startup blocking, this fixes runtime drive blocking). Brief + requirements + research + design + tasks done; phase=tasks-generated (tasksapproved: false)./kiro-validate-designGO 2026-06-25 — three review findings folded into design+tasks: (1) deadlock-freedom + LivenessAdmission — the documented invariant reversal (ack/commit_on_ackmoves off iomgr to the vtask pool,commit.c:16) co-locates commit-barrier wakers+waiters; review foundCOMMIT_WAIT_RESERVEDis insufficient because it counts only commit-waits while peer_ctrl also puts vote-grant fsync + config-ack waits on the pool (invisible to it). Fix: generalize the reservation to a pool-level task-class admission in vtaskmgr (VTASK_LIVENESS/LIVE_BLOCK/REQ_BLOCK; liveness never gated;COMMIT_WAIT_RESERVEDfolded in) — new Phase-1 task 1.6 (dormant infra), hard prerequisite of 3.1; task 3.4 is the admission gate. Transient untilraft-apply-decouplingP1 makes the barrier async; (2) WAL-trim cursor-bound guard added to task 3.2 (bug-1147, see Hardening below — moving checkpoint/trim onto a concurrent lane worsens the existing latent trim-vs-cursor race); (3) in-process partition primitive inxce_testas the portable primary for R7 (firewall DROP secondary) so the soak actually runs unprivileged. Next: approve tasks (/kiro-spec-tasks raft-drive-async) →/kiro-impl; ship Phase 1 (bounded connect) first. - raft-apply-decoupling — decouple the raft protocol step from the hook fan-out (item #1); canonical pre-hooks → commit → apply → notify ordering (item #2); single
apply_committed_entry()seam shared by online commit + restart replay; post-restart validation that committed log was correctly applied to materialized state (item #4); requirement + regression tests (item #5). Contains P1 (commit-barrier async) as its keystone. Commands (WAL_MODE_WAIT) apply-after-commit; facts (WAL_MODE_RETAIN) routed through commit-then-apply too — D1 RESOLVED (block-but-durable under quorum loss); formalized asha-consistency-invariantscriterion 2.9. Dependencies: raft-drive-async, raft-log-replication + raft-commit-safety (DONE/implemented), worker-rejoin-resync; coordinate with ha-term-safety. Briefs:.kiro/specs/raft-apply-decoupling/brief.md+facts-in-raft.md. IMPLEMENTED 2026-07-07: 32/32 tasks, validate-impl GO — 79/79 controller_unit_test groups (926 tests) green, live 3-node smoke boot verified, zero blocked tasks. Task 7.2 fixed bug-1416 (boot-time TOCTOU false APPLY_DIVERGENT fence). Task 7.4's own throughput benchmark found and fixed a real O(n²) apply-pump regression (56% throughput drop, superlinear scaling) via a segment-read cache onpersist_t, 2 adversarial review rounds. Residual, non-blocking: design.md has 3 sections not yet reconciled with implementation deviations already self-documented in tasks.md's Implementation Notes (repl.c's plannedrepl_submit_majority_commit()was never built; apply pump wired viacommit_resolve_pending()notha.c'son_commit_advanced; fact hooks collapse to genericHOOK_DETAIL_JOB_UPDATEnot per-type); task 5.3 touchedha.cwithout a formal_Boundary:_exception tag (substantively justified, process-inconsistent only). Two out-of-scope findings flagged for follow-up: an intermittent client hang in the synchronousjobsubpath (resembles but not confirmed as bug-1416's class), andtrim_wal_segments's retention floor has no awareness of the local apply pump's own lag (same family as an already-tracked standby-cursor gap). - worker-rejoin-resync — PROMOTED to spec 2026-08-10 (
/kiro-discovery; brief at.kiro/specs/worker-rejoin-resync/brief.md). Elevated to HARD prereq for the facts half of raft-apply-decoupling 2026-06-25 (was backlog "designated backstop"). Worker re-reports running/finished job state on rejoin so facts lost in a failover window are recovered; re-reports flow through commit-then-apply idempotently (criterion 2.9). Today workers send onlyhostattrson join (bug-396). Scoped narrowly to worker job-execution-fact resync only — apiserver/scheduler resync-on-reconnect is a different data shape (cluster/queue/job list state, not job execution facts) and stays out of scope (see the deferred "lightweight rejoin re-attach" backlog item below, still YAGNI). Dependencies: ha-consistency-invariants (commit barrier + idempotency guards) — both implemented, unblocked. Next:/kiro-spec-requirements worker-rejoin-resync. - job-array-single-wal-record — PROMOTED from backlog 2026-06-24. Persist/replicate/push a job-array submission as ONE Raft record (base spec + index range/count + per-index overrides) committed atomically through a single barrier; expand on apply (online + replay) and on the scheduler side; preserve per-element identity/addressing; idempotent re-apply (item #3). Dependencies: raft-apply-decoupling (HARD — builds on the shared apply seam), ha-commit-engine, ha-commit-barrier-rollout, ha-consistency-invariants. Brief:
.kiro/specs/job-array-single-wal-record/brief.md.
Existing Spec Updates (Raft Apply-Ordering phase)
- raft-sim-conformance — add apply-after-commit regression assertions (item #5): no apply on a failed/uncommitted entry; online-apply ≡ replay-apply for the same committed log; ordering invariant pre-hooks → commit → apply → notify. Revisit with
/kiro-spec-requirements raft-sim-conformanceonce raft-apply-decoupling requirements land. - ha-term-safety — coordinate: raft-apply-decoupling restructures the same controller submit→commit path this umbrella wires. Sequence the apply-decoupling edits against ha-term-safety's adapter work (disjoint-but-adjacent regions) to avoid conflicting refactors.
Direct Implementation Candidates (Raft Apply-Ordering phase)
- xce_test waldump/walcompare/snapdump inspectors (already a Hardening item below) double as the offline evidence for the item #4 restart-validation requirement — wire their nonzero-exit-on-divergence into the decoupling spec's E2E rather than as a separate spec.
Specs (dependency order)
[x]= spec generated (requirements/design/tasks approved, ready for implementation). Implementation tracked via each spec's tasks.md; implement in roadmap order (cross-spec review 2026-06-11: four specs touch ha_dispatch_gate / raft_cb_become_follower in disjoint-but-adjacent regions).
-
ha-commit-engine — commit.c per-LSN majority engine + quorum accounting fixes, wired behind job submit. Dependencies: none. (specs done 2026-06-11; IMPLEMENTED 2026-06-12: 12/12 tasks, validate-impl GO, 467 tests green; deferred follow-ups in its tasks.md §Implementation Notes)
-
ha-commit-barrier-rollout — classification table, commit-first-then-reply sweep, RETAIN facts, config barrier, idempotency guards. Dependencies: ha-commit-engine. (specs done 2026-06-11; IMPLEMENTED 2026-06-13: 16/16 tasks, validate gate GO, 508 controller tests green under ASAN. Fixed bug-447 (key_find found-rc leak — queue/host control was silently unpersisted+unreplicated in production) and bug-396 (worker fact loss on quorum-loss gate rejection); task 5.2 needed one remediation round (wired the missing production config-ACK ingestion — would have bricked multi-member config upgrades — + kept the barrier off the iomgr thread). Logged not-fixed: bug-448 (job_ctrl ref leak), bug-451 (RUSAGE va_list OOB read). Barrier-before-state-removal precondition for ha-single-leader-role satisfied)
-
ha-single-leader-role — promotion no-op + own-term gate, transitional-state (the former fourth role) removal. Dependencies: ha-commit-engine, ha-commit-barrier-rollout (HARD: barrier before state removal). (specs done 2026-06-11: 2 reqs / 7 components / 11 sub-tasks)
-
ha-convergence-recovery — demotion truncate+self-restart, rejoin reconciliation, egress watermark filter, ACK-driven catch-up, quorum logging. Dependencies: ha-commit-engine (E2E additionally needs ha-single-leader-role). (specs done 2026-06-11: 9 reqs / 7 components / 13 sub-tasks)
-
ha-commit-durability — closes bug-661 (acknowledgment did not imply durability; committed jobs lost across failover). Makes acknowledged ⇒ durable on a majority: the primary counts its own copy toward the commit majority only at its durable LSN (
majority_candidate_lockedcaps self atpersist_durable_lsn, not the appended tip);fsync_workerrepurposed timer→demand-driven group-commit flusher (onefdatasyncover pending appends, advancedurable_lsn, wake commit-eval) — absorbs the former "WAL group-commit batching" backlog item (see below); recovery integrity verdict (clean vs corruption-truncated WAL) + durable-backed freshness floor (candidate advertises barepersist_durable_floor, voter floor =max(durable_floor, learned_committed)) + pre-promotion eligibility fence. Establishes the controllers-never-self-terminate invariant: a recovery-truncated/behind member that cannot catch up is a LOUD PERMANENT FENCE (non-promotable, stays alive, keeps retrying — neverexit/abort), self-heals on peer return (seeha-async-io.mdprocess-lifecycle invariant +src/controller/CLAUDE.md). Dependencies: ha-commit-engine (consumes commit-position semantics), ha-wal-replication (standby ACK/catch-up), ha-commit-barrier-rollout (reply gate, unchanged). (specs done 2026-06-18; IMPLEMENTED 2026-06-18: 17/17 tasks (1.1–5.3), validate-impl GO, controller suite 0 failures under ASAN; deterministic ack-before-fdatasync E2E RED→GREEN + rolling-SIGKILL soak zero acked-job loss. Verified by tests + Protocol Verification Checklist, NOT by raft.tla (which assumes a durable log). Fixed bug-760 (adjacenttest_fact_hook_appendraced the async flusher — test made durable-deterministic viapersist_flush). raft.tla durability-model extension deferred unless explicitly opted in.) -
scheduler-allocator-runner — NEW 2026-09-28 (
/kiro-discovery, Path C). The framework ownsjob_alloc_fnthrough a newxce_sched_allocator_iface_t(accepts guard + plan iterator) and a singlesched_allocator_run(); bothmy_alloc()s are deleted (seqjob/parjob), andalloc_iter.hinitis retyped toxce_sched_core_t*. Behaviour must stay identical (bug-1882/1767/1768). Closesissues/new_requirements.mditem 4. Brief:.kiro/specs/scheduler-allocator-runner/brief.md. Dependencies: scheduler-allocation, scheduler-core (both done). IMPLEMENTED 2026-09-30 (11/11 tasks, e2266582..28cff179; validate-impl GO; scheduler ASAN suite 96/96): runner insrc/scheduler/src/alloc_runner.c; decided along the way: the runner clearsalloc_req.hostbefore every candidate so every short host gets pend reasons (both allocators), and fixes bug-1893 (shared reasons were never recorded). Follow-ups: publish pend reasons only when changed; sim-mode parjob allocation parity fixture; bug-1892; bug-1897. -
scheduler-alter-pend-reasons — NEW 2026-09-28 (
/kiro-discovery, Path E). An ALTER-resreq job keeps a pend reason for EVERY alternative instead of only the last (scheduler.c:424FIXME). Wire shape (user decision): additivealternatives @3: List(JobPendReason)onJobPendReason, per-alternative attribution; carried end-to-end through controller job record, WAL preason fact, recordings andjob_preason_eq. Also fixes the confirmedobj->reasonoverwrite leak (scheduler.c:388). Brief:.kiro/specs/scheduler-alter-pend-reasons/brief.md. Dependencies: libxce-alloc-preason-equality (HARD: extends itsjob_preason_eq); sequence after scheduler-allocator-runner (its "no pend-reason content change" rule). -
application-profile — NEW 2026-09-29 (
/kiro-discovery, Job Sandbox Execution initiative, Path D; reshaped fromjob-execution-modeby user direction: execution mode is a job attribute determined by the APPLICATION). Admin-defined named application profiles (LSF-appprecedent) in cluster config: execution mode + options (direct|sandbox, room forcontainer/vm), launch type, env + pre/post exec, resource defaults/limits (extensible). Users pick a profile at submit (--app), cluster default profile otherwise; queues (scheduling policy) and profiles (application config) are orthogonal — neither restricts the other; only profile-marked overridable attributes may be overridden; access by RBAC permission (newapp:use/app:viewwithappdomain type, folded into this spec); apiserver checks profile existence; controller resolves at submit and persists effective values on the job (wire additive, WAL/snapshot field-completeness). apiserver never checks node accounts; worker fails adirectjob with a clear reason if the exec user is missing. Worker capability advertisement + scheduler placement. Brief:.kiro/specs/application-profile/brief.md. Dependencies: none. -
job-sandbox-execution — NEW 2026-09-29 (Job Sandbox Execution). Worker: pluggable execution-backend interface (
directrefactored +systemd-sandbox; non-systemd backends later). Sandbox = existing transient unit +DynamicUserwith fresh per-job name (never the submitter's), ProtectSystem=strict/ProtectHome/PrivateTmp/NoNewPrivileges, Bind(ReadOnly)Paths for job I/O dirs or worker-created temp workspace (handed to the uid via SO_PEERCRED),StandardOutput=file:output, helper auth by unit/cgroup, MANDATORY post-job cleanup/ownership normalization (dynamic uid reuse), systemd ≥ 242 + nss-systemd capability probe; single-node incl. single-node MPI. Viability-checked 2026-09-29. Brief:.kiro/specs/job-sandbox-execution/brief.md. Dependencies: application-profile; remote-task-root fix (Direct-Implementation). -
job-sandbox-multinode — NEW 2026-09-29 (Job Sandbox Execution). Multi-node sandbox jobs: cluster-consistent ephemeral uid (expected: controller-allocated, WAL-replicated uid lease from a reserved range), worker-driven remote/MPI launch (no ssh; PMIx/prted via worker), shared-FS ownership normalization, one unit per job per node. Brief:
.kiro/specs/job-sandbox-multinode/brief.md. Dependencies: job-sandbox-execution, application-profile. -
rbac-persistence — NEW 2026-09-29 (
/kiro-discovery, raised during application-profile discovery). Closes the deferredsecurity.mdgap: runtime RBAC mutations (roles, permissions, user-role assignments, Logon auto-assignment) are in-memory only and silently revert torbac.yamlon apiserver restart — including revocations. Durable-or-rejected mutations, audit trail, defaults-vs-runtime reconciliation, multi-apiserver consistency; storage approach (rbac.yaml write-through / controller-replicated entity / embedded store / read-only) decided in design. Brief:.kiro/specs/rbac-persistence/brief.md. Dependencies: none (independent of the sandbox initiative; application-profile's API-madeapp:usegrants rely on it for durability). -
job-time-window — NEW 2026-09-29 (
/kiro-discovery, Path C). Job begin time (scheduler gate insched_job_is_ready()viaxce_core_now, pend reason BEGIN_TIME_NOT_REACHED) and end time (WORKER enforces running jobs: helper SIGTERM→grace→SIGKILL, exit reason END_TIME_REACHED persisted, unit RuntimeMaxUSec backstop; PEND jobs whose end time can't be met stay PEND with END_TIME_UNMEETABLE until user kills/modifies — no controller sweep, primary not involved). Adds runtime estimate (-We/--estimated_run_time, scheduling hint only, never enforced; estimate > run limit rejected); unmeetable rulenow + (estimate ‖ run_limit ‖ 0) > end. Times/estimate modifiable only while PEND (newxce jobs modify+ harnessjobmod). Both xcecli and harnessjobsubgain all options (-b/-t/-W/estimate). Also fixes the silent drop of xcecli-b/-t/-Wand RESTrun_time_estimation(apiservermodelJobToSubmitnever sets them norexdata). Brief:.kiro/specs/job-time-window/brief.md. Dependencies: none (new reason codes need text in job-status-detail-display). -
job-dependency — NEW 2026-09-29 (
/kiro-discovery, Path D; ref LSF 10.1 Admin Guide "Job dependency and job priority" pp. 459-465 — dependency only, priority deferred).-wexpressions by job ID: done/ended/exit(id[,op code])/started/post_done/post_err (PDONE/PERR) + bare id,&& || !(). Shared libxce grammar (Go via cgo); apiserver early validation (syntax, parent exists, submitter hasjob:view); controller authoritative re-validation, stores expression (additive JobSubmitData field) + in-memory reverse index rebuilt on replay (implements controller-job-cleanup'sjob_has_dependents()); scheduler evaluates insched_job_is_ready()(pend reasons DEP_NOT_SATISFIED / DEP_NEVER_SATISFIED; orphans stay PEND). Fixes scheduler exit-code field-completeness gap (xce_sched_job_t/SchedJob/snapshot lack exit code). xcecli-w,modify -w/-wn; harnessjobsub -w/jobmod. Brief:.kiro/specs/job-dependency/brief.md. Dependencies: job-time-window (shared gate + modify path) — coordinate. -
job-dependency-insight — NEW 2026-09-29.
bjdepinfo-style query (parents/children/-p blocking/-r levels/-l verdicts, RBAC-filtered) via REST/xcecli/harness, dependency info in job details, optional orphan termination (per-job-ti+ cluster grace period, default off; EXIT reason ORPHAN; failover-safe persisted grace start; minimal primary periodic work). Brief:.kiro/specs/job-dependency-insight/brief.md. Dependencies: job-dependency, job-time-window (exit-reason field). -
controller-job-cleanup — NEW 2026-09-29 (
/kiro-discovery, Path C). Primary-only periodic sweep (configurablejob_cleanup_period, default 300 s) removes DONE/EXIT jobs finished longer than configurablejob_retention(default 3600 s, 0 = off) with no dependents (stub; XCE has no job dependencies yet), via a NEW replicated WAL job-removal fact applied on every node (first-everjobmgrdelete; refcount-safexkvmgrdelete), propagated to scheduler and apiserver (OnJobDeleted). Retires the node-local snapshot-onlyjob_should_retainfinished-job filter (hard-coded 3600 s; causes snapshot/memory job-set drift). HA/persistence → full 3-phase workflow. Brief:.kiro/specs/controller-job-cleanup/brief.md. Dependencies: none (extends ha-entity-snapshots). -
job-status-detail-display — NEW 2026-09-28 (
/kiro-discovery, Path E). End users (REST/xcecli) see NO pend reason for ANY job today: the apiserver cgo conversion (backend/convert.go) never mapsxce_job_t.pend_reasons, sopending_reasonis always empty. Maps it to a structured JSON (includingalternativesfrom day one) using libxce's code→text mapping, and renders it inxceclijob detail. Open for requirements: also maprun_usage→JobRusage(same gap; reserved vs. used for RUN jobs). Brief:.kiro/specs/job-status-detail-display/brief.md. Dependencies: none for flat reasons; scheduler-alter-pend-reasons for per-alternative rendering. -
job-config-merge — NEW 2026-10-09 (
/kiro-discovery, Path E "configuration layering"; ref LSF 10.1 Admin Guide pp. 314-316, 435-437, 561-563, 643, 660). One merge function insrc/libturning the job's own values + application profile + queue policy + project into effective values (resreq incl.span, task range, limits, pre/post-exec, env). One owner per attribute (user decision;.kiro/steering/job-config-layering.md): job overrides a profile attribute only if it is default (forselectonly by adding ANDed terms); queue ceilings and project quotas only check (reject if never satisfiable, pend if full now). Live merge (user decision): WAL keeps inputs + names; controller/apiserver validate at submit; scheduler computes effective values and re-evaluates pending jobs on config change. Queue is policy only: queueres_reqandpre_exec/post_execdeprecated (pre/post-exec moves to the profile), dropped queue limits (cpulimit/memlimit/runlimit/task limit) wired. Brief:.kiro/specs/job-config-merge/brief.md. Dependencies: none. -
project-config — NEW 2026-10-09 (configuration layering). Projects control resource ownership, v1 = quota: project definitions in cluster config (members, priority, cluster default), default-project resolution, submit access check, scheduler
pgmgrloaded from config soPROJECTS/PER_PROJECTlimits work end to end, per-project usage display. Brief:.kiro/specs/project-config/brief.md. Dependencies: none. -
host-failure-job-recovery — NEW 2026-10-10 (
/kiro-discovery, "Long-running services" phase 1; also a batch gap: RUN jobs on a dead host stay RUN forever,controller/sched.c:631FIXME). After a grace period, jobs on a lost host go to an unknown state, then are requeued (rerunnable, job option or profile default) or end EXIT "host lost"; multi-host jobs resolved as a whole; attempt numbers fence a stale copy when the host returns; manual requeue (REST/xcecli). Brief:.kiro/specs/host-failure-job-recovery/brief.md. Dependencies: none. -
service-supervision — NEW 2026-10-10 (Long-running services phase 1). Application profile kind
service: restart policy (always/on-failure/never, backoff, give-up), liveness and readiness probes (command/TCP/HTTP) run by each replica's own worker (no special replica), in-place restart, change-only health reports, display. Brief:.kiro/specs/service-supervision/brief.md. Dependencies: application-profile, host-failure-job-recovery. -
service-replica-set — NEW 2026-10-10 (Long-running services phase 2; user decision: no head agent, no promotion). Controller-held service object owning independent replica jobs; event-driven rules on commit (replace ended replicas with backoff, scale, rolling update with max-unavailable/surge, pause/resume/rollback); spread rule; REST/xcecli
services. Brief:.kiro/specs/service-replica-set/brief.md. Dependencies: service-supervision, host-failure-job-recovery, application-profile. -
service-endpoint — NEW 2026-10-10 (Long-running services phase 2). Named ports allocated per replica as host resources, host addresses reported by workers, endpoint =
host:portof ready replicas from readiness changes, REST/xcecli queries; DNS/proxy later. Brief:.kiro/specs/service-endpoint/brief.md. Dependencies: service-supervision, service-replica-set. -
provisioning-demand — NEW 2026-10-10 (
/kiro-discovery, "Auto resource provisioning"; LSF resource-connector precedent). Scheduler knows a provisionable catalog (host templates, license headroom, supply in flight), tries it after real resources fail (templates as virtual hosts, headroom shortfall), finalizes demand and idle supply in the end-of-session handler (preferred design) and publishes it to the controller. Simulator support is a hard requirement (same demand as live, REPL display, recordings, simulated provider responses). Brief:.kiro/specs/provisioning-demand/brief.md. Dependencies: none (licenses need resource-distribution-mapping's shared pools). -
resource-provisioner — NEW 2026-10-10 (Auto resource provisioning). New daemon (
src/autoscaler, an LSF RC-style port, is prior art only, not a required basis): several instances, each owning providers via controller leases (cloud and license provisioners may differ); providers describe capacity, cost, priority, lead time, granularity, hold time; script contract v2 (hosts and counts); automatic policy (no approval), budgets, cooldowns, retries, idle reclaim; request/instance state as controller facts; orphan cleanup; REST/xcecli/audit; simulated provider. Brief:.kiro/specs/resource-provisioner/brief.md. Dependencies: provisioning-demand. -
elastic-hosts — NEW 2026-10-10 (Auto resource provisioning). Host templates in config, expected-host records matched at join, provisioned/draining/decommissioned states, drain-then-release, decommission control, spot loss as host loss. Brief:
.kiro/specs/elastic-hosts/brief.md. Dependencies: resource-provisioner, host-failure-job-recovery. -
elastic-shared-resources — NEW 2026-10-10 (Auto resource provisioning). Elastic shared resources (e.g. EDA licenses): base + borrowed total updated by the provisioner role through the controller, unused borrowed amounts returned, display. Brief:
.kiro/specs/elastic-shared-resources/brief.md. Dependencies: resource-provisioner, resource-distribution-mapping. -
custom-resource-reporting — NEW 2026-10-11 (
/kiro-discovery, "Unified resource model" phase 2;resource-distribution-mappingoption 3 split out, pending user decision 1 inresource-model.md). Runtime custom resource values: an elim-like script reporter on workers (posix_spawn) and/or an external reporter role (decision 2), staleness andintervalenforced, a string-set kind for dataset locality, instance-inventory publishing (DRA ResourceSlice-like). Brief:.kiro/specs/custom-resource-reporting/brief.md. Dependencies: resource-distribution-mapping, peer-authentication-hardening. -
resource-instances — NEW 2026-10-11 (Unified resource model phase 3). Identified instances (GPU, MIG slice, NIC, ports) with attributes; topology-aware allocator plugin driving the unused
affinity[](NVLink domain, GPU-NIC affinity; switch block viasame[]/span[]); durable per-job instance assignment (WAL/snapshot field-complete); worker binding (device cgroup,CUDA_VISIBLE_DEVICES, port env). Brief:.kiro/specs/resource-instances/brief.md. Dependencies: custom-resource-reporting, scheduler-framework. -
resource-claims — NEW 2026-10-11 (Unified resource model phase 4). Data and volumes as lifecycle resources: template claims (per job/replica: scratch, staging, KV cache) and standalone claims (K8s PVC/ResourceClaim-like: checkpoint volumes, model weights, dataset caches; access modes RWO/ROX/RWX/RWOP; retain/delete), claim WAL entity, dispatch readiness gate (stage-in/out), storage provider contract (reused from resource-provisioner), worker publish into the sandbox, orphan handling. Absorbs the sandbox workspace and
transfer_filesstaging (bug-1937 deferral). Brief:.kiro/specs/resource-claims/brief.md. Dependencies: resource-provisioner, resource-instances, job-sandbox-execution. -
gang-groups — NEW 2026-10-11 (Unified resource model phase 5, LLM training). All-or-nothing scheduling of a group of jobs (launcher + workers, JobSet-like), topology packing across the gang, start barrier until every member is placed and its claims are READY, group failure policy. Brief:
.kiro/specs/gang-groups/brief.md. Dependencies: resource-instances, resource-claims, parjob-placement.
Existing Spec Updates (2026-10-11 unified resource model discovery)
Direction: .kiro/steering/resource-model.md. Decisions, proposals (PR-1 generic supply map incl. provisioned supply, PR-2 resource provider proxy, PR-3 datasets in the map with staging as provisioning) and open questions: .kiro/steering/resource-questions.md. Duration/decay: must-have, future spec (R8).
- resource-distribution-mapping — phase 1: shared pools (option 2) plus the resource type descriptor fields (
scope,unit,reporter,layer,instances,provider); option 3 moves tocustom-resource-reportingunless the user keeps it here (decision 1). - service-endpoint — ports as identified instances of
resource-instancesinstead of a separate port model. - job-sandbox-execution — the per-job workspace becomes the first template claim of
resource-claims; publish (mounts) through the claim's worker step. Where data staging lives is decision 9. - application-profile — default claims (model weights, checkpoint) and GPU instance requests in profiles;
containerexecution mode decides volume publishing (decision 6). - job-resize — re-bind a job's standalone claims to the new host set; resize a gang group.
- service-replica-set — replicas share one read-many weights claim; rollout attaches version N+1 while N stays attached; per-replica template claims.
- resource-provisioner — its provider contract, lease, epoch and orphan machinery are shared with storage/claim providers.
- provisioning-demand — claim shortfall as provisionable demand.
- peer-authentication-hardening — reporter and claim-provider roles on the per-role opcode allowlist.
- scheduler-framework — the deferred GPU/affinity allocator plugin is delivered by
resource-instances; honourrusageduration/decay, parsed but ignored today (alloc_runner.c:429; decision 8, licenses need it).
Existing Spec Updates (2026-10-10 auto resource provisioning discovery)
- resource-distribution-mapping — choose its shared-pool scope (option 2) so a cluster-wide pool (licenses) can be declared in
resources.yaml; prerequisite of elastic-shared-resources. - peer-authentication-hardening — a provisioner role with its allowed operations (provisioning facts, shared-total updates, expected hosts).
- xce-node-manager — revise requirements (approved 2026-09-03) for the cross-spec interactions recorded 2026-10-10 in its requirements.md: shared supervision/probe module with service-supervision, a lease-based
provisionerrole, worker stop on decommission and role declaration for provisioned hosts, grace period vs worker restart, future service proxy underreverse-proxy.
Existing Spec Updates (2026-10-10 long-running services discovery)
- application-profile — profile kind
servicesection: restart policy, probes, ports, default replicas, spread rule, rollout settings (consumed by service-supervision, service-replica-set, service-endpoint). - job-config-merge — service attributes follow the ownership rule (profile owns them; the job may override only
defaultones, e.g. replica count).
Existing Spec Updates (2026-10-09 configuration layering discovery)
- application-profile — the profile carries the job's resource requirement (select/rusage/
span/same) and task limits (min/default/max); "resolved and frozen at submit" replaced by the live merge ofjob-config-merge(brief updated). Dependencies: job-config-merge. - parjob-placement —
spanread from the effective resreq; span constraints in the fixed-N planner; range search bisects over the planner's allowed counts (block: multiples; ptile: multiples + max); LSF 10.1 findings recorded in its requirements.md notes;span[stripe]candidate. Dependencies: job-config-merge (forspanfrom profiles; job-level-Rspan can land first).
Existing Spec Updates (2026-09-28 info job discovery)
- scheduler-sim-diagnostics —
info job <jobid>enhancement: a PEND job shows its pend reason set (per alternative once scheduler-alter-pend-reasons lands; shows the flat reason until then); a RUN job shows per-host/per-resource reserved (job->allocs) vs. real used (job->rusages), and when no rusage has been reported yet says "resource usage not reported yet" (no fabricated zeros; reserved still shown). Byte units per its Req 6. Read-only. Next:/kiro-spec-requirements scheduler-sim-diagnostics. Dependencies: none (alternatives display depends on scheduler-alter-pend-reasons).
Future Specs / Backlog (dependency order)
-
project-guarantee — NEW 2026-10-09 (configuration layering, backlog). Project-owned guarantees (resource amount or host pool), borrowing of idle guaranteed capacity, reclaim through preemption. Brief:
.kiro/specs/project-guarantee/brief.md. Dependencies: project-config, scheduler-preemption. -
job-resize — NEW 2026-10-10 (from long-running services discovery; not on the services path). Grow/shrink a running parallel job's allocation (LSF resizable jobs,
bresize) for elastic applications. Brief:.kiro/specs/job-resize/brief.md. Dependencies: parjob-placement, host-failure-job-recovery. -
project-delegated-membership — NEW 2026-10-10 (from project-config requirements, user decision: future). Project managers edit their project's (and subtree's) members at runtime without an admin config push; needs a durable store that coexists with
xceadminconfig pushes (e.g. a separate delegated member list) and audit. Dependencies: project-config, rbac-persistence. -
lsf-config-migration — NEW 2026-10-09 (user idea, backlog; no brief yet). A tool (likely an
xceadminsubcommand) that converts LSF configuration (lsb.queues,lsb.applications,lsb.resourcesLimit sections,lsb.users/lsb.hostsgroups,lsb.paramsdefaults, project settings) into XCEconfigs/*.yaml, with a report of what does not map: queueRES_REQ(XCE queues are policy only; move into a profile or drop), LSF's full per-section merge rules vs XCE's simplified ones, compound/alternative resreqs, unsupported parameters. Dependencies: job-config-merge, application-profile, project-config, parjob-placement (span), admin-config-tool. Promote via/kiro-discoverywhen those land. -
xce-harness-component — PROMOTED to spec 2026-09-13 (
/kiro-discovery; brief at.kiro/specs/xce-harness-component/brief.md). Elevatexce_test(the REPL-driven wire-protocol test client used by HA soak / multi-host / resource-value verification) out ofsrc/controller/testsuite/into its own first-classsrc/harness/component — ownmeson.build,CLAUDE.md, and unit-test binary (carved out ofcontroller_unit_test, which today recompiles ~14 of xce_test's own files a second time paired with white-box tests) — fully decoupled from/xce-build controller(today's implicit "controller always builds xce_test" coupling,build-deployment.md:24). Verified finding: none of xce_test's 15 source files include any controller-private header — only libxce public headers + generated capnp schema — so this is a pure relocation + build-graph split, not a dependency untangling problem, and no xce_test behavior changes. Touches/xce-test-ha,/xce-deploy-ha,/xce-test-multihost,/xce-test-resources(each must buildharnessexplicitly once decoupled) and is adjacent to (not overlapping) the three existing behavior specsxce-test-cli-ux/xce-test-e2e-primitives/xce-test-rc-file, whose file-path references go stale after the move. Next:/kiro-spec-init xce-harness-component. -
config-upgrade-snapshot — descoped from
ha-term-safetyR8 on 2026-06-21 (requirements generated;.kiro/specs/config-upgrade-snapshot/). Closes bug-857: a configuration upgrade can leave members with DIVERGENT materialized state because today it does config-push + restart + per-node WAL replay under the new config (config_repl.cdo_upgrade_config_with_bytes~1001-1163), with no snapshot pinning an identical post-upgrade state (replay is config-dependent —lost_and_foundre-homes orphaned entities). Approach: an upgrade materializes a full entity-bearing state snapshot at the config-change marker's(term,lsn)boundary, embeds the new config, and installs it on every member via thesnapshot_transfer_stransport — no per-node re-derivation; supersedesha-term-safetyR7's interim config-push byte delivery for upgrades. Former HARD dependencyentity-bearing-snapshotsis CLEARED — it shipped as specha-entity-snapshots(IMPLEMENTATION-COMPLETE, validate-impl GO 2026-07-18; see Future Specs/Backlog below), andha-term-safety(the config-change marker it anchors on) is also implemented.config-upgrade-snapshot's ownspec.jsonnow hasblocked_on: []. Verify by reproducing bug-857 (upgrade during chaotic multi-kill, diff materialized state). Ready to promote to design. -
component-failover-adoption — recorded 2026-06-16; depends on libxce-failover (HARD). Make the C daemons and the Go apiserver actually exercise libxce's transparent failover. The mechanism reaches them for free (worker/scheduler/controller link
libxce_dep; apiserver uses it via cgo,src/frontend/apiserver/backend/clib.go), but two per-component integration items remain: (1) each component must hand libxce the full master list instead of a single endpoint (today even the CLI uses onlyconf->masters[0],client.c:122); (2) bounded retry makes the already-blockingxce_requestblock longer (seconds of backoff) — for the async C daemons (workercontroller_connector.c, schedulerhandler.c) this must be verified liveness-safe, i.e. it must not stall a thread that also drives heartbeats (the "never block the iomgr thread" rule). Scope: per-component master-list config + retry policy + liveness-safe blocking + per-component E2E failover for scheduler, worker, apiserver. (xce_testis NOT here — it is the in-spec verification client of libxce-failover.) Promote via/kiro-spec-init component-failover-adoptionafter libxce-failover lands. -
worker-rejoin-resync— PROMOTED to spec 2026-08-10, see In Flight (Raft Apply-Ordering family) above for current status and brief. No longer tracked here. -
admin-config-tool — PROMOTED from backlog to spec 2026-07-06 (
/kiro-discovery; brief at.kiro/specs/admin-config-tool/brief.md). NEW:xceadminPython CLI for cluster operators — builds and deploys cluster configuration via direct TCP+TLS capnp wire to controller (NOT through apiserver). Two subcommands: (a)config build— directory scan: parseconfigs/{hosts,queues,resources,users}.yaml, validate against JSON schemas (configs/schema/*.schema.json), serializeClusterConfigcapnp struct tocluster.binwith SHA-256; (b)config push— zero-config dev (defaultlocalhost:9991, same as xce_test), single--controllerflag for production, auto-discovers peers + primary from controller reply, sendsOP_upgradeConfig, displays{versionTag,ackedCount,error}. Single dependency:controller.capnp. Pure Python (pycapnp + yaml + jsonschema + click), open-source ready (pip install). The tool is the client-side trigger forconfig-upgrade-snapshot's controller-side path. MUST validate against reserved name"lost_and_found"for queue/host (defence-in-depth). xcecli comparison:xcecli= user tool (HTTP/HTTPS → apiserver → CGO → controller, JWT auth);xceadmin= operator tool (direct TCP+TLS → controller, zero-config, same trust model as controller peers). Shared future:xcecommonPython package with capnp schema + wire protocol reusable by both tools. Dependencies:controller.capnpschema only. Blocks: nothing — ships independently. Controller-side upgrade snapshot path (config-upgrade-snapshot) was blocked onentity-bearing-snapshots; that blocker is now cleared (see Future Specs/Backlog above —ha-entity-snapshotsimplemented,config-upgrade-snapshotblocked_on: []). Next:/kiro-spec-requirements admin-config-tool. -
component-rejoin-resync — PROMOTED to spec 2026-08-10 (
/kiro-discovery; brief at.kiro/specs/component-rejoin-resync/brief.md) from the "lightweight rejoin re-attach" item below. apiserver + scheduler reconnect/rejoin resync efficiency — today each does a full re-join and receives full state again (whole job list, queue/resource/config state), not a delta; for a large cluster this is sizable but not yet a measured problem. Sibling ofworker-rejoin-resync— disjoint data (list/config state vs. job-execution facts), NOT merged into that spec. Not started: first step is investigation (is reconnect cost actually a measured problem at realistic cluster sizes?) before committing to any delta/session-token mechanism — original YAGNI discipline still applies, this spec is the promoted vehicle for that investigation, not a rubber-stamped design. Original decision (libxce-failover design review) retained below for provenance. Dependencies: libxce-failover (rejoin hook — implemented), component-failover-adoption (daemon rejoin content — in progress, sequence alongside/after). Next:/kiro-spec-requirements component-rejoin-resyncwhen ready to begin (not immediate). -
lightweight rejoin re-attach (failover optimization)— recorded 2026-06-16; deferred (YAGNI); apiserver/scheduler half PROMOTED tocomponent-rejoin-resync2026-08-10 (see above); worker half already promoted toworker-rejoin-resync. No longer tracked as a bare backlog item — provenance only. Original text: on controller failover a reconnecting daemon does a full re-join and apiserver/scheduler receive full state (e.g. the whole job list), not a delta; for a large cluster this is sizable but rare. Decision (libxce-failover design review): accept full-state rejoin — it is simple, correct, and still cheaper than a full-history replace with no snapshot (cf. IBM LSF). Future optimization: a session-token "re-attach" hello that lets the new primary skip re-pushing already-replicated state, or a delta-only state transfer keyed on the consumer's last-known committed LSN. Delta reconciliation is non-trivial (the primary must know what each consumer already holds). Promote only if failover-rejoin latency/bandwidth is measured as a problem at scale. -
job-array-single-wal-record — IMPLEMENTED, validate-impl GO 2026-07-17 (reopened once 2026-07-16 for three user-directed residual gaps — bug-1443 bulk-insert partial-visibility, task 4.2's boot-replay fence gap, bug-1444 replay_wal array-blind tally — all closed, re-validated fresh GO). PROMOTED to a spec 2026-06-24 (
/kiro-discovery; brief at.kiro/specs/job-array-single-wal-record/brief.md; now tracked under the Raft Apply-Ordering & Hook Decoupling phase above, sequenced after raft-apply-decoupling). Original note retained for provenance: Enhance controller & scheduler so a job-array submission persists, replicates, and pushes to the scheduler as a single WAL record rather than one record per array element. Today a job array fans out to N per-job state changes, so a 10k-element array means 10k WAL appends + 10k replicated commits + 10k scheduler pushes — amplifying commit-engine load, replication bandwidth, and failover replay time linearly in array size. Scope sketch: (a) controller writes one WAL entry describing the array (base spec + index range/count + per-index overrides) committed atomically through the commit barrier; (b) replication carries the single record so standbys reconstruct the whole array from one committed LSN; (c) scheduler receives the array as one push and expands locally. Must preserve per-element identity/state addressing after expansion (status, cancel, completion still operate per task id). Dependencies: ha-commit-engine + ha-commit-barrier-rollout (single atomic commit), ha-consistency-invariants (replicated scheduling state). Spec advised before implementation; promote via/kiro-spec-init "job-array-single-wal-record"when ready. -
job-array-one-based-index — NEW 2026-09-30 (spec
.kiro/specs/job-array-one-based-index/); IMPLEMENTED 2026-10-01, 30/30 tasks; validate-impl GO after one remediation round (full suite, HA array soak, multihost, live REST flow). LSF-compatible array numbering:xcecli jobs submit -J 'name[1-N]'/'name[1]'create elements numbered 1..N (previously 0..N-1, and the indices in-Jwere ignored — bug-1896); submit reports the array identity and element count; elements are shown and addressed as<array-id>[k], control commands also take<array-id>[a-b]; unsupported LSF forms (other starts, index lists, steps,%N, interactive arrays) are rejected with specific messages; API-servermax_array_sizedefault 1000, clamped to 32767; running elements seeXCE_JOBINDEX(0 for ordinary jobs); harnessjobsub -a Nnumbers 1..N and$jobid[k]names elements; the controller rejects multi-element arrays starting at 0 from un-upgraded clients (E_XCE_ARRAY_START0). Supersedesjob-array-single-wal-recordRequirement 5 (identities unchanged, numbered from 0) and thexce-test-e2e-primitives$jobid/expect-jobdefinitions (superseded notes added in those specs). User documentation:src/docs/xce.md"Job arrays" section, including the LSF features not supported. Bugs: bug-1896 (indices ignored, numbered from 0), bug-1898 ([..]filters never evaluated; restart path fixed afterwards inc73708b8), bug-1899, bug-1900, bug-1901 fixed; found and fixed during validation: bug-1903, bug-1904, bug-1906, bug-1907. Open item: a liveXCE_JOBINDEXcheck on a host with systemd (unit-tested only). -
bulk job-array query/cancel — recorded 2026-07-13, deferred out of
job-array-single-wal-recordscope by design. A single client operation to query or cancel an entire array (not one element at a time) is explicitly out of scope forjob-array-single-wal-record— see that spec's Boundary Context. Reason: array elements can be in heterogeneous states at request time (done/exited elements need no action; running elements need a worker kill signal; pending elements need a direct state transition to cancelled without ever running), which is a materially different bulk-operation problem from atomic array submission and needs its own requirements (partial-failure semantics, atomicity vs best-effort per element, etc.) rather than being folded into the submission spec. Dependencies:job-array-single-wal-record(per-element identity/addressing this would operate over). Promote via/kiro-discoveryonce job-array-single-wal-record ships. -
WAL group-commit batching— recorded 2026-06-17 as deferred; ABSORBED INTO ha-commit-durability 2026-06-18 (design-review reversal). The/kiro-validate-designreview surfaced that the highest-volume WAL traffic isWAL_MODE_RETAINfacts (job start/finish/fail/rusage) — not array-collapsible and not covered byjob-array-single-wal-record— so a pure per-entry synchronous design would penalize the dominant write path. Decision (with user): do group-commit now — repurposefsync_workerfrom a timer into a demand-driven flusher (batch onefdatasyncacross pending appends, advancedurable_lsn, wake commit-eval) as part of ha-commit-durability rather than deferring. No longer a separate backlog item. -
primary step-down-on-quorum-loss — optional CP follow-on noted in ha-consistency-invariants brief (writes already blocked on quorum loss; step-down is an availability/clarity optimization).
-
read consistency / leader leases — Raft §8 read-only optimization; status queries may currently observe stale or provisional state (documented deviation in ha-consistency-invariants).
-
entity-bearing snapshots ("Task 11" format) — PROMOTED to spec
ha-entity-snapshots(created 2026-07-01); IMPLEMENTED, validate-impl GO 2026-07-18 (21/21 tasks 1.1-8.1; 962 controller tests green including all 9test_persist_snapshot_entities.ccases; live--force-snapshotsoak: committed_divergence=0, committed_job_loss=0, confirmed real "HA: snapshot" install log line).write_snapshot()(persist.c~2304-2372) now collects and serializes job/queue/host entity frames (collect_job_frames/collect_queue_frames/collect_host_frames) ahead of the header — no longer a bare 16-byte LSN sentinel. Original backlog note retained for provenance: real entity serialization unblocks snapshot-based state transfer and faster recovery. Cheaper than it looks (verified 2026-06-11): the dual-zarray COW machinery it needs was already built and unit-tested but dormant —xzarray_freeze/xzarray_thawin the vtable (zarray.c:695-757, O(1) freeze, thaw withshould_retainGC filter, test_zarray_cow.c) with zero production callers (kvmgr.c:297vfreeze = NULL /* wired in P0-2 */). Note: single-generation COW — the snapshot consumer owns freeze/thaw; do not add second concurrent consumers. Slot-level only (snapshots array structure, not object contents — serialize item state under per-object locks during the freeze window). Also strengthens ha-consistency-invariants §C eviction option (iii) and faster rebuild-on-demotion. Downstream:config-upgrade-snapshot's former HARD dependency on this is now cleared (blocked_on: []) — see that item above. Also strategy B for catch-up of a far-behind / empty-rejoin standby (cursor=0) is now live: the standby-side snapshot-install/apply path is wired (ha.c~3112-3147 wire-receive path task 6.1;persist.c~4277-4285 local boot recovery task 8.1), with a decision path that requests a snapshot transfer when a standby's cursor falls below the leader's oldest retained WAL LSN (ha.c:4413). The bug-1147 WAL-trim cursor-bound guard (see Hardening below) is implemented in production, no longer just a stopgap.
Hardening / Direct-Implementation Items
Smaller items that likely don't warrant a full spec; pick up opportunistically or bundle into adjacent spec work.
-
remote-task units run as root (SECURITY, found 2026-09-29 during job-sandbox discovery) —
job_start_remote_taskpath allocatestask_ctx(src/worker/src/controller_connector.c:1204) and submits it (:1388) without ever settingtask_ctx->limits;start_systemd_job()only appendsUser=whenlimits != NULL(xcecd_cgroups.c:296-312), so remote tasks of multi-host jobs run in a system unit as root. Confirmed by code reading (not yet live-reproduced). Fix: buildlimits(at leastuser_name= taskhostexecuser) on the remote-task path; refuse to start with an empty user. Log viabuglogbefore fixing. HARD prereq for job-sandbox-execution / job-sandbox-multinode. -
eliminate src/frontend/Makefile, consolidate Go builds onto meson— PROMOTED to spec 2026-08-27 (/kiro-discovery; brief at.kiro/specs/eliminate-frontend-makefile/brief.md). Investigation (recorded 2026-08-21, fromdirty-content-fingerprintspec's task 4.3) confirmed the risk is real and independently corroborated:build-serveris separately confirmed BROKEN today (bug-1597, barego buildwith no CGO flags,fatal error: client.h: No such file or directory;src/docs/deployment.md:243-247already tells developers to use/xce-build apiserverinstead). Blast radius is narrower than originally framed:/xce-buildalready builds both binaries via meson exclusively (build-cli/build-serverare dead weight from that path today); only 2 live call sites (xce-build.sh:240,287) depend onmake test, with an already-proven direct-go testreplacement 3 lines away in the same file. One genuine gap found: no mesontest()exists for the CGO backend suite (test-backend) — that must be added before the Makefile can be safely removed, or backend CGO coverage is lost, not just inconvenienced. Next:/kiro-spec-init eliminate-frontend-makefile. -
job_ctrl direct-mutate path — migrate to commit-then-apply — recorded 2026-07-13, investigated 2026-08-19 (finding: real risk, wider scope than originally framed).
raft-apply-decouplingdeliberately scopedjob_ctrl'smark_job_update/mark_job_fail(admin SIGCONT/SIGSTOP) OUT-OF-BOUNDARY (task 4.1/6.1 Implementation Notes). The 2026-08-19 investigation found the original framing wrong in two ways: (1) NOT the only remaining call site —on_job_stop/on_job_resume/on_job_ckpt(job.c:2067-2222) share the identical unconverted mutate-then-notify-then-WAL-append pattern, fed by ordinary worker/scheduler traffic, not "rare, admin-only" as originally described; (2) blast radius (a) is confirmed real, not theoretical — the pre-commit mutation is synchronously pushed live to BOTH the scheduler (sched_job_update_fun) AND every connected apiserver/client (apiserver_job_update_fun) before the commit barrier resolves; on barrier timeout the admin gets a failure reply butjob->job.stateis never rolled back and no retraction is ever sent — matching the bug-795/828/851/1060 shape. Live-apply vs replay-apply (b) is narrower than feared forjob_ctrlspecifically (theallocs != NULLgate mutually excludes it from the converted deferred-apply fact types), but the investigation surfaced a SEPARATE bug underpinning that safety argument:job_ctrl(job.c:999) holds only a read lock while mutating job state — every other mutator in this file takes a write lock — so two concurrent admin commands on the same job aren't mutually excluded, undermining the "same lock, no staleness window" claim the replay-safety argument depends on (already flagged by araft-apply-decouplingtask 2.1 reviewer, never fixed). Recommendation: promote to a small follow-up spec covering all four call sites together (bounded, well-precedented fix — same shape as the fact-receipt conversionraft-apply-decouplingalready built for job submit); the lock-type bug is independently fixable and low-risk regardless of when/whether the larger migration happens. Not yet promoted — user decision 2026-08-19 to correct scope/framing here first, promote later. -
WAL-trim cursor-bound guard (bug-1147; surfaced 2026-06-25 by raft-drive-async design review) — IMPLEMENTED as part of
raft-drive-asynctask 3.2 (raft-drive-asyncis IMPLEMENTED, validate-impl GO 2026-07-18; see above).trim_wal_segments(persist.c~2597-2644) now computesfloor = repl_trim_lsn(&p->repl, active_seg_lsn, p->config.snap_interval_s)— folding in active-standbyacked_lsnand disconnected-slotlast_disconnected_lsn— and only unlinks segments below that floor; the code comment atpersist.c:2634explicitly labels this the "(bug-1147 guard)". Far-behind/empty join (cursor=0) is additionally covered now thatentity-bearing snapshots(strategy B) has landed asha-entity-snapshots(see above), with a live decision path (ha.c:4413, "< oldest_wal_lsn → requesting snapshot transfer"). Related: bug-795, bug-828, bug-1060. -
OP_heartbeat peers cross-validation — include a hash of the local
--peersstring in heartbeat requests; log ERROR on mismatch between candidates. Detects misconfigured nodes at election time instead of silently risking dual-primary split-brain. (FUTURE_WORK.md §3.) -
peer-authentication-hardening — NEW 2026-07-06 from admin-config-tool discovery (
/kiro-discovery). XCE currently operates under a trusted-LAN model — any CA-signed SSL peer can connect to the controller and perform ANY operation. Three gaps identified: (a) Admin→Controller:validate_host()is a stub returning success for all peers (roadmap § below).OP_upgradeConfighas no real authorization gate today. Same gap confirmed 2026-08-02 forOPCode_schedAdmin(scheduler-coredesign,cluster.c'scase OPCode_upgradeConfigwas checked as the closest precedent and has only a primary/standby routing gate, no RBAC/auth check) —scheduler-coreshipsOPCode_schedAdminat parity with that existing gap (project owner decision: not ascheduler-coreblocker), so this item now covers both opcodes; whenvalidate_host()is implemented, wire it to bothOP_upgradeConfigandOPCode_schedAdminin the same pass. (b) Worker/Scheduler→Controller: workers and schedulers connect viacontroller_connector.cusing the same TLS context as controller peers, with no role differentiation — a compromised worker could sendOP_upgradeConfigor read full config viaOP_replConfig. (c) Cross-component trust: no distinction between controller peers, admin tools, workers, and schedulers — they share the same X.509 identity pool. (d) xceadmin login (future): xceadmin currently uses zero-config TLS (same as xce_test). Production deployments likely need an admin login requirement — token-based session (xceadmin login → token → config push) or password-per-command. X.509 CN alone proves identity but not intent; a login step provides audit trail, session expiry, and operator accountability. Needs design: role-based X.509 CN validation (controller/admin/worker/scheduler roles), per-role OP code allowlists (now includingOPCode_schedAdmin), admin login/session model, audit logging for admin operations. Separate from the existingvalidate_host()hardening (below) which is the minimal gate forOP_upgradeConfig/OPCode_schedAdminspecifically. Discuss + design before implementing; likely promotes to a spec via/kiro-discovery. -
validate_host() real authorization — currently a stub returning success for all peers (
join.c:13-16,return 1;unconditionally).CONF_ENABLE_UPGRADE_CONFIGis already1in the standard build (config_repl.h:27-28, no build-system override found) — the precondition this item was originally framed to guard against has already been crossed;OP_upgradeConfig(andOPCode_schedAdmin, added 2026-08-02,scheduler-core) are live and unauthenticated TODAY, not a future risk to prevent. Minimum fix: verify peer X.509 CN against a configured allowlist (--admin-cnflag oradmin_cn_listconfig), reject non-allowlistedOP_upgradeConfigandOPCode_schedAdminwith clear error, WARN-log rejected attempts with CN+IP. Future: IP allowlist, role-based access, admin-specific CA. (FUTURE_WORK.md §6; security-critical.) Part of the broaderpeer-authentication-hardeningitem above. -
OP_replConfig access control hardening — currently serves the full config blob to any CA-signed SSL peer (trusted-LAN model). Consider: verify requester is a known
--peerscontroller, rate-limit per peer,minimum_rolecheck (controllers only). (FUTURE_WORK.md §7.) Part of the broaderpeer-authentication-hardeningitem above. -
lost-and-found drain command —
xcecli lost-and-found drain: reassign or cancel sidelined jobs, resetlost_and_found_job_count. Automates operator cleanup after config upgrade. (FUTURE_WORK.md §4.) -
OP_upgradeConfig standby redirect verification— RESOLVED 2026-08-19, then the underlying gap itself CLOSED 2026-08-26 (bug-1700/1701). As of 2026-08-19, a standby did NOT return the primary's address forOPCode_upgradeConfig—ha_dispatch_gaterejected it before the handler's own dead defensive check ever ran, replying flatstatus=-XCE_ERR_STANDBY, data_which=nodatawith no redirect fields;fill_redirect_reply()(join.c:27) was never called for this opcode, a documented, deliberate feature gap (admin-config-tooldesign.md's "Revalidation Triggers"). That gap is now closed:cluster.c's generic dispatch-gate rejection path callsfill_redirect_reply()on every-XCE_ERR_STANDBYrejection (bug-1700/1701, gate-level fix, not opcode-specific), and a standby pushingconfig pushnow redirects to the primary and succeeds. Coverage: client-side redirect-following remains unit-tested against mocks (test_discovery.py,test_config_push_mock.py::test_push_config_follows_one_redirect_to_primary); the real server-side behavior is live-verified against a real 3-node cluster (src/xceadmin/tests/test_e2e_live_ha_push.py::test_live_config_push_against_standby_redirects_and_succeeds, renamed from..._returns_standby_rejection_not_redirectto match the now-correct outcome). -
steering sync —
ha-async-io.mdsynchronized to the three-state model + own-term gate (transitional-state row/role removed; heartbeat re-arm PRIMARY-only; PRIMARY no-quorum fact allowlist noted). Done as part of ha-single-leader-role task 6.1. -
xce_test WAL/snapshot inspection tooling — extend the offline inspector family in
xce_test(sibling of the shippedwaldump,src/controller/testsuite/waldump.{c,h}+cmd_waldump). Two remaining commands: (a)snapdump <snap_dir|snap_file>— decode theXCESNAP\0header (8-byte LSN;persist.c:1266load_snapshot) and report whether the snapshot carries job/queue entities or is an LSN-only stub. This directly settles Open Fork #3 of the failover job-loss investigation (.kiro/specs/ha-commit-durability/INVESTIGATION-failover-job-loss.md): if snapshots are entity-less, any empty-rejoin/WAL-prune below committed is unrecoverable BY DESIGN. (b)walcompare <dirA> <dirB>— diff two nodes' WALs bylsn → crc/jobidto flag divergence/prefix-gaps between members instantly. Reuse thewaldump.creader/decoder; same zero-alloc capnp jobid decode +c_capnproto_dep/zlib_depwiring already added toxce_test_deps. Nonzero exit on entity-less snapshot / divergence so both double as E2E assertions. (recorded 2026-06-20;waldumpalready done.) -
xce_test shell command support— IMPLEMENTED (task 2.1, specxce-test-e2e-primitives, closed 2026-06-19; stale entry corrected 2026-08-19).preprocess_and_run()(src/controller/testsuite/test.c:950) detects a leading!and runs the remainder viasystem(); the shell command's exit status becomesg_last_status(the$?auto-variable) and a non-zero status setsg_session_failed, aborting the script the same way any other failing command does —system()'s child inherits the parent's stdout/stderr fds, so output lands in whatever the invokingxce_testsession's own output is already redirected to. Works in every REPL context (noleave_ctx()/disconnect), including mid-session insideworker/clientcontexts — used this session to fix bug-1579 (resource-value-verification's nested controller-check pattern). No parser/harness-layer change remains to do. -
scheduler framework enhancement — PROMOTED to spec 2026-07-06, then DECOMPOSED 2026-07-27 into
scheduler-core(IMPLEMENTATION-COMPLETE),scheduler-allocation, andscheduler-preemption— see In Flight above for current status. Scope notes from the original brief still apply: commit barrier wiring deferred (separate hardening item); GPU/affinity allocation deferred (pluggable via new allocator interface); new job selection policies deferred (framework enables them, ships separately). No longer tracked here. -
[→] perf-tuning-extraction — PROMOTED to spec 2026-07-20 (
clusterconfig-schema-split,.kiro/specs/clusterconfig-schema-split/). Originally recorded 2026-07-06 from admin-config-tool discovery as a documentation/audit item; the audit (2026-07-20) found the fields are load-bearing enough to need real code changes, not just a doc pass —candidates/vcpus/hash-tuning fields (jobmgr/workermgr/qmgr/resmgr/xstrings) are already dead weight in theClusterConfigcapnp blob (superseded by--peers/--vcpusCLI flags or never read into runtime state — seesrc/docs/cluster-config-split-analysis.md).portis NOT dead — a second review pass (2026-07-20) foundcluster_open_listener(cluster.c:1216-1258) falls back to the blob'sportfield, and single-node mode (no--peersflag at all,main.c:293-294) depends on that fallback entirely; the spec now requires a replacement port-sourcing mechanism before the field can be removed (clusterconfig-schema-splitRequirement 1.7), not a bare deletion.heartbeatInterval/inactiveHeartbeatCount(controller→worker liveness, NOT the HA/Raft election heartbeat) were investigated and deliberately kept INClusterConfigfor operational uniformity despite passing the independence rule — see.kiro/steering/config-design.md.fetchJobInterval/netioTimeoutleft unresolved, flagged out-of-scope in the new spec for a future pass. -
Raft/HA heartbeat interval+timeout as CLI parameters — NEW 2026-07-20 from clusterconfig-schema-split discovery. The controller-to-controller HA/Raft election heartbeat (
ha->config.heartbeat_interval_ms/heartbeat_timeout_ms— the one where a cross-node mismatch risks spurious failover) is 100% hardcoded today (HA_DEFAULT_HEARTBEAT_INTERVAL_MS/HA_DEFAULT_HEARTBEAT_TIMEOUT_MS,cluster.c:1131) — there is noClusterConfigfield for it, and per user decision (2026-07-20) there should never be one: these values must be available to a controller BEFORE it has validated/received cluster configuration (a controller needs its own election-timing parameters to even participate in the election that delivers config in the first place — a bootstrap/chicken-egg constraint, not an independence/frequency judgment call). Target:--heartbeat-interval-ms/--heartbeat-timeout-msCLI flags following the exact--vcpuspattern (OPT_*+struct arguments+myconf_tfield,0sentinel = use hardcoded default). Kept hardcoded for now; this is a future item, not blockingclusterconfig-schema-split. -
resource-distribution-mapping — created 2026-07-23, never added here (found 2026-08-19, itself a small doc gap). Physical resources have no "configured total vs. currently-consumed" concept anywhere in this codebase, live or dead —
resources.yaml'sresourcemapfield (which expresses exactly this: a value shared across N hosts) is deliberately dropped byxceadmin config build(build.py:41-43), and the matchingcontroller.capnpfields are commented out (controller.capnp:208-209).mark_host_res()(worker.c) actively rejects any resource flaggedXCE_RESF_SHAREDtoday, so "shared pool" and "per-host value" are mutually exclusive by construction in the live system right now. A working total/current pooling mechanism DOES exist in the scheduler (resource.c'ssched_check_shared_satisfy_()), but it exclusively serves job-limit virtual resources (queueMAX_RUNNING-style), never physical shared resources — architecturally reusable, never connected. This spec (research.md done, 3 scoped options, requirements.md never generated — sitting at the decision point) is the existing owner of closing this gap; surfaced again 2026-08-19 when scheduler-core's REPLinfo resourcecommand couldn't show a total for a GLOBAL/SHARED resource because there genuinely isn't one to show. Next: pick a scope option in research.md, then/kiro-spec-requirements resource-distribution-mapping. -
scheduler-sim-diagnostics — NEW 2026-08-10 (
/kiro-discovery). Open-ended, continuously-extended spec for scheduler simulation-mode debug/troubleshoot capability — added to over time as new investigation needs surface from discussion or from other in-flight scheduler specs (scheduler-allocation,scheduler-preemption). Extendsscheduler-core's REPL (info job/queue/worker/resource/summary, breakpoints, snapshots). Two seed capabilities identified so far: (1) limit inspection —xce_limit_t/xce_vres_tconfig + live usage currently live only in thelimitplugin's private kvmgr tables, invisible to the REPL; needs a newinfo limit <name|all>command + accessor plumbing. (2) decision-reasoning trace —xce_pendreason_tis captured on pend decisions but never printed by the REPL, and dispatch decisions have no reasoning trail at all (no record of which limit/resource checks passed) — needs new instrumentation in the allocation path (resource.c'ssched_try_alloc_on_host_,plugin.c'slimit_prepare_allocation) plus a REPL command to surface it. Explicitly simulation-mode only (no live/production controller-connected diagnostics) and read-only (no state mutation) per user decision 2026-08-10. Brief:.kiro/specs/scheduler-sim-diagnostics/brief.md. Not started — requirements to be added per-capability, not fully speced upfront. Next:/kiro-spec-init scheduler-sim-diagnosticswhen ready to begin. -
xcecd_virtual concurrent-job support (MXJ > 1) — NEW 2026-08-19, recorded during bug-1589 investigation (
.wolf/buglog.json). Live testing found that when a job array (multiple elements) is dispatched to a singlexcecd_virtualworker in quick succession, only the first element's start ever gets confirmed back to the controller (on_job_start) — the rest are dispatched but never confirmed. Root-caused (or being root-caused — see bug-1589 for the confirmed mechanism once the in-flight investigation lands) toxcecd_virtual's job-simulation path: unlike the realxcecdbinary, which launches an actual dbus-managed worker process per job (tracked by real pid, real IPC status reports),xcecd_virtual(src/worker/src/xcecd.c'sxcecd_process_command(),VIRTUAL_CLUSTERbranch) never launches a real process at all — it assigns a bare incrementing fake pid (static int virtual_pid,xcecd.c:27) and simulates job execution via a sleep-timer mechanism (xcecd_worker_utils.h'sVIRTUAL_CLUSTER-onlyxcecd_worker_tfieldsstart_time/sleep_time/killed_signal,check_worker_sleep_time_elapsed()). The immediate bug-1589 fix (once landed) addresses the specific reported symptom; this item is the broader follow-up: properly support N concurrent simulated jobs perxcecd_virtualworker, since MXJ (max jobs per host) > 1 is a legitimate, common configuration to want to exercise in virtual-cluster-mode testing/CI (this project's own dev workflow relies onxcecd_virtualfor HA soak tests, resource-value verification, and now scheduler-core's live validation — several.wolf/buglog.jsonentries this session alone used it), not just a single-job-at-a-time edge case. Scope sketch (to refine once bug-1589's root cause is fully confirmed): audit every VIRTUAL_CLUSTER-only code path insrc/worker/(xcecd.c,main.c,xcecd_worker_utils.h/.c,process_worker_manager.c) for single-job assumptions (a lone poll/early-return that only processes one pending simulated job per tick, a shared mutable scratch struct reused across concurrent jobs, etc.) and generalize each to iterate the full set of in-flight simulated jobs, matching the pattern the real-process path (process_manager.c'sprocess_info_t manager->processes[], a proper per-pid array) already establishes correctly. Dependencies: bug-1589 (must land first — its root-cause trace is the concrete map of what needs generalizing). Promote via/kiro-discoveryor/kiro-spec-initonce bug-1589 is closed and the exact mechanism is confirmed.
Superseded / Absorbed Items
Quorum-ACK gate before config restart(FUTURE_WORK.md §2) — largely superseded by ha-consistency-invariants Requirement 5: configuration changes now require majority acknowledgment before being confirmed/committed, and fail to the requester on timeout (no silent rollback when standbys are offline). Residual to verify in that spec's design: restart sequencing after a committed config change (don't restart the primary before the commit barrier passes).Lost-and-found keyword validation(FUTURE_WORK.md §8) — folded into the admin-config-tool spec (brief:.kiro/specs/admin-config-tool/brief.md).admin-config-tool backlog item(FUTURE_WORK.md §1 + §8, 2026-05-12) — absorbed intoadmin-config-toolspec 2026-07-06 (/kiro-discovery). The one-paragraph backlog sketch is superseded by the full brief with architecture decisions, decomposition, and boundary contracts at.kiro/specs/admin-config-tool/brief.md.
Notes
-
Backlog items here are seeds for
/kiro-discovery//kiro-spec-init; promote an item by creating its spec under.kiro/specs/. -
Provenance: items marked (FUTURE_WORK.md §N) originate from the 2026-05-12 config-replication-design.md review, merged here 2026-06-10.
-
2026-10-11 unified resource model discovery (data/volumes as resources, custom resources, one interface; context: the LLM training + serving platform direction in the Overview). Key decisions:
- One resource type descriptor and one provider contract over three layers: L1 attribute, L2 counter, L3 instance/claim. Not one mechanism for everything.
- The scheduler only selects from its cached snapshot; providers run after dispatch.
- Batch stays LSF-style.
- Claims come in two forms, template and standalone (Kubernetes PVC/ResourceClaim-like), as WAL entities with the resource-provisioner discipline.
- Adopt Kubernetes DRA/CSI concepts, not (yet) their APIs.
Phases:
resource-distribution-mapping(shared pools) →custom-resource-reporting→resource-instances→resource-claims→gang-groups. Nine user decisions are pending, listed inresource-model.md. -
2026-07-06 admin-config-tool discovery (
/kiro-discovery, Path E mixed decomposition):# Workstream Type Language Dependencies 1 admin-config-tool NEW spec Python controller.capnponly2 config-upgrade-snapshot EXISTING spec extension C entity-bearing-snapshots (blocked upstream) 3 perf-tuning-extraction DIRECT work doc None Key architecture decisions: Python (future open-source, shared capnp infra), pure Python wire (no CGO/libxce), direct TCP+TLS to controller (not apiserver), single
controller.capnpdependency,xceadminseparate fromxcecli(user=REST, admin=TLS), auto primary detection via peer list + redirect. Full details:.kiro/specs/admin-config-tool/brief.md.-
2026-07-06 scheduler-framework discovery (
/kiro-discovery, Path C single-scope):Key architecture decisions: Iterator-driven allocation (lazy plan iterator + host iterator composition), configurable job picker (plugin name from config, not hardcoded), combinatorial parallel job allocation (1host×N → 2hosts×⌈N/2⌉ → … → Nhhosts×1 sorted by preference), session-level unsatisfiable resreq fingerprint cache. Scope narrowed from original backlog seed: commit barrier wiring deferred, new job selection policies deferred (framework enables them), GPU/affinity allocation deferred (pluggable via allocator interface). Alternatives documented in brief.md (Approach A: incremental/rejected, Approach C: full framework/deferred). Full details:
.kiro/specs/scheduler-framework/brief.md.
-