Commit graph

2355 commits

Author SHA1 Message Date
a50c0e236b
docs(spec): application-profile params and annotations; 0-valued rusage dropped; app-submit-hook backlog
- params: declared application settings XCE carries but never interprets;
  exported as XCE_APP_PARAM_*; job overrides with --app-param; undeclared
  names rejected; stored in exdata app_params
- annotations: metadata for tools, also exported as XCE_APP_ANN_* (name
  conversion, collision check, size limits, no secrets)
- merge drops 0-valued rusage terms so the scheduler sees no term (today a
  0 term still rejects hosts where the resource is over-committed)
- app-submit-hook (esub-style) recorded as a roadmap backlog item only

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 03:04:32 +00:00
f658b0a4b0
docs(spec): application-profile review fixes
Gaps closed:
- profile env travels separately from the job env (needed for the clean
  outer-layer environment; remote tasks get both)
- merge library parses and rewrites exdata (env, limits; keeps meta);
  added to job-config-merge scope
- new start_info fields listed (job starter, profile env)
- empty profile name = no profile, never resolved to default_application
- a file profile named default replaces the built-in one
- restart copies the profile name; array jobs carry one name
- multi-host outer pre/post-exec and job starter placement as open design
  questions; rusage=0 and declined-dispatch counting to confirm
- scheduler-side field completeness (frozen dispatched jobs, Conf4Sched
  profiles in snapshot/replay)
- no secrets in profiles; xceadmin warns on secret-looking env names

Stale text fixed: job-modify reference, exdata wording, rusage defaults
exception, I/O directories (moved to job-sandbox-execution), sandbox in the
sketch, job starter and job_pre_post_exec in the table, dispatch record
contents, misplaced rationale paragraph, versioning reference, scope and
touchpoints, task range (min/max) in job-config-layering.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 02:55:23 +00:00
1f9aaae050
docs(spec): structured profile resreq; per: optional (default task); merge rules at a glance
- profile resreq split into select / rusage entries / span / same / order;
  rusage entries carry optional per: (default task, today's PER_DEFAULT
  behaviour) and optional default
- job's rusage term wins whole for a resource in both; unit must match;
  no modifier inheritance
- compound/alternative: only the profile select applies; any profile
  rusage default or span/same/order rejects until PR-15
- job-config-layering: merge rules at a glance table; profile = essentials
  plus default reservations

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 02:49:53 +00:00
8f3a811a43
docs(spec): rusage merge: union, job value wins, profile per-type; compound rule
- rusage: union of profile and job resources; for a resource in both the
  job's value wins (either direction); the profile's per-type applies and an
  explicitly different per-type is rejected; omitted modifiers inherited;
  name=0 means none
- rusage is the one profile section that is a per-resource default;
  shared-resource protection via limits.yaml/quotas, later a counted marker
- side effects recorded for requirements (lowering warnings, redundant
  preset values, origin labels, ceiling errors, hash churn)
- compound/alternative: profile select ANDed into every part, per-task
  rusage merged per part, other profile resreq sections reject until PR-15

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 14:49:10 +00:00
a68d2fc965
docs(spec): presets record themselves in exdata.meta; job-labels backlog item
- no preset field on the server: the client puts preset name + hash into
  the job's exdata JSON under 'meta', passed through uninterpreted; the
  worker skips 'meta' silently; 'preset report' filters jobs client-side
- drop the local submission log idea
- job-labels: independent backlog item (general server-side labels)
- bug-1970: note the dropped REST 'tags' field

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 13:26:09 +00:00
5cfe64218c
docs(roadmap): config-history-audit backlog item; profile versioning/audit deferred from application-profile
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 13:12:39 +00:00
67002b2a25
docs(spec): application-profile v1 attributes: job starter added, others ship with their features
- v1 profile attributes: mode (direct), launch type, env + pre/post-exec,
  essential resreq and limits, plus the job starter
- principle: a profile attribute is added by the spec that builds its job
  feature; requeue/success exit values -> job-requeue (new backlog item),
  checkpoint and warning-before-kill later, output path -> I/O track,
  runtime estimate is not a profile attribute
- log bug-1970: REST submit accepts rerunable, requeue_error_values,
  run_time_estimation, mig_threshold, chkpnt_*, warning_* and drops them

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 13:08:29 +00:00
83c6eb8024
docs(spec): xcecli-presets: server preset directory, pull name collisions, /xce/v1 routes
- server presets live in <TopDir>/config/presets/ (or presets.dir in
  app.yaml), one file per preset, re-read on change; not in ClusterConfig
- pull refuses a name collision unless it updates the same server preset;
  --as / --force (keeps .bak); submit uses local presets only
- fix route prefix: /xce/v1/presets, not /api/v1

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:33:31 +00:00
d1e03055e4
docs(spec): split execution modes from application-profile into job-sandbox-execution
- application-profile keeps the profile core: config, access and submit,
  dispatch record, outer pre/post-exec layer; mode: accepts only direct
- sandbox mode + options, I/O directories, capability advertisement and
  placement by mode move to job-sandbox-execution
- order: application-profile requirements/design before job-config-merge
  design; implementation interleaves

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:20:15 +00:00
8900f8876b
docs(spec): application-profile: profile aliases; moving pending jobs deferred to job-modify
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:18:06 +00:00
c0bd701f48
docs(spec): xcecli-presets: one file per preset, same layout on client and server
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:15:34 +00:00
1a5ddc2642
docs(spec): xcecli-presets: environment capture by name (XCE_ and secret exclusions)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:14:50 +00:00
8f8be20885
docs(spec): application-profile: clean env for the outer pre/post-exec, reserved XCE_ prefix
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:12:15 +00:00
d88b9cb31f
docs(spec): application-profile: dispatch-window handling and profile content hash
- profile gone or changed between scheduler decision and controller
  dispatch: dispatch fails (retryable) and the job returns to PEND via
  requeue, never EXIT
- internal per-profile content hash (canonical capnp, excluding
  description) carried on the dispatch decision and the dispatch record

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 10:09:38 +00:00
84f2068ae3
docs(spec): application-profile: dispatch record covers resreq; removed profile makes jobs pend
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 09:57:37 +00:00
3088a21c86
docs(spec): application-profile: freeze execution values on the dispatch record, re-read on requeue
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 09:55:53 +00:00
4536d36f47
docs(spec): application profiles hold essentials only; additive rule; client-side presets
- profiles hold only what every job of the application must have; every
  profile value binds and a job may add to it, never change or remove it
  (replaces the default/fixed markers of 2026-10-09)
- convenience defaults move to client-side presets (new xcecli-presets
  brief): option-level expansion on the client, the apiserver only shares
  admin-deployed presets read-only, pull copies, export/import
- service section stays in the profile: probes, restart policy, ports bind;
  replica count within the profile range; spread/rollout if unset
- job-config-layering, job-config-merge brief/requirements, roadmap and
  resource-questions updated to the additive rule
- app:override and profile inheritance deferred; recommendations target
  site presets

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 09:47:30 +00:00
3fa9361ad8
docs(spec): application-profile: convenience purpose, advisory recommendations, resreq tuning questions
- profiles exist mainly so users need not repeat resreq and other settings;
  most values are defaults, only what the application needs is fixed
- usage-based recommendations are advisory (user decision); new backlog
  item profile-usage-insight
- open questions: per-term resreq markers with ranges, app:override,
  inheritance, presets, job labels, compound resreqs

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 09:30:51 +00:00
84501d30da
docs(spec): application-profile brief: own config file, default_application, live merge cleanup
- profiles in src/configs/applications.yaml (+ schema, ClusterConfig and
  Conf4Sched), optional file with a built-in 'default' profile
- default_application in xce.yaml; an undefined name is a config error at
  xceadmin build, live upgrade and controller start, never a fallback
- remove the superseded submit-time resolution text: the job keeps its
  profile name and own values, effective values come from job-config-merge
- this spec owns the profile attribute schema and override markers
- record the 2026-10-12 open questions with leanings

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 09:11:06 +00:00
19c9f616fb
docs(steering): resource log: delivery plan (tracks, first slices, deferred list with revisit triggers)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 08:00:30 +00:00
680a8bb641
docs(steering): resource log: relationships and compound resreqs (PR-15, N45-N50)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 07:59:41 +00:00
a14595deb0
docs(steering): resource log: uniform task relationship description, canonical jobspec (PR-14, N41-N44)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 07:58:01 +00:00
a6c18162ca
docs(steering): resource log: task relationship model (PR-13, N35-N40)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 07:32:42 +00:00
da46c68d15
docs(steering): resource log: disaggregated serving as one job per unit (PR-12, N31-N34)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 07:27:13 +00:00
77361ba13e
docs(steering): N24 decided: gang-groups demoted to backlog as a co-start group
LLM training is one parallel job with topology requirements (PR-10).
gang-groups moves from the spec list to the roadmap backlog, re-scoped as
a co-start group of separately managed jobs and services (RL
post-training, disaggregated serving, streaming pipelines). resource-model
phases and the brief updated; job-resize no longer resizes gang groups.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:44:56 +00:00
56c4d896d1
docs(steering): resource log: data, cache and communication topology between jobs (PR-11)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:40:04 +00:00
7662cf2aed
docs(steering): resource log: gang use cases; N24 leaning (demote gang-groups)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:34:51 +00:00
d69a418e76
docs(steering): resource log: LLM training as one parallel job with topology requirements (PR-10)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:34:10 +00:00
5959e892d6
docs(steering): resource log: simple submit options (PR-7), data dependencies (PR-8), user isolation and sharing (PR-9)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:32:08 +00:00
73dbe2535e
docs(steering): resource log: shared volume with per-job subdirectories as the job I/O default (PR-6)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:28:06 +00:00
c1aeb209f4
docs(steering): resource log: job input/output through provisioned volumes (PR-6, N6-N11)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:21:03 +00:00
dbcdf100f8
docs(steering): resource log: hosts as supply (PR-4), simple datasets (PR-5), CSI notes, N2/N4 input
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:11:33 +00:00
5b05d51b7a
docs(steering): resource decision and question log (PR-1..3 proposals, R/P/N items)
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>
2026-10-12 04:00:47 +00:00
bab73826f0
docs(spec): record Gitea sync for job-array-one-based-index, parjob-placement, pend-reason-push-dedup
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 03:31:30 +00:00
c14fe3dab5
docs(steering): unified resource model; briefs for reporting, instances, claims, gangs
resource-model.md: one resource type descriptor and provider contract over
three layers (L1 attribute, L2 counter, L3 instance/claim); the scheduler
only selects from its cached snapshot, providers run after dispatch; batch
stays LSF-style; template and standalone (PVC/ResourceClaim-like) claims
as WAL entities with the resource-provisioner discipline; LSF/K8s mapping;
LLM training/serving needs; phases; nine pending user decisions.

New briefs: custom-resource-reporting, resource-instances,
resource-claims, gang-groups. Roadmap: long-term LLM training + serving
platform direction (features from LSF and Kubernetes), the four new specs,
updates to ten existing specs, discovery note. resource-distribution-mapping
becomes phase 1 (shared pools + descriptor fields).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 03:13:44 +00:00
b01b341869
docs(buglog): record Gitea sync for bug-1969
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 15:00:18 +00:00
c52e61df2e
docs(buglog): bug-1969 fixed (autoscaler provider calls use posix_spawn)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:41:21 +00:00
19052674bd
fix(autoscaler): run provider scripts with posix_spawn, not fork (bug-1969)
The scaler is multi-threaded (monitor and demand threads); invoke() forked
and, in the child, logged, snprintf'd and setenv()'d before execl(), which
can deadlock on a lock another thread held at fork time and block the
caller in waitpid() forever.

run_script() now posix_spawn()s `sh <script> -f <in.json>`: stdout and
stderr go to the output file through file actions, the provider variables
(PRO_CONF_DIR, PRO_DATA_DIR, PRO_LOG_DIR, PROVIDER_NAME) are passed as the
child's envp (provider_env()), the child starts with an empty signal mask
and default dispositions, and waitpid() retries on EINTR.

The scaler unit suite (scaler/testsuite) was never built; it is now the
meson test "autoscaler test", linked with -Wl,--wrap=fork so it counts
fork() calls during a provider call.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:41:02 +00:00
ad6ce7eb1e
docs(buglog): record Gitea sync for bug-1968
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:27:50 +00:00
e88e440b7f
docs(buglog): bug-1968 fixed (restart carries only honoured options; Jsonb/resreq copies)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:23:45 +00:00
6a2c69f8bd
fix(apiserver): restart carries only the options a job gets (bug-1968)
RestartJobByID rebuilt the new job from the old job's row:
- it accepted asked_hosts and copied asked hosts, I/O paths and out_dir,
  which no job gets (refused at submit since bug-1936); restart now
  refuses asked_hosts with 400 and no longer carries those over;
- it read the JSONB columns chkpnt_info/extend_data as strings, but rows
  keep models.Jsonb, so env/limits were lost and a checkpointed job never
  restarted from its checkpoint; new rowJSON() reads both;
- it read "res_req" (the column is "resreq"), losing the resource
  requirement, and never copied exec_home.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:23:16 +00:00
801d26db06
docs(buglog): record Gitea sync for bug-1969
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 14:17:02 +00:00
ce3772868f
docs(spec): resource-provisioner decisions and research (language, in-memory lease, orphan cleanup)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:46:58 +00:00
832e397351
docs(buglog): log bug-1969 (autoscaler forks from a multi-threaded process)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:36:02 +00:00
6dd70f1091
feat(build): no fork in multi-threaded XCE processes, enforced by check-no-fork
Design constraint (tech.md "Process Creation"): the controller, scheduler,
xcecd and anything that starts libxce threads never call fork, vfork,
forkpty, daemon, system, popen or uv_spawn; children start with posix_spawn()
or a systemd unit. A process proven single-threaded may fork, marked
/* xce-fork-ok: <why> */. Tests, harness, autoscaler (not finalized; bug-1969)
and the Go frontend are out of scope.

- scripts/check-no-fork.py scans src/{controller,scheduler,lib,worker}
  (comment/string/#if 0 aware); runs as meson test "no-fork rule" in the
  lib/controller/scheduler/worker suites and in the pre-commit hook.
- worker: drop xcecd's unused fork-based worker start paths
  (process_manager_start_process, process_manager_start_worker; xcecd
  starts xcecd_worker over D-Bus) and a dead #if 0 daemonize fork.
- xcecd_worker's fork/uv_spawn/system calls are marked: its call graph
  from main(), callbacks included, reaches no pthread_create or libuv
  thread-pool call.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:35:52 +00:00
c4fee1077c
docs(buglog): record Gitea sync for bug-1936, bug-1955, bug-1967, bug-1968
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:14:37 +00:00
05465a20bf
docs(buglog): bug-1967, bug-1955, bug-1936 fixed; log bug-1968 (restart drops options)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 11:56:29 +00:00
edad8c7385
fix(apiserver): reject submit options the job never gets; add exec_home (bug-1936)
Cause: CreateJob accepted in_file, out_file, err_file, out_dir,
asked_hosts, begin_time, term_time and transfer_files and returned
success, but neither the controller's submit data/start info nor the
worker carries any of them (the worker never stages transferred files),
so they were silently dropped. Exec home had no submit field at all, and
a relative cwd would have been resolved against the worker unit's
directory.

Fix: new preCheckSubmitOptions() runs right after binding, before file
uploads and ID allocation, and answers 400 naming every unsupported
option that is set; cwd and the new exec_home field must be absolute and
fit the worker's job_assignment_t buffers (1023 bytes). exec_home goes
to JobInfo.ExecHome and from there (submitStartInfo) to the start info's
exechome. num_files already reaches exdata as nofile_limit; a handler
test now pins it. The array %J/%I submit-time substitution test (9.4)
checks cwd instead of out_file/err_file, which are now refused. Swagger
regenerated with `swag init -g cmd/main.go -o docs`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 11:49:28 +00:00
725b1d23fd
fix(worker): run the job in its cwd with HOME = exec home; apply nofile_limit (bug-1936)
Cause: the start info's execcwd/exechome reached xcecd and its worker-list
entry, but the MSG_JOB_ASSIGNED reply to the per-job xcecd_worker
(job_assignment_t) carried neither, and uv_proc_exec() spawned the job
with cwd NULL, so every job ran in the xcecd_worker unit's directory
whatever --cwd said, and exec home was never applied. parse_limits()
ignored the apiserver's "nofile_limit", so num_files never became an
rlimit.

Fix: job_assignment_t gets cwd/home, filled by the new
ipc_fill_job_assignment() (uv_ipc.c, which also NUL-ends every copied
string). xcecd_worker's job callback calls the new
uv_proc_enter_job_dirs() (uv_proc.c) before pre-exec and the job: it
exports HOME and chdir()s into cwd, falling back to /tmp with a warning
when the directory cannot be entered (the xcecd_worker runs as the job
user, so this is the user's own access). parse_limits() reads
nofile_limit into res_limits_t.nofile_limit and start_systemd_job() sets
LimitNOFILE like LimitNPROC. xcecd_virtual spawns no job and is
unaffected.

Tests: testsuite/test_job_dirs.c (assignment carries cwd/home, enter
cwd/home, fallback, a spawned job's pwd is the cwd) and
test_apiserver_nofile_limit_parsed in test_exdata_parse.c.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 11:49:28 +00:00
81e7187ddc
fix(worker): keep a job-control signal that reaches a remote host before its runtasks (bug-1955)
The controller sends job control to every host of a multi-host job
(bug-1942) as soon as the job is dispatched, but a remote host's runtasks
request is relayed by the controller (task.c do_runtasks, stateless) only
after the head worker has started and asked for it. A kill/stop that
reached a remote host first found no worker and no pending start, was
dropped ("Failed to find worker for job ID"), and the task started later
and kept running.

pending_signal now also holds "early" entries: handle_jobcontrol() records
a signal for a job with no task here (pending_signal_record_early), and
handle_runtasks() adopts it (pending_signal_start_task), so it is delivered
at RUNNING through the bug-1908 path and the task's exit is reported as
usual. Early entries are bounded (256) and expire after 60 s, pruned on
every early record and task start. A late control for a task that already
finished here (finished-job retention) is still dropped, and a head-host
start does not adopt an early entry, so neither can hit a later run of the
same jobid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 11:38:05 +00:00