docs(steering): one owner per job attribute; pre/post-exec moves to the app profile

New steering job-config-layering.md: queue = scheduling policy, application
profile = what the application needs and how it runs (resreq, task range,
execution settings, pre/post-exec, limits), project = resource ownership.
Only two interactions: the job overrides a profile attribute marked
default (fixed: not at all; select: only ANDed terms), and queue ceilings
or project quotas check effective values (reject if never satisfiable,
pend if full now). Replaces the simplified job > app > queue rules.

Queue pre_exec/post_exec are deprecated with queue res_req: the profile's
pre/post-exec fills the worker's existing outer layer, the job's own stays
the inner layer, allowed or forbidden by the profile.

job-config-merge and application-profile briefs and the roadmap follow;
CLAUDE.md lists the new steering file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-10 03:19:20 +00:00
parent b761878b58
commit 25cdbc79b4
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
5 changed files with 123 additions and 21 deletions

View file

@ -13,10 +13,18 @@ decisions):**
requirement* (select / rusage / `span[...]` / same) and task limits
(min / default / max, LSF TASKLIMIT), **project** = resource ownership
(`project-config`).
- How the levels combine is owned by **`job-config-merge`**: job overrides
profile section by section, `select` is ANDed, queue hard and task limits
are ceilings that reject. This answers the open question "how resource
defaults combine with a job's own resreq" below.
- Every attribute has one owning level (`.kiro/steering/job-config-layering.md`).
How the levels interact is owned by **`job-config-merge`**: each profile
attribute is *default* (the job may replace it) or *fixed* (the job may
not; for `select` it may only add ANDed terms); queue ceilings and project
quotas only check, never change, the job's values. This answers the open
question "how resource defaults combine with a job's own resreq" below.
- **Pre/post-exec moves here from the queue** (queue `pre_exec`/`post_exec`
deprecated). The profile's pre/post-exec is admin-defined and always runs
as the outer layer; the job's own pre/post-exec is the inner layer, allowed
or forbidden by the profile. Order: profile pre → job pre → job → job post
→ profile post (the worker's existing two-layer structure,
`xcecd_worker.c` `queue_pre_exec()`/`queue_post_exec()`).
- **Replaces "Resolution at submit time"** below: the merge is *live*. The WAL
keeps the job's own values plus the profile name; the controller and
apiserver validate at submit, and the scheduler computes effective values

View file

@ -45,18 +45,23 @@ apiserver and display would disagree about what a job actually asked for.
application profile, the queue's policy and the project; output is the
job's **effective** values: resreq (select / rusage / span / same /
order), task range, execution limits, pre/post-exec, environment.
- **Merge rules (simplified, user decision 2026-10-09; deliberately not
LSF's full per-section rules):**
- The resreq has two levels only, app profile and job (queues carry no
resreq, see below). The job overrides the app section by section;
`select` is the exception: both apply (ANDed).
- Everything else: job overrides app overrides queue defaults.
- Queue **hard limits** and queue **task limits** are ceilings: a job (or
app) value outside them is rejected at submit, never silently clipped.
- The application profile's task limits (min/default/max) also bound the
job's `-n`; with no `-n`, the app default applies (LSF p660 semantics).
- Where the simplified rules diverge from LSF, the requirements list the
divergence explicitly (input for `lsf-config-migration`).
- **Merge rules: one owner per attribute** (user decisions 2026-10-09; the
full rule set is `.kiro/steering/job-config-layering.md`). Every attribute
has exactly one owning level (queue = scheduling policy, application
profile = what the application needs and how it runs, project = resource
ownership), so only two interactions exist:
- **Override (job vs. profile):** each profile attribute is *default* (the
job's value replaces it) or *fixed* (the job cannot change it; for
`select` the job may only add ANDed terms). This replaces LSF's
per-section merge table.
- **Ceiling (queue or project vs. effective values):** never changes a
value; a never-satisfiable value (runtime above the queue maximum, task
range above the queue's max tasks) is rejected at submit, a quota that is
only full now makes the job pend with a reason naming the queue/project.
- The profile's task limits (min/default/max) bound the job's `-n`; with no
`-n`, the profile default applies.
- Where this diverges from LSF, the requirements list the divergence
explicitly (input for `lsf-config-migration`).
- **Live merge (user decision 2026-10-09).** The WAL keeps the job's own
values plus the names of its queue, profile and project. The merge runs:
- at submit, in the controller (authoritative for every submit path) and
@ -66,8 +71,13 @@ apiserver and display would disagree about what a job actually asked for.
upgrade). A pending job that no longer satisfies the merged values pends
with a clear reason (LSF: "Job no longer satisfies TASKLIMIT
configuration"); running jobs are unaffected.
- **Queue is policy only (user decision 2026-10-09).** Queue `res_req` is
deprecated: warned on by `xceadmin config build` first, then rejected.
- **Queue is policy only (user decision 2026-10-09).** Queue `res_req`,
`pre_exec` and `post_exec` are deprecated: warned on by `xceadmin config
build` first, then rejected. Pre/post-exec moves to the application
profile: the controller fills the worker's outer pre/post-exec layer (today
the queue's, `get_queue_exec()`, `controller/queue.c:199`, called at
dispatch `job.c:1827`) from the profile; the job's own pre/post-exec stays
the inner layer, allowed or forbidden by the profile.
The queue limits `xceadmin` drops today (cpulimit, memlimit, runlimit,
task limit) are wired through config, capnp and the merge as hard limits.
- **Visibility.** Job details (REST, `xcecli`, REPL `info job`, decision
@ -86,7 +96,8 @@ values and the three names must round-trip).
- **In**: the merge library and its rules; controller and apiserver submit
validation; scheduler effective-value computation and re-evaluation on
config change; queue hard/task limit wiring (YAML, schema, `mapping.py`,
capnp, C); queue `res_req` deprecation; effective values in job details and
capnp, C); queue `res_req` and pre/post-exec deprecation; outer
pre/post-exec sourced from the profile; effective values in job details and
the decision trace; tests.
- **Out**: the profile model itself (`application-profile`); project
definitions (`project-config`); `span` placement semantics