workflow
How Launchpad keeps BACKLOG.md and TASKS.md from rotting. Includes the WP template, path-scoped rules, and the staleness hook that catches drift.
init generates three files that together form a workflow: CLAUDE.md (what Claude knows), TASKS.md (what we're doing now), BACKLOG.md (what we're doing later). Without structure, those files rot. TASKS.md balloons past 200 lines, BACKLOG.md becomes a dumping ground, and the same work package ends up in both files at once.
v1.10.0 ships three things to stop the rot: a typed work-package template, a path-scoped rule file Claude auto-loads when editing those files, and a PostToolUse hook that warns on four staleness conditions.
The single rule
A work package (WP) lives in exactly one of BACKLOG.md or TASKS.md at any time.
- Pulled into a sprint → move (delete from BACKLOG, add to TASKS) in a single edit.
- Sprint closed → the WP leaves TASKS entirely (summarized into Completed Sprints) and does not return to backlog.
- A WP ID appearing in both files at once is a drift bug. The workflow hook catches it.
Everything else in this page enforces that rule.
BACKLOG.md template
init (and doctor --fix, when BACKLOG.md is missing) writes this structure:
# <project> — Backlog
> Single source of truth for future work. Rules in .claude/rules/workflow.md.
## Priority definitions
| Priority | Meaning |
|---|---|
| **P0** | Blocks launch or an active sprint. Next sprint or sooner. |
| **P1** | Important for MVP. Pulled within 2–3 sprints. |
| **P2** | Post-MVP or nice-to-have. Review monthly. |
| **P3** | Parked idea. Review quarterly; delete if still untouched. |
## Work package template (copy this exactly)
### WP-NNN — <short imperative title>
- **Priority:** P0 | P1 | P2 | P3
- **Proposed:** YYYY-MM-DD
- **Stories / Docs:** links to specs, issues, or "none yet"
- **Depends on:** WP-MMM (empty if none)
- **Estimate:** XS (<1h) | S (half-day) | M (1–2 days) | L (full sprint) | XL (>1 sprint; must decompose)
- **Trigger to pull:** What has to be true before this moves into a sprint.
- **Definition of done:** Exactly what "done" looks like.
One-paragraph description.
## P0 — Next sprint
## P1 — Soon (within 2–3 sprints)
## P2 — Post-MVP / nice-to-have
## P3 — Parked
## ChangelogEvery WP entry must include all 7 fields. Free-form entries are a drift signal. XL estimates must be decomposed before they can enter a sprint.
doctor --fix never overwrites an existing BACKLOG.md. If you migrated from a freeform backlog, your content is preserved verbatim; doctor just flags when workflow.md is missing and fixes that independently.
TASKS.md discipline
## Current Sprint holds only the active sprint's WPs. Between sprints it's empty. That's the canary that tells you the last sprint closed cleanly.
# <project> — Task Tracker
> Under 80 lines. Session log: 3 entries max. ## Current Sprint empty between sprints.
## Current Sprint
<!-- EMPTY. Pull WPs from BACKLOG.md when ready. Format: - [ ] WP-NNN — short title -->
## Completed Sprints
<!-- One line per sprint. Detail lives in git history. -->
## Session Log
<!-- Most recent first. Max 3 entries. -->.claude/rules/workflow.md
A path-scoped rule file Claude Code auto-loads only when editing BACKLOG.md or TASKS.md. Uses YAML frontmatter to declare the scope:
---
paths: ["BACKLOG.md", "TASKS.md"]
---
# Backlog → Tasks → Sprint Workflow Rules
...It codifies the single rule, the WP template requirements, numbered sprint start / sprint close sequences, and the staleness trigger list. Doctor flags MEDIUM when this file is missing; doctor --fix writes it.
Why path-scoped rules matter
A monolithic CLAUDE.md grows past the 200-line budget fast. Path-scoped rule files let you keep per-domain conventions close to the files they govern. Claude Code only loads them when relevant. YAML frontmatter with paths: [...] is the convention.
init generates two scoped rule files by default: conventions.md (general code style) and workflow.md (BACKLOG/TASKS lifecycle). Add your own. For example, Swift rules under paths: ["ios/**"], or backend rules under paths: ["api/**"].
Sprint lifecycle
Starting a sprint
- Pick the top-priority WPs from BACKLOG (P0 first, then P1 if P0 is empty).
- Same edit: delete from BACKLOG.md, add to
TASKS.md ## Current Sprintas- [ ] WP-NNN — short title. - Append to
BACKLOG.md ## Changelog:YYYY-MM-DD: WP-NNN pulled into Sprint N. - Write your sprint plan (outline approach + success criteria).
- Commit the pull + plan together.
Closing a sprint
- All
## Current Sprintitems checked off, or explicitly moved back to BACKLOG with rationale. - Run your review workflow. Verify tests, typecheck, and convention compliance before declaring done.
- Add one-line summary to
## Completed Sprints. - Empty
## Current Sprintback to its placeholder comment. - Update
## Session Log(prune to 3 entries). - Append to
BACKLOG.md ## Changelog:YYYY-MM-DD: Sprint N closed. WP-NNN done.
The workflow-check hook
init installs a PostToolUse hook at .claude/hooks/workflow-check.sh. It fires on every edit to BACKLOG.md or TASKS.md and warns (never blocks) on four conditions:
| Condition | What it catches |
|---|---|
Same WP-NNN ID in both files | Move-not-copy rule was violated. You pulled a WP into TASKS.md without removing it from BACKLOG.md. |
TASKS.md > 80 lines | Completed Sprints or Session Log is overflowing. Prune. |
## Current Sprint > 15 items | Sprint is oversized. Split it; move some WPs back to BACKLOG.md P0. |
## Session Log > 3 entries | Older sessions should live in git history, not in TASKS.md. |
The hook always exits 0; warnings appear as hook output in your Claude Code session and don't block edits or commits.
Doctor flags LOW when the hook is missing; doctor --fix installs the script and the settings entry together.