Break a large goal into 3–8 sequenced tasks, each one /eng → /tdd cycle. Writes to specs/{slug}.todos.md when a spec exists, root TODOS.md otherwise. /decompose — decompose a feature or goal /decompose re-entry — resume where you left off (auto-detected)
Scanned 5/27/2026
Install via CLI
openskills install iamvonpasion/hashb---
description: >
Break a large goal into 3–8 sequenced tasks, each one /eng → /tdd cycle.
Writes to specs/{slug}.todos.md when a spec exists, root TODOS.md otherwise.
/decompose — decompose a feature or goal
/decompose re-entry — resume where you left off (auto-detected)
---
# Decompose
Break a large goal into 3–8 sequenced tasks, each one `/eng` → `/tdd` cycle.
Writes to `specs/{slug}.todos.md` when a spec exists, or the root `TODOS.md`
"General" section otherwise. Replaces the former `/spec decompose` mode —
kept separate so `/spec` stays focused.
**Writes TODOS files only.** No code changes.
Per-spec files cut merge conflicts: parallel features touch parallel files
instead of stacking into one shared `TODOS.md`.
> Follows `rules/integrity.md`. Shared formatting + Visual Emphasis in
> `skills/shared/formatting.md` (use **bold** for key terms, tables for
> manifests, `▎` blockquotes for gates).
---
## When to use
| Signal | Action |
|--------|--------|
| Large feature spanning multiple modules | `/decompose` |
| Goal too big for one `/eng` session | `/decompose` |
| Goal spans 8+ files or multiple areas | `/decompose` |
| Small enough for single `/eng` (< 3 tasks) | Skip — use `/eng` directly |
| Existing TODOS section for this goal | Re-entry mode (auto-detected) |
**Input sources** (in priority order):
1. A `/spec` output from earlier in the conversation — pull ACs from it. The spec sets the **capability slug**.
2. An existing spec doc referenced by path — slug comes from the filename.
3. A user description with no spec — falls back to root "General".
---
## Complexity routing
| Complexity | Signal | Behavior |
|---|---|---|
| **Skip** | < 3 tasks | "Small enough for one `/eng` — skip decompose." |
| **Normal** | 3–8 tasks | Single chain or parallel pairs. |
| **Milestone** | 9+ tasks | Group into 2–3 milestones, each 3–5 tasks. |
---
## Output structure — Option A inverted pyramid
`/decompose` follows the **Inverted-Pyramid Output** pattern in
`skills/shared/formatting.md`. Read that section once; the rules below specify
only `/decompose`-specific bindings.
### Progress block
```
/decompose ═══════════════════════════════════════════════════════════════════════════
▸ Phase 1 Scope
○ Phase 2 Tasks
○ Phase 3 Write
══════════════════════════════════════════════════════════════════════════════════════
```
No inline title — the topic appears inside `★ THE PLAN` below in plain English.
---
## Flow
### Phase 1 · Scope (internal reasoning, no visible output)
Resolve the target file and check for re-entry. **Reason fully but emit
nothing yet** — the first thing the user sees is Phase 2's progress-block
re-emit.
**Target file resolution:**
| Input | Capability slug | Target file |
|---|---|---|
| `/spec` ran earlier in session | from spec's filename | `specs/{slug}.todos.md` |
| Path to spec doc | from filename | `specs/{slug}.todos.md` |
| User description, no spec | — | `TODOS.md` (General section) |
If the target is `specs/{slug}.todos.md` but `specs/{slug}.md` doesn't exist,
ask: "No spec found at `specs/{slug}.md` — write to root `TODOS.md` General
instead?" Default to root on confirm.
**Tracker detection.** Read Project Profile `Tracker:` field from the
consumer's `CLAUDE.md`. If `Tracker: github-issues`, run the detection block
from `skills/shared/tracker.md` §Tracker Detection. Cache `TRACKER_TYPE` for
all downstream use. If `gh` is unavailable or unauthenticated, warn and
proceed in TODOS-only mode (set `TRACKER_TYPE` empty).
**Re-entry detection (tracker-aware).** When `TRACKER_TYPE=github-issues`,
query the tracker first — it is the authoritative source:
```bash
# Tracker re-entry — query GitHub Issues by milestone
gh issue list --label "hashb" --milestone "{goal}" --state all \
--json number,title,state,labels --limit 50
```
If issues are found:
1. Regenerate the local TODOS file from tracker state (see
`skills/shared/tracker.md` §Re-entry Query for field mapping):
- `state: "OPEN"` → `- [ ]`, `state: "CLOSED"` → `- [x]`
- Labels `hashb:P1`/`hashb:M` → priority/effort fields
- Labels `hashb:eng`/`hashb:tdd`/`hashb:review`/`hashb:qa` → badge lines
- Labels `status:*` → infer current pipeline phase for next-task selection
2. Write the regenerated TODOS to the target file (overwrite stale local state).
3. Skip Phase 2 and go straight to Phase 3 in re-entry mode
(see §Phase 3 · Re-entry).
When `TRACKER_TYPE` is empty (no tracker configured), fall back to the
local file scan:
Scan known TODO files for a `### Feature:` section matching the requested goal:
```bash
ls TODOS.md specs/*.todos.md 2>/dev/null
```
If a match is found, skip Phase 2 and go straight to Phase 3 in re-entry mode
(see §Phase 3 · Re-entry).
### Phase 2 · Tasks — emit, then Gate D
Phase 2 emits the **full progress block** at the start of the phase as the
entry banner. This is the first visible output of `/decompose`. Then it emits
in order: inverted-pyramid header (3 `▎` blocks), receipts, then waits at
Gate D at the bottom.
```
/decompose ═══════════════════════════════════════════════════════════════════════════
✓ Phase 1 Scope
▸ Phase 2 Tasks
○ Phase 3 Write
══════════════════════════════════════════════════════════════════════════════════════
```
#### 2a · Inverted-pyramid header (must-read summary)
```
▎ ★ THE PLAN
▎
▎ {1–2 plain-English lines: what's being broken into how many tasks +
▎ rough sequence shape — single chain, parallel pairs, milestones.}
▎ ⚠ HEADLINE RISKS
▎
▎ • {plan-level risk — critical-path serialization, missing dependency, scope leak}
▎ • {plan-level risk}
▎ • {2–3 bullets max}
▎ ✎ TASKS · {N}
▎
▎ #1 P1 M {title, ≤50 chars} deps: —
▎ #2 P1 S {title} deps: —
▎ #3 P1 L {title} deps: #1, #2
▎ ...
```
For milestone mode (9+ tasks), group rows under one-line milestone headers
inside the `✎` block:
```
▎ Milestone A · auth basics
▎ #1 P1 M ...
▎ #2 P1 S ...
▎ Milestone B · session lifecycle
▎ #3 P1 L ...
```
**Field semantics:**
| Field | Content |
|-------|---------|
| # | Sequential ID, continuing from highest existing across `TODOS.md` + `specs/*.todos.md` (global ID space — see §Write rules) |
| P | P1 (blocking), P2 (important), P3 (nice-to-have) |
| Effort | S (< half day), M (half day–2 days), L (2+ days) |
| Title | What to build — 1 imperative phrase, ≤50 chars |
| deps | `#N, #M` or `—` (immediate predecessors only — may reference IDs in any TODOS file) |
#### 2b · Receipts — between header and gate
```
══════════════════════════════════════════════════════════════════════════════════════
Receipts — Sequence
══════════════════════════════════════════════════════════════════════════════════════
#1 ──→ #3 ──→ #4
#2 ──┘
Parallel: after #2 → {#3, #4}
Effort: {count by size — e.g. 2S · 2M · 1L}
══════════════════════════════════════════════════════════════════════════════════════
Receipts — Target file
══════════════════════════════════════════════════════════════════════════════════════
Target: specs/{slug}.todos.md
Index: TODOS.md · {slug} entry will be added/updated
```
For root `TODOS.md` (no-spec) targets, the second receipts section reads:
```
Target: TODOS.md · ## General (no spec)
```
If 3+ tasks have no shared dependencies, append below the sequence diagram:
```
Tasks #N, #M, #K are independent — consider /hashb:swarm for parallel run.
```
If a task overlaps an existing TODO (in any file), surface a `⚠` line in the
sequence receipts — don't bury it inline:
```
⚠ #N overlaps existing: {description} (in {file}). Skip? Replace?
```
#### 2c · Gate D — at the bottom, after receipts
```
▎ ▸ GATE D — approve manifest?
▎
▎ Reply "go" to write and proceed, or override.
▎ For details: "expand #N" (Goal + AC for one task), or "expand all".
```
**Override vocabulary at Gate D:**
| Reply | Action |
|---|---|
| `go` | Approve, expand silently, write to target, surface task #1. |
| `expand #N` | Show Goal + 2–5 AC for that one task before deciding. |
| `expand all` | Show Goal + AC for every task. |
| `#N: {revision}` | Revise that task's title/effort/deps before writing. |
| `swap #N #M` | Reorder. |
### Phase 3 · Write — write file, surface task #1
Phase 3 re-emits the **full progress block** at the start. It then writes the
target file silently (Goal + 2–5 AC per task expanded into the file), confirms
the write, and surfaces task #1 detail for the `/eng` handoff.
```
/decompose ═══════════════════════════════════════════════════════════════════════════
✓ Phase 1 Scope
✓ Phase 2 Tasks
▸ Phase 3 Write
══════════════════════════════════════════════════════════════════════════════════════
```
**Write confirmation:**
```
══════════════════════════════════════════════════════════════════════════════════════
Receipts — Write
══════════════════════════════════════════════════════════════════════════════════════
✓ {target file} · {feature name} · tasks #{N} through #{N+K}
✓ TODOS.md index updated · {slug} {done}/{total} (per-spec target only)
```
**Tracker sync (when `TRACKER_TYPE=github-issues`).**
After writing the local TODOS file, create GitHub Issues for cross-session
persistence. See `skills/shared/tracker.md` for label conventions and
issue body template.
1. **Ensure labels exist** (idempotent — run once per repo):
```bash
for label in hashb hashb:P1 hashb:P2 hashb:P3 hashb:S hashb:M hashb:L \
status:backlog status:planning status:dev status:review status:testing \
hashb:eng hashb:tdd hashb:review hashb:qa; do
gh label create "$label" --force 2>/dev/null || true
done
```
2. **Create milestone** (idempotent — reuse if exists):
```bash
gh api repos/{owner}/{repo}/milestones --method POST \
-f title="{feature name}" -f state="open" 2>/dev/null || true
```
3. **Create project board** (one per feature):
```bash
PROJECT_NUM=$(gh project create --title "hashb: {feature name}" \
--owner {owner} --format json --jq '.number' 2>/dev/null)
```
Cache as `TRACKER_PROJECT` for downstream skills.
4. **Create issues** for each task:
```bash
gh issue create \
--title "#{N} {title}" \
--label "hashb,hashb:{priority},hashb:{size},status:backlog" \
--milestone "{feature name}" \
--project "hashb: {feature name}" \
--body "{issue body from template in tracker.md}"
```
5. **Use returned issue numbers as task IDs.** Rewrite the TODOS file
with the GitHub Issue numbers instead of sequential IDs. This
eliminates the ID-mapping problem — `depends: #42` means both
GitHub Issue #42 and TODOS task #42.
6. **Tracker receipt lines** (append to the receipts block):
```
✓ GitHub Issues #{N}–#{N+K} created · milestone: {feature name}
✓ Project board: hashb: {feature name}
```
If any issue creation fails, surface the failure but don't block —
the TODOS file is always written completely as a fallback.
**Task #1 handoff:**
```
══════════════════════════════════════════════════════════════════════════════════════
Next Task
══════════════════════════════════════════════════════════════════════════════════════
#{N} P1 [M] {title}
Dependencies met: yes
GOAL
{1 sentence}
ACCEPTANCE CRITERIA
- {criterion}
- {criterion}
```
**Ready gate (auto-chains to /eng):**
```
▎ ▸ READY — start /hashb:eng on task #{N}?
▎
▎ Next: /hashb:eng (recommended — task #{N} is next in sequence){· /hashb:swarm (if tasks #{N}, #{N+1}, #{N+2} are independent of each other)}
▎
▎ Reply "go" to start, or "stop" to pause (tasks #{N+1}+ stay queued).
```
Tasks #2+ remain in the target file for `/eng` to pick up in sequence. Don't
preview them unless the user asks.
#### Phase 3 · Re-entry (alt path from Phase 1)
If Phase 1 detected re-entry, skip Phase 2 entirely. Phase 3 emits the
progress block with Phase 2 marked `— skipped`, then a re-entry-specific
inverted-pyramid header.
```
/decompose ═══════════════════════════════════════════════════════════════════════════
✓ Phase 1 Scope
— Phase 2 Tasks (already decomposed)
▸ Phase 3 Write
══════════════════════════════════════════════════════════════════════════════════════
▎ ★ THE PLAN
▎
▎ Re-entry · {feature} · {done}/{total} done · next is task #{N}
▎ ⚠ STATUS
▎
▎ • {empty if on-track, or one line if blocked: "Task #N depends on #M, still open"}
▎ ✎ PROGRESS
▎
▎ ✓ #1 {title} [eng ✓] [tdd ✓] [review ✓] [qa ✓]
▎ ✓ #2 {title} [eng ✓] [tdd ✓] [review ✓] [qa ✓]
▎ ▸ #3 {title} ← NEXT [eng ✓] [tdd ✓]
▎ ○ #4 {title} (depends: #3)
```
If all tasks are `[x]`, the header changes:
```
▎ ★ THE PLAN
▎
▎ Re-entry · {feature} · all {N} tasks complete
▎ ▸ COMPLETE — feature done
▎
▎ Next: /hashb:retro (recommended — capture learnings)
▎
▎ Reply "go" to start /hashb:retro.
```
**Tracker cleanup on completion (when `TRACKER_TYPE=github-issues`).**
When all tasks are `[x]` (all issues closed):
```bash
# Close milestone
MILESTONE_NUM=$(gh api repos/{owner}/{repo}/milestones \
--jq ".[] | select(.title==\"{feature}\") | .number")
gh api "repos/{owner}/{repo}/milestones/$MILESTONE_NUM" \
--method PATCH -f state="closed" 2>/dev/null
# Archive project board
gh project close "$TRACKER_PROJECT" 2>/dev/null
```
If the suggested next task has unmet dependencies, flag it and recommend the
blocking task instead. Re-entry handoff gate matches the standard form
(canonical `Next: /hashb:eng …` line).
---
## Write rules
**Per-spec file (`specs/{slug}.todos.md`):**
```markdown
# Tasks: {capability title}
> Generated by `/decompose` for `specs/{slug}.md`.
> See root `TODOS.md` for the full index.
### Feature: {name}
- [ ] P1 [M] #1 {title} (depends: none)
- Goal: {1 sentence}
- AC:
- [ ] {criterion}
- [ ] {criterion}
```
**Root `TODOS.md` (index + General):**
```markdown
# TODOS
## By spec
- [auth](specs/auth.todos.md) — {done}/{total} done
- [billing](specs/billing.todos.md) — {done}/{total} done
## General (no spec)
### Feature: {name}
- [ ] P2 [S] #N {title} (depends: none)
- Goal: {1 sentence}
- AC:
- [ ] {criterion}
```
**File rules:**
| Target | Rule |
|---|---|
| `specs/{slug}.todos.md` | Create with header if absent. If present, append the new feature section. Never move or reformat existing items. |
| `TODOS.md` General | Append `### Feature:` under `## General (no spec)`. Create the file with both `## By spec` and `## General (no spec)` headers if absent. |
| `TODOS.md` index | After writing the per-spec file, add or update the matching `## By spec` line: `- [{slug}](specs/{slug}.todos.md) — {done}/{total} done`. Sort lines alphabetically by slug for deterministic merges. |
**ID allocation (conditional on tracker):**
When `TRACKER_TYPE=github-issues`:
- Create GitHub Issues first (Phase 3 tracker sync). Use the returned issue
numbers as task IDs. GitHub is the allocator — no local numbering needed.
- TODOS file task lines use GitHub Issue numbers: `#47`, `#48`, etc.
- Numbers may be non-sequential if the repo has other issues. This is expected.
- Cross-file `depends: #47` references work because issue numbers are globally
unique per repo.
When `TRACKER_TYPE` is empty (no tracker configured):
- Read max `#N` across `TODOS.md` + every `specs/*.todos.md`. Start numbering at max+1.
- Branch isolation handles most collisions. On rebase, a dev may need to renumber if their range collides — small cost for keeping cross-file `depends: #4` refs working without prefix collisions.
**Stage badges (appended by downstream skills):**
Skills append inline badges to the task line as they complete work on that task.
Badges appear on a continuation line below the task, indented to align with the
task text:
```markdown
- [ ] P1 [M] #3 Add auth middleware (depends: #2)
[eng ✓] [tdd ✓]
- [x] P1 [S] #2 Setup JWT config (depends: none)
[eng ✓] [tdd ✓] [review ✓] [qa ✓]
```
| Badge | Appended by | When |
|-------|-------------|------|
| `[eng ✓]` | `/eng` | After gate approval (plan complete) |
| `[tdd ✓]` | `/tdd` | After suite check passes (Phase 3) |
| `[review ✓]` | `/review` | After APPROVED or APPROVED WITH NOTES verdict |
| `[qa ✓]` | `/qa` | After clean report (no critical/high issues) |
Rules:
- Only append a badge if the handoff includes a `Task:` line.
- Each badge appears at most once per task — skip if already present.
- `/decompose re-entry` reads badges to show stage progress alongside checkmarks.
- Optional stages that are skipped simply have no badge — absence is normal.
---
## Next step
| Condition | Next |
|---|---|
| Tasks written, ready to work | `/hashb:eng` on task #1 |
| Tasks are independent | `/hashb:swarm` for parallel run |
| Re-entry, all complete | `/hashb:retro` |
| Re-entry, more tasks | `/hashb:eng` on the `▸` task |
**Autonomous mode:** In a recipe chain, auto-invoke `/hashb:eng` on task #1
after Phase 3.
---
## Rules
| Rule | Why |
|------|-----|
| Writes TODOS files only | No code changes. Parallel to how `/ship` writes CHANGELOG. |
| Per-spec by default, root for spec-less | Per-spec files cut merge conflicts in multi-dev repos. Spec-less invocations stay on the lightweight path. |
| Root TODOS.md is an index | The `## By spec` section points at per-spec files. The `## General (no spec)` section holds spec-less feature tasks. Never inline per-spec task content into the index. |
| Global #N IDs | Cross-spec dependencies (`depends: #4`) keep working without prefix collisions. Allocator reads max across all files. |
| One gate (D) | User approves the manifest shape. Expansion happens silently after approval. |
| Progressive expansion | Phase 2 shows the task list. Phase 3 expands AC silently and writes the file. Task #1 surfaces for the `/eng` handoff — never preview #2+ unless asked. |
| Task sizing | Each task ≈ one `/eng` → `/tdd` cycle. Not "half a feature." |
| Dependencies explicit | Immediate predecessors only. No transitive walks. |
| Re-entry detection | Scan root + all `specs/*.todos.md` for matching feature sections before re-decomposing. |
| Plain-English handoff content | Task `GOAL` is one sentence in plain English. AC items name something the reader can verify, not internal codenames. If a codename appears (e.g. "Tier 2 batch 4", "RECURRING-3x"), gloss it once in parentheses — the reader shouldn't need outside context to act on the task. Engineer-grep precision (file paths, identifiers, package names) stays — that's not jargon. |
| Closing message after Phase 3 | After the `Next Task` block emits, the conversational close is **one** plain-English line: e.g. `Wrote 8 tasks (#35–#42). No code changed. Run /hashb:eng 35 to start.` Don't restate the conditional alternatives — the gate's `Next:` line already cited them. Don't quote prior user instructions back ("per your instruction…"); the reader knows what they asked for. |
| Stage badges | Downstream skills (`/eng`, `/tdd`, `/review`, `/qa`) append `[skill ✓]` badges to the task's continuation line in the TODOS file. Re-entry reads these badges to show pipeline progress. See §Write rules for format. |
No comments yet. Be the first to comment!