Sprint Guide¶
What Is a Sprint?¶
A sprint is a named, persistent list of issues executed as a coordinated batch. It lives in .sprints/ as a YAML file, travels with your repository, and can be paused and resumed across sessions.
Why use a sprint instead of running issues one at a time?
- Batching — queue up a day or week of work, then execute hands-free
- Dependency awareness — the system computes execution order automatically; you don't sequence by hand
- Parallelism — independent issues run simultaneously in isolated worktrees
- Resume — if execution is interrupted, pick up exactly where you left off
The three batch tools each serve a different need:
| Tool | Best for |
|---|---|
ll-auto |
Sequential, unordered queue; simplest setup, no dependencies needed |
ll-parallel |
Ad-hoc parallel run of a few independent issues |
ll-sprint |
Curated list with dependency ordering, waves, file contention handling, and resume |
For anything beyond a few issues or anything with known dependencies, use ll-sprint.
How Waves Work¶
The most important concept in sprint execution is the wave. A wave is a group of issues that can run at the same time because none of them depend on each other.
The system computes waves automatically by performing a topological sort of the dependency graph:
Given issues and their blockers:
FEAT-001 (no blockers)
BUG-010 (no blockers)
FEAT-002 (blocked by FEAT-001)
FEAT-003 (blocked by FEAT-001)
FEAT-004 (blocked by FEAT-002, FEAT-003)
Wave 1: FEAT-001, BUG-010 ← parallel (no blockers)
Wave 2: FEAT-002, FEAT-003 ← parallel (Wave 1 done)
Wave 3: FEAT-004 ← solo (Wave 2 done)
You don't configure waves — you configure dependencies (via the blocked_by field in issue files), and the system derives the wave structure.
blocked_by vs depends_on¶
Two relationship fields affect sprint scheduling differently:
| Field | Arrow | Effect on sprint |
|---|---|---|
blocked_by |
──→ (hard dependency) |
Wave-gated — the dependent issue is held back until all listed issues are done |
depends_on |
--> (soft ordering) |
Not wave-gated — recorded for context and ll-deps validation but does not delay execution |
Use blocked_by when ISSUE-A cannot start until ISSUE-B is merged (e.g., ISSUE-A calls an API that ISSUE-B introduces). Use depends_on when the ordering is recommended but the issues can technically proceed in parallel (e.g., ISSUE-A tests a subsystem that ISSUE-B improves, but ISSUE-A is still valid without ISSUE-B).
Single vs. Multi-Issue Waves¶
- Single-issue wave: runs in-place without worktree overhead (fast path)
- Multi-issue wave: each issue runs in its own git worktree in parallel, up to
max_workersat once
File Contention Splitting¶
When two issues in the same wave touch the same files, running them in parallel would cause merge conflicts. The system detects this automatically using the Integration Map sections of each issue file, and splits the wave into sequential sub-waves:
Wave 2 (2 issues, serialized — file overlap [min_files=2, ratio=0.25]):
Step 1/2:
└── FEAT-002: Add middleware layer (P2)
Step 2/2:
└── FEAT-003: Update middleware config (P2)
Contended files: src/middleware.py, src/config.py
Tune: dependency_mapping.overlap_min_files / overlap_min_ratio in ll-config.json
Sub-waves are displayed as a single logical wave in the execution plan. The user sees "Wave 2 (serialized)" rather than two separate waves — the contention is handled transparently. The effective threshold values are shown in the wave header so users can tune dependency_mapping in ll-config.json if the sprint over-serializes.
Overlap detection AND semantics: Serialization is triggered only when both overlap_min_files and overlap_min_ratio are met simultaneously — not either one alone. This means an issue pair sharing 3 files out of 100 total (high count, low ratio) will not serialize unless both thresholds are crossed. Raise overlap_min_files or overlap_min_ratio in ll-config.json to reduce serialization for large issue sets.
Sprint File Anatomy¶
Sprint files live in .sprints/ and follow a simple YAML format:
name: bug-fixes
description: "All active P1-P2 bug fixes for the sprint"
created: "2026-02-13T10:00:00+00:00"
issues:
- BUG-372
- BUG-403
- BUG-415
options:
timeout: 3600
max_workers: 4
| Field | Required | Description |
|---|---|---|
name |
yes | Sprint identifier; used as filename (<name>.yaml) |
description |
no | Human-readable purpose for the sprint |
created |
yes | ISO 8601 timestamp; set automatically on creation |
issues |
yes | List of issue IDs (e.g., BUG-001, FEAT-010) |
options.timeout |
no | Per-issue timeout in seconds (default: 3600) |
options.max_workers |
no | Max parallel workers per wave (default: 2) |
options.max_iterations |
no | Max Claude iterations per issue (default: 100) |
Issue IDs in the sprint list are resolved to actual files at runtime. The sprint itself only stores IDs — the file search happens when you run.
Creating a Sprint¶
Interactive: /ll:create-sprint¶
The interactive skill walks you through sprint creation:
- Goal clarification — asks what you're trying to accomplish
- Auto-grouping — proposes issue groupings based on your backlog; you select or reject each
- Dependency validation — checks that blocked issues are included or have their blockers satisfied
- Confirmation — shows the proposed sprint before writing the YAML
The skill proposes six auto-grouping strategies:
| Strategy | Groups issues by |
|---|---|
| Priority cluster | P0-P1 together, P2-P3 together, etc. |
| Type cluster | All bugs, all features, all enhancements |
| No-blockers sprint | Only issues with no dependencies (fully parallelizable) |
| Theme-based | Keyword clusters: test coverage, performance, security, docs |
| Component/file-based | Issues touching the same files or directories |
| Goal-aligned | Mapped against ll-goals.md if present |
You can accept one strategy, mix strategies, or skip auto-grouping and specify issues directly.
Direct CLI¶
ll-sprint create sprint-name --issues BUG-001,FEAT-010,ENH-020
ll-sprint create sprint-name --issues BUG-001,FEAT-010 --description "Q1 fixes"
ll-sprint create sprint-name --issues BUG-001,FEAT-010 --max-workers 3 --timeout 7200
ll-sprint create sprint-name --issues BUG-001,FEAT-010,ENH-020 --skip BUG-001 # exclude specific IDs
ll-sprint create sprint-name --issues BUG-001,FEAT-010,ENH-020 --type bug,feat # filter by issue type
The CLI creates a sprint immediately without interactive prompting. Use this when you already know exactly which issues to include.
Reviewing Before Running¶
Before executing a sprint, especially if issues have been refined since the sprint was created, run a health check:
The skill performs a six-phase analysis:
- Staleness check — are issue files still current, or have they been superseded?
- Priority drift — have priorities changed since the sprint was built?
- Dependency cycles — would execution deadlock?
- File contention warnings — which issues will serialize and why?
- Backlog scan — are there related issues not in the sprint that belong?
- Removal proposals — issues that are completed, invalid, or out of scope
The skill is interactive: it proposes changes and you approve or reject each one. Accepted changes are applied via ll-sprint edit. When you're done reviewing, the sprint is ready to run.
When to review: any time more than a day has passed since you built the sprint, or after running
/ll:refine-issueor/ll:verify-issueson issues in the sprint.
Running a Sprint¶
ll-sprint run sprint-name
ll-sprint run sprint-name --dry-run # show plan without executing
ll-sprint run sprint-name --max-workers 3
ll-sprint run sprint-name --timeout 7200
ll-sprint run sprint-name --skip BUG-010 # exclude specific issues
ll-sprint run sprint-name --only BUG-001,FEAT-010 # run only these issues (allowlist)
ll-sprint run sprint-name --type bug,feat # filter by issue type at run time
ll-sprint run sprint-name --skip-analysis # bypass pre-execution dependency analysis
ll-sprint run sprint-name --quiet # suppress progress output
ll-sprint run sprint-name --handoff-threshold 80 # context window handoff threshold (1–100)
The --handoff-threshold flag controls when Claude Code hands off to a fresh session mid-issue. During a long-running issue, Claude's context window fills up as it reads files, runs tools, and accumulates output. When context usage reaches the threshold (expressed as a percentage from 1 to 100), the runner writes a continuation prompt and starts a new session to complete the remaining work. Lower values trigger handoff earlier and more conservatively; higher values let sessions run longer before handing off. The default is 80 (hand off at 80% context usage).
Pre-flight¶
Before the first wave runs, ll-sprint validates the sprint:
- Issue files exist on disk
- No dependency cycles
- Wave structure computed and displayed
- Issues with
status: doneorstatus: cancelledin frontmatter are auto-skipped silently; if all issues are already completed, the sprint exits with success immediately
The execution plan is printed before any work begins:
======================================================================
EXECUTION PLAN (5 issues, 3 waves)
======================================================================
Wave 1 (parallel):
├── FEAT-001: Add middleware layer (P2)
└── BUG-010: Fix null check in parser (P1)
Wave 2 (parallel, after Wave 1):
├── FEAT-002: Extend middleware config (P2)
│ └── blocked by: FEAT-001
└── FEAT-003: Update middleware tests (P2)
└── blocked by: FEAT-001
Wave 3 (serial, after Wave 2):
└── FEAT-004: Integration tests for middleware (P3)
blocked by: FEAT-002, FEAT-003
======================================================================
DEPENDENCY GRAPH
======================================================================
FEAT-001 ──→ FEAT-002 ──→ FEAT-004
FEAT-001 ──→ FEAT-003 ──→ FEAT-004
Legend: ──→ blocks (must complete before)
Use --dry-run to see this plan without executing anything.
Wave Execution¶
Each wave runs as follows:
- Single-issue wave:
/ll:manage-issueruns in-place (no worktree overhead) — this is the same skill used for individual issue implementation, invoked automatically by the sprint runner - Multi-issue wave:
ParallelOrchestratorcreates a git worktree for each issue, runs them in parallel, then the merge coordinator integrates results. Withuse_feature_branches: trueinll-config.json, auto-merge is skipped and each issue produces a PR-readyfeature/<id>-<slug>branch instead — use this for PR-based CI/CD workflows.
After each wave completes:
- State is checkpointed to .sprint-state.json
- Execution continues to the next wave
Failed Issues¶
If an issue fails during a multi-issue parallel wave, the runner:
- Records the failure
- Retries once sequentially (outside the worktree)
- If the retry also fails, marks it as failed and continues with the next wave
Issues that fail in a single-issue wave are immediately marked as failed — no retry is attempted.
A sprint with some failures still completes — it doesn't stop at the first failure. Failed issues are reported in the summary with their reason.
Graceful Shutdown¶
Send Ctrl+C once to request graceful shutdown. The runner finishes the current wave, saves state, and exits. Send Ctrl+C again to force immediate exit (state is still saved before exit).
Handling Interruptions (Resume)¶
If a sprint is interrupted — by Ctrl+C, a system restart, or a tool crash — you can resume it exactly where it left off using ll-sprint run sprint-name --resume. Sprint state persists across interruptions. The state file lives at .sprint-state.json in the repository root and contains:
- Sprint name and which wave is current
- Completed and failed issue IDs
- Per-issue timing
- Start time and last checkpoint timestamp
State is checkpointed after each wave (not after each issue). This means:
- If execution stops mid-wave, that wave's issues restart from scratch on resume
- If execution stops between waves, resume starts cleanly at the next wave
To resume an interrupted sprint:
The runner reads .sprint-state.json, finds the first incomplete wave, and starts there. Completed issues from earlier waves are skipped automatically.
State is automatically deleted when the sprint completes successfully. If you want to force a fresh start (discarding resume state), run without --resume:
Editing a Sprint¶
Add or remove issues from an existing sprint:
ll-sprint edit sprint-1 --add BUG-099,FEAT-020 # add issues
ll-sprint edit sprint-1 --remove BUG-010 # remove issues
ll-sprint edit sprint-1 --prune # remove completed/invalid refs
ll-sprint edit sprint-1 --revalidate # re-run dependency analysis
ll-sprint delete sprint-1 # delete a sprint entirely
--prune scans each issue ID in the sprint and removes any that no longer have a file on disk (either completed and archived, or deleted). Use this to clean up a sprint that's been running for a while.
--revalidate re-reads the dependency graph after edits and updates any ordering implications. Run this after adding new issues to ensure wave groupings are still accurate.
Edit vs. recreate: Edit when you're making minor adjustments to an existing sprint. Recreate (delete + create) when the scope has changed significantly or you want /ll:create-sprint to re-run its auto-grouping logic.
Inspecting Sprints¶
ll-sprint list # all sprints, one per line
ll-sprint list --verbose # sprints with issue counts and descriptions
ll-sprint list --json # output as JSON array
ll-sprint show sprint-1 # sprint details + wave visualization
ll-sprint show sprint-1 --json # structured JSON output
ll-sprint show sprint-1 --skip-analysis # skip dependency analysis step
ll-sprint analyze sprint-1 # file conflict analysis
ll-sprint analyze sprint-1 --format json
ll-sprint show is the primary inspection command. It displays the sprint YAML contents, validates that all issue files exist, and renders the dependency graph and wave structure — the same execution plan you'd see at the start of a run. The output also includes:
- Composition breakdown — issue count by type (BUG/FEAT/ENH/EPIC) and priority distribution
- Sprint run state — progress from
.sprint-state.jsonif the sprint has been started - Readiness/confidence scores — per-issue scores from any completed confidence checks
- Issue file paths — full paths shown in the execution plan for easy navigation
- Human-friendly timestamps — relative time suffixes (e.g., "3 days ago") on dated fields
Use --json to get all fields as structured JSON for scripting or integration.
ll-sprint analyze focuses specifically on file overlap. It reads each issue's Integration Map and reports which files are touched by multiple issues, which pairs would contend, and which would be forced into sub-waves. Use this when planning a sprint with many issues touching the same subsystems.
Configuration¶
Sprint behavior is configured in .ll/ll-config.json under the sprints key:
| Option | Default | Description |
|---|---|---|
sprints_dir |
.sprints |
Directory where sprint YAML files are stored |
default_timeout |
3600 |
Per-issue timeout in seconds (1 hour) |
default_max_workers |
2 |
Max parallel workers per wave |
Per-sprint options (in the YAML options block) override the project config for that sprint. CLI flags (--max-workers, --timeout) override both.
Common Recipes¶
Quick Bug-Fix Sprint¶
Capture recent bugs, enrich them, and run a sprint in one session:
1. /ll:capture-issue "description of bug 1"
/ll:capture-issue "description of bug 2"
/ll:capture-issue "description of bug 3"
2. /ll:format-issue --auto
3. /ll:refine-issue
4. /ll:ready-issue
5. /ll:create-sprint ← pick "all bugs" auto-group
ll-sprint run bug-sprint
Themed Sprint (Test Coverage)¶
Build a sprint from issues related to a specific theme:
1. /ll:scan-codebase ← discovers test gaps as ENH issues
2. /ll:prioritize-issues
3. /ll:tradeoff-review-issues
4. /ll:create-sprint ← pick "theme: test coverage" auto-group
5. /ll:review-sprint test-sprint ← health check before running
ll-sprint run test-sprint
Sprint with Dependencies¶
When issues have a natural ordering, dependency-aware sprinting is the key advantage:
1. Create issues with blocked_by (hard) or depends_on (soft) fields:
FEAT-010 has no blockers
FEAT-011 blocked_by: [FEAT-010] # hard stop — wave-gated
FEAT-012 depends_on: [FEAT-010] # soft ordering — not wave-gated
FEAT-013 blocked_by: [FEAT-011, FEAT-012]
2. /ll:map-dependencies ← validates the graph, proposes missing edges
3. ll-sprint create feature-sprint --issues FEAT-010,FEAT-011,FEAT-012,FEAT-013
4. ll-sprint show feature-sprint ← confirm wave structure:
Wave 1: FEAT-010
Wave 2: FEAT-011, FEAT-012 (parallel)
Wave 3: FEAT-013
5. ll-sprint run feature-sprint
Resume an Interrupted Sprint¶
# Sprint was interrupted mid-run
ll-sprint run sprint-name --resume ← finds .sprint-state.json, continues
# Or inspect state first
ll-sprint show sprint-name ← see which issues completed/failed
ll-sprint run sprint-name --resume
Picking Up After a Partial Failure¶
When a sprint finishes but some issues failed, address failures without re-running the whole sprint:
1. ll-sprint show sprint-name ← review which issues failed and why
2. /ll:refine-issue ISSUE-ID ← investigate and update each failed issue
3. ll-sprint edit sprint-name --prune ← remove any issues that are now completed/invalid
4. ll-sprint run sprint-name --only FAILED-ID-1,FAILED-ID-2
← re-run only the failed issues
5. ll-sprint show sprint-name ← confirm all issues completed
If a failed issue blocks downstream issues, fix it first — the wave structure ensures dependents run after.
Pre-PR Quality Sprint¶
Run code quality loops before opening a PR, then address any issues found:
1. /ll:check-code all ← run lint, types, and format checks
2. /ll:scan-codebase ← capture any issues found
3. /ll:create-sprint ← sprint the findings
4. ll-sprint run quality-fixes
5. /ll:open-pr
Full "Plan a Feature Sprint" Pipeline¶
The complete workflow from empty backlog to executed sprint is documented in detail in the Issue Management Guide. That guide covers every refinement step — discovery, enrichment, quality gates, and dependency mapping — before handing off to ll-sprint for execution. Start there if you are setting up a sprint from scratch.
See Also¶
- Issue Management Guide — refinement pipeline to run before sprint creation
- Loops Guide — create custom FSM loops for recurring sprint workflows
/ll:map-dependencies— discover and validate cross-issue dependencies before building a sprint/ll:issue-size-review— decompose oversized issues before adding them to a sprint/ll:review-sprint— health check an existing sprint before runningll-sprint --help— full CLI reference for all subcommands and flags