submit-wandb-job
Submit one or more wandb-logged training/finetuning runs to the HPC scheduler. `WANDB_PROJECT` is fixed per repo (snake_case basename); `WANDB_RUN_GROUP` is picked per invocation. The training script
Files1
View on GitHubSKILL.mdskills/submit-wandb-job/SKILL.md
GitHubSubmit wandb Job
Enforces a wandb/commit contract on top of cluster-instructions. For training/finetuning runs that log to wandb — not eval-only jobs.
Contract
| Env var | Value | Scope |
|---|---|---|
WANDB_PROJECT |
.env: WANDB_PROJECT or snake_case repo basename |
constant per repo |
WANDB_RUN_GROUP |
user, per invocation (tmp for one-offs) |
one per invocation |
WANDB_NAME |
<group>__<tag> |
one per job |
The skill exports these env vars in the job script. The experiment/group name must be a config key in the training script (e.g. Hydra meta.experiment_name, or whatever the project's equivalent is) — the user's command should include the override (e.g. ... meta.experiment_name=<group>) so the training code receives the same value the skill sets in WANDB_RUN_GROUP. If the training script hardcodes the experiment name or the wandb project, that's a real bug in the project — surface it and ask the user to fix it; don't paper over it from this skill.
Step 0 — Pre-flight
git rev-parse --show-toplevel # → REPO_ROOT; bail if not a git repo
git symbolic-ref -q HEAD # → branch ref; empty + non-zero exit = detached
git status --porcelain # → DIRTY (string)
Also read .env (walking up from $PWD to $REPO_ROOT) and capture JOBS_DIR and LOGS_DIR if defined — Step 2 and Step 5 both need them. Fall back to $REPO_ROOT/jobs and $REPO_ROOT/logs respectively if unset.
Refuse on: not a git repo. On detached HEAD (Step 0's git symbolic-ref returned non-zero), ask once whether to proceed against the bare SHA — abort if the user says no.
Step 1 — Project (constant)
.env: WANDB_PROJECT if set, else snake_case of basename $REPO_ROOT (lowercase, - → _, strip non-[a-z0-9_], collapse _). Show it to the user. If they override, ask whether to persist the override into .env (so it stays constant next time) — don't write silently.
Step 2 — Group
If --one-off was passed, set group = tmp and skip the picker. If --group <name> was passed or the user named a group in the conversation, use that.
Otherwise gather candidates and ask:
$JOBS_DIR/<project>/*/— prior groups from this skill (skip ifJOBS_DIRis unset).$LOGS_DIR/wandb/run-*/files/config.yaml— grepgroup:, dedupe, cap at 10 most recent (skip ifLOGS_DIRis unset).- A fresh slug from a salient piece of the user's command, only if the command actually hints at one.
Present via AskUserQuestion with up to 3 existing groups + tmp as a first-class option + Other. If one existing group is a strong semantic match for what the user is running ("another seed for the dropout sweep" + an existing mlm_tune_dropout), recommend it explicitly. If there are no candidates at all, ask freeform.
Validate: [A-Za-z0-9_.-]+, non-empty, no whitespace.
Step 3 — Commit gate
If DIRTY is empty: capture HEAD_SHA, continue.
If DIRTY non-empty and --skip-commit-check: capture HEAD_SHA, set commit_pinned=false, continue (warn in the final report).
Otherwise show git status --short + git diff --stat, then ask once via AskUserQuestion:
- Commit (recommended) —
git add -u, propose a one-liner from the diff,git commit(let hooks run; never--no-verify). Re-stage and retry once if hooks rewrite. Verify clean, then capture newHEAD_SHA. - Bypass —
commit_pinned=false. Report will flag it. - Cancel — abort.
Don't include untracked files unless the user says so.
Step 4 — Per-job details
Ask for N if not in $ARGUMENTS (default 1). For each job collect:
- Command — full invocation (user usually states it; ask if not). Skill is agnostic to Hydra/argparse/CLI shape — don't parse it, but do check that the command sets the experiment/group name as a config key (e.g.
meta.experiment_name=<group>). If it doesn't, ask the user to add it before continuing — theWANDB_RUN_GROUPenv var alone won't reach a Hydra config. - Tag — short, used in
WANDB_NAMEand the script filename (lr1e-3,seed42). Default toj<i>or a salient=valuefrom the command if the user omits one. Validate the same way as the group:[A-Za-z0-9_.-]+, non-empty, no whitespace.
If N > 1 and the user hasn't said how the jobs differ, ask — don't invent ablations.
Step 5 — Cluster + paths
Invoke cluster-instructions (Skill tool) for scheduler detection and templates. Don't submit from this skill directly. mkdir -p $JOBS_DIR/<project>/<group>/logs (using the JOBS_DIR resolved in Step 0). The <project> outer level matches monitor-jobs' documented $JOBS_DIR/<project>/ layout; <group> nests inside so related runs cluster on disk too.
Step 6 — Generate scripts
One script per job at $JOBS_DIR/<project>/<group>/<group>__<tag>.{sh,batch}. Use the scheduler header from cluster-instructions. Before the user's command:
export WANDB_PROJECT="<project>"
export WANDB_RUN_GROUP="<group>"
export WANDB_NAME="<group>__<tag>"
cd "$REPO_ROOT"
Logs to logs/<group>__<tag>.out (PBS) or logs/<group>__<tag>_%j.out (SLURM), relative to the submission dir — matches monitor-jobs expectations.
Show the scripts (cat) and pause for confirmation if N > 3 or commit_pinned=false. Otherwise just submit.
Step 7 — Submit
sbatch / qsub per script. Capture job IDs as you go. On any failure, stop — don't retry, don't continue to the next job. If jobs k+1..N failed but jobs 1..k already made it into the queue, list those job IDs and ask via AskUserQuestion whether to scancel / qdel them or leave them running. Don't auto-cancel; the user may want the already-submitted runs to proceed.
Step 8 — Report
## Submitted <N> job(s) to <cluster>
- **project**: `<project>` **group**: `<group>`
- **commit**: `<short-SHA>` — `<subject>` <!-- or "dirty submit — not pinned" if commit_pinned=false -->
- **logs**: `<absolute path>`
| # | Job ID | Tag | Script | Log |
|---|---|---|---|---|
Monitor: `/softnano:monitor-jobs`.
Repeat the dirty-submit warning at the bottom if applicable.
Hard rules
- Never edit the user's training code to fit the env contract — if it hardcodes the project or experiment name, surface it and let the user fix it.
- Wandb auth (
WANDB_API_KEY/~/.netrc) is not this skill's problem — let the job fail at runtime if it's missing.