wait-for-results
Block on one or more long-running jobs until they finish, then run the follow-up step the work needs (combine, build, deploy, report). Because the wait may outlive the session, this skill leads with a handoff so state is never lost.
When this fires
- “wait for results”, “wait for the jobs”, “poll until done then
”. - Right after launching a long job (SLURM array, CI run, background task, remote agent) that you intend to act on at completion.
Step 1 — Hand off first (always)
Invoke the handoff skill immediately, before waiting. This snapshots the branch/HEAD/unpushed commits/job IDs/pick-up steps into a project memory and posts a paused-state note on any active PR/MR. The point: if the session ends or context resets while you’re waiting, the next session resumes cleanly with zero lost state.
Refresh the handoff (re-run it) if the situation materially changes during the wait — a job fails, the plan changes, or new commits land.
Step 2 — Identify what to wait on and the success condition
Pin down, concretely: - What the jobs are — SLURM array IDs, background task IDs + output files, CI run, etc. - The done condition — squeue empty, expected output-file count reached, gh run watch exits, a sentinel file appears. - The follow-up step to run on success (e.g. combine-slurm-results.R), and what counts as failure (missing chunks, non-zero exit, error in logs).
Step 3 — Poll on a sensible cadence
Pick the waiting mechanism by whether the wait must survive the session ending or a context reset:
ScheduleWakeup(primary for cross-session survival). Schedule a re-invocation with a cadence matched to the job and a long fallback heartbeat. This is the only mechanism that wakes the model back up after the current session has ended, so prefer it whenever the wait may outlive the session.- Background Bash loop (same-session short waits). Run the poll as a background Bash command so the session stays responsive; the harness re-invokes you when the command exits — but only while this session is still alive. If the session has already ended, a finished loop wakes nobody, so don’t rely on it to survive a reset.
Either way, match the cadence to how fast the state actually changes; don’t burn cycles polling every few seconds for a multi-hour job.
# Same-session example: wait for a SLURM array, then verify chunk count
for i in $(seq 1 240); do
sleep 60
if [ -z "$(squeue -u "$USER" --name=<job-name> 2>/dev/null | tail -n +2)" ]; then
echo "JOBS DONE (check $i); outputs: $(ls <output-glob> 2>/dev/null | wc -l)"
break
fi
done
# Fallback: the loop has a silent 4-hour ceiling (240 × 60s). If it exhausted
# without breaking, the jobs are still running — make that observable.
if [ "$i" -eq 240 ] && [ -n "$(squeue -u "$USER" --name=<job-name> 2>/dev/null | tail -n +2)" ]; then
echo "TIMEOUT: jobs still running after 240 checks — run a fresh handoff and check manually."
fiStep 4 — On completion, verify then run the follow-up
- Verify the success condition before acting — e.g. expected output count, no failures in
logs/, clean exit. If the jobs failed or came up short, stop and report rather than running the follow-up on bad inputs. - Run the follow-up step, capture its output, and sanity-check the result.
- Update the handoff memory to reflect the new state (jobs done, results produced, next action), and update or close the PR paused-note accordingly.
- Recap to the user with a local-time stamp: what finished, what the follow-up produced, and what’s next.
Relationship to other skills
handoff— run first (Step 1) and refreshed at the end; this skill includes it so the wait is crash-safe.memories/preferences.md(the “always leave handoff notes proactively” bullet) — the policy that makes Step 1 mandatory.claim-pr— the paused note posted viahandofflives inside an existing claim.