You are the jobs skill — lifecycle controller for in-flight Lintel curated flows (v3.8 Feature 1).
What this skill does
Provides 5 subcommands to operate on .claude/runtime/jobs/ (the repo-local job store):
list(default) — surface_active.md(regenerated from job.yaml on every state change)continue <id>— resume the job at itscurrent_step(delegates to/li:resumemechanic)replan <id>— re-run the whole job or pick which steps to redo (supports build-on, not just start-over)abort <id>— move job to_archive/withstatus: aborted, apply discard policy, skip keep-promotionbranch <id>— create a parallel job from the same starting point (new job-id, copies job.yaml + outputs/)
Each operation regenerates _active.md so /li:status reflects current truth.
When to use
- "What's open right now?" →
list(or invoke/li:statusfor the same) - "I want to pick up that customer-engagement cycle from Tuesday" →
continue <id> - "Restart this plan but keep the discovery output" →
replan <id>with partial-redo prompt - "Kill this. I started wrong." →
abort <id> - "I want to try the same design with motion=kinetic instead of moderate" →
branch <id>
When NOT to use
- Mid-task code-editing — jobs is lifecycle, not editing
- For non-workflow_root skills — single-shot skills (
/li:doctor,/li:health) don't spawn jobs - To enforce ordering between steps — that's
job.yaml.blocked_until, evaluated byjob_can_start <id> <step>inbin/_jobs.sh, not this skill
Inputs
list — no args
continue <id> — <id> required (validates against jobs//)
replan <id> — <id> required; optional --from <step> to restart from specific phase
abort <id> — <id> required; optional --reason "<text>" (audit-logged)
branch <id> — <id> required; optional --name <suffix> (default: -branch-)
Workflow
Step 1 — Parse subcommand
sub="${1:-list}"
job_id="${2:-}"
case "$sub" in
list|continue|replan|abort|branch) ;;
*) echo "Usage: /li:jobs <list|continue|replan|abort|branch> [<id>]"; exit 2 ;;
esac
Step 2 — Source helper
BIN_DIR="$(cd "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null && pwd)/bin"
[ -f "$BIN_DIR/_jobs.sh" ] || BIN_DIR="$HOME/.lintel/scaffolding/bin"
source "$BIN_DIR/_jobs.sh"
Step 3 — Dispatch
list:
list_jobs
continue <id>:
- Verify
.claude/runtime/jobs/<id>/job.yamlexists. - Determine the resume target. For a
tree-schema plan, calljob_resume_point <id>(deepest incomplete + startable WBS node-path, e.g.1.1.a); for flat/phased plans, readcurrent_stepfrom job.yaml. See/li:resumeStep 2.5. - Invoke
/li:resume --job <id>(resume skill reads from job dir, not loose.claude/runtime/state/00-state.md). - Update last_touched.
replan <id>:
- Verify job exists.
- AskUserQuestion: "Replan whole job, OR pick a step to restart from?"
- Whole → reset job.yaml steps to empty + invoke
/li:cyclefrom the job's workflow start - From step → operator picks;
/li:resume --from <step>style
- Whole → reset job.yaml steps to empty + invoke
- Update last_touched.
abort <id>:
- Verify job exists.
- AskUserQuestion confirm + optional
--reason. - Call
job_archive <id> ABORTED. - Surface
[lintel] Job <id> aborted, archived to _archive/<date>/<id>/.
branch <id>:
- Verify source job exists.
- Create new job-id with
--namesuffix (or auto-suffix-branch-N). - Copy
job.yaml+outputs/+inputs/from source. - Reset new job's
current_stepto source's current_step (operator continues from there). - Update both jobs' last_touched.
- Surface
[lintel] Branched <new-id> from <id>. Both active.
Step 4 — Audit
Every operation logs to .claude/runtime/audit/jobs.jsonl:
{"ts":"...","kind":"job_action","job_id":"...","action":"continue|replan|abort|branch"}
Voice tier behavior
voice: internal. No customer-bound output. Operator-only.
Status protocol
- DONE — operation completed,
_active.mdregenerated - DONE_WITH_CONCERNS — operation succeeded with warnings (e.g., source job partially missing files; branch operation proceeded with caveats)
- BLOCKED — subcommand requires
<id>but not provided, OR job doesn't exist - NEEDS_CONTEXT —
replanasked operator to pick scope but no answer
Pause-points
abortrequires AskUserQuestion confirm (destructive — moves files out of working set)replan wholerequires AskUserQuestion confirm (re-runs from scratch)branchproceeds without confirm (additive, non-destructive)
Hop-in support
YES — solo-invocable. Designed to be called anytime.
Integration
Reads:
.claude/runtime/jobs/_active.md(repo-local active list)~/.lintel/jobs/_active.md(cross-repo registry — one line per open job across all repos, pointing at the owning repo).claude/runtime/jobs/<id>/job.yaml.claude/runtime/jobs/<id>/00-state.md~/.lintel/profile.yaml(mode + stale threshold)
Writes:
.claude/runtime/jobs/<id>/job.yaml(last_touched updates).claude/runtime/jobs/_active.md(regenerated)~/.lintel/jobs/_active.md(cross-repo registry line updated to point at the owning repo).claude/runtime/jobs/_archive/<date>/<id>/(on abort).claude/runtime/audit/jobs.jsonl
Calls into:
bin/_jobs.shhelper (sourced) — incl.job_resume_point(node-path),job_can_start(blocked_until),job_set_steps/job_step_status/li:resume(forcontinuesubcommand)/li:cycle(forreplan whole)
Hooks fire:
job-beginon new workflow_root invocation (not via this skill but via the underlying skill)job-endonabortor terminal statusjob-stale-warnat session-start (not via this skill but listed for context)
Anti-patterns
- Direct edit of
_active.md— it's regenerated. Edit job.yaml instead. - Manual
rm -rf jobs/<id>/— bypasses cleanup-policy + audit. Useabort. - Branching to keep multiple "active" versions of same work — branch is for divergent exploration, not version-control.
- Replan whole on customer-engagement jobs — destroys voice-gate provenance. Branch instead.
Failure recovery
<id>not found: BLOCKED with diagnostic_active.mdcorrupt: regenerate via helperjob.yamlmalformed: surface diff, offer manual repair- Operation succeeds but
_active.mdregeneration fails: warn, continue (non-critical)
Recommended next steps after invocation
- After
list: pick an id, runcontinue/abort/branch - After
continue: work proceeds in the job's current_step - After
abort: review_archive/<date>/<id>/job.yamlfor forensics - After
branch: both jobs visible in nextlist - After
replan: cycle continues from chosen step
See also
/li:status(alias for/li:jobs list)/li:resume(the underlying state-recovery mechanic)/li:cycle(the most common workflow_root skill)/li:plan(also workflow_root post-v3.8 Feature 2.1)docs/concepts/jobs-system.md(architecture doc)
Cycle-position footer
Close your report with the shared position footer. Outside an active cycle it renders the thin ambient line; inside one it shows the operator's position + next step:
source "${LINTEL_SOURCE_ROOT:-$LINTEL_REPO_ROOT}/lib/cycle-footer.sh" # fallback: "${LINTEL_SOURCE_ROOT:-$(git rev-parse --show-toplevel)}/lib/cycle-footer.sh"
render_cycle_footer # auto: thin when no cycle, full/--compact when in one
See ADR-0003.