Skip to content
Back to skills

2633 Backlog Lifecycledraft 7189f18b

ASecurity

**STATUS: DRAFT** — This document was derived from reading source files on 2026-02-27. Claims marked with `[VERIFY]` require confirmation against live script execution before this document is promoted to canonical reference. SOURCE: Derived from reading `.claude/skills/backlog/SKILL.md`, `.claude/skills/backlog/references/state-machine.md`, `.claude/skills/backlog/references/item-schema.md`, `.claude/skills/backlog/scripts/backlog.py` (lines 1–100), `.claude/skills/work-backlog-item/SKILL.md`...

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
code-qualitygobashtestinggitapi

Works with

  • terminal
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2633-backlog-lifecycledraft_7189f18b --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2633 Backlog Lifecycledraft 7189f18b?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2633 Backlog Lifecycledraft 7189f18b
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2633-backlog-lifecycledraft-7189f18b/badge)](https://www.skillsdirectory.com/skills/tools-only-2633-backlog-lifecycledraft-7189f18b)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
<!-- DRAFT — 2026-02-27 — Pending verification against live script behavior -->
# Backlog Item Lifecycle

**STATUS: DRAFT** — This document was derived from reading source files on 2026-02-27.
Claims marked with `[VERIFY]` require confirmation against live script execution before
this document is promoted to canonical reference.

SOURCE: Derived from reading `.claude/skills/backlog/SKILL.md`,
`.claude/skills/backlog/references/state-machine.md`,
`.claude/skills/backlog/references/item-schema.md`,
`.claude/skills/backlog/scripts/backlog.py` (lines 1–100),
`.claude/skills/work-backlog-item/SKILL.md`,
`.claude/skills/create-backlog-item/SKILL.md`,
`.claude/skills/groom-backlog-item/SKILL.md` (accessed 2026-02-27).

---

## 1. Data Architecture

Three-layer system. Each layer has a distinct role; they are not interchangeable.

### Layer 1 — GitHub Issues (canonical source of truth)

GitHub Issues are authoritative for item status and priority. The label set on the issue
is the canonical status. When a local file and its linked issue disagree, the GitHub issue
wins.

- Status is encoded as `status:*` labels (one per item at any time)
- Priority is encoded as `priority:*` labels (P0/P1/P2/Ideas)
- Issue body mirrors the item file body after each sync
- Milestone field mirrors `metadata.milestone`

### Layer 2 — `.claude/backlog/*.md` (local cache for agent consumption)

Per-item files exist to avoid GitHub API saturation during agent sessions. Agents read
these files instead of hitting the API for every lookup.

- Named `{priority}-{slug}.md` — e.g., `p1-error-recovery.md`
- Contain YAML frontmatter + body sections
- Written by `backlog.py`; never edited directly by skills or agents
- Stale when their linked issue has changed state without a `backlog pull` [VERIFY: pull subcommand behavior]

### Layer 3 — `backlog.py` (sole interface)

All reads and writes to both layers go through this script. No direct edits to
`.claude/backlog/*.md` files. No direct `gh issue edit` calls. The script handles:

- Creating per-item files with correct frontmatter
- Creating and closing GitHub Issues
- Syncing groomed content to issue bodies
- Writing label transitions
- Writing `metadata.issue` back to the local file after issue creation

```bash
uv run .claude/skills/backlog/scripts/backlog.py <subcommand> [options]
```

---

## 2. Item Lifecycle Flow

### State 1: Created (local only)

**Trigger**: `/create-backlog-item` collects fields and invokes `backlog add`.

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py add \
  --title "Item title" \
  --priority P1 \
  --description "Description" \
  --source "Session observation" \
  --type Feature \
  [--research-first "questions"] \
  [--no-create-issue]
```

**What gets created**:

- Per-item file: `.claude/backlog/{priority}-{slug}.md`
- Frontmatter fields set: `name`, `description`, `metadata.topic`, `metadata.source`,
  `metadata.added`, `metadata.priority`, `metadata.type`, `metadata.status: needs-grooming`
- Body sections written: Description, optionally Acceptance Criteria, Research First,
  Suggested Location

**Where data lives**: Local file only. No GitHub issue unless P0/P1 and `--create-issue` was
passed (or the user confirmed in guided/quick mode).

**GitHub behavior**:

- P0 or P1 with `--create-issue`: GitHub Issue created immediately; `metadata.issue: '#N'`
  written to file
- P0 or P1 without `--create-issue`: local file only; issue created later by `backlog sync`
  or `backlog update --create-issue`
- P2 or Ideas: always local only at creation; `--no-create-issue` is set automatically

---

### State 2: Synced to GitHub

**Trigger**: `backlog sync` (also triggered by GitHub Action on `.claude/backlog/` changes).

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py sync [--dry-run]
```

**What happens**:

- Script scans `.claude/backlog/` for P0/P1 items without a `metadata.issue` field
- Creates a GitHub Issue for each such item
- Writes `metadata.issue: '#N'` back to the per-item file frontmatter
- Applies `status:needs-grooming` and `priority:P*` labels to the issue

**Where data lives**: Both local file and GitHub Issue. The local file is now linked.

**GitHub Action integration**: [VERIFY] The GitHub Action triggers `backlog sync` when
`.claude/backlog/` files are changed in a push. This means committing a new P0/P1 item
file triggers issue creation automatically without a manual sync call.

---

### State 3: Groomed

**Trigger**: `/groom-backlog-item <title>` orchestrates fact-checking, RT-ICA, and the
`backlog-item-groomer` agent, then writes sections via `backlog groom`.

**Commands** (incremental, preferred):

```bash
# After fact-check step
uv run .claude/skills/backlog/scripts/backlog.py groom "{title}" \
  --section "Fact-Check" --content "{fact-check summary}"

# After RT-ICA step
uv run .claude/skills/backlog/scripts/backlog.py groom "{title}" \
  --section "RT-ICA" --content "{rt-ica summary}"

# After groomer agent output
uv run .claude/skills/backlog/scripts/backlog.py groom "{title}" \
  --section "Reproducibility" --content "{content}"
# ... repeated for each of the 7 required subsections
```

**Alternative (full body at once)**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py groom "{title}" \
  --groomed-content "{full groomed body}"
# Or from file:
uv run .claude/skills/backlog/scripts/backlog.py groom "{title}" \
  --groomed-file path/to/groomed.md
```

**What gets written to the item file**:

- `metadata.groomed: YYYY-MM-DD` (set only after ALL 7 required sections are present)
- Body sections appended: Fact-Check, RT-ICA, then groomed subsections (Reproducibility,
  Priority, Impact, Scope, Output / Evidence, Dependencies, Research, Skills, Agents,
  Prior Work, Files, Decision)

**Where data lives**: Local file updated with all sections. If the item has a linked GitHub
Issue, `backlog groom` syncs the groomed content to the issue body. [VERIFY: whether the
script pushes body to GH on every `groom` call or only on explicit sync]

**GitHub label transition**: `status:needs-grooming` removed, `status:groomed` added.

**Item is considered fully groomed only when** all 7 canonical sections are present
(Fact-Check, RT-ICA, Reproducibility, Dependencies, Skills, Agents, Prior Work) AND
`metadata.groomed` is set. Partial grooming (some sections present) is not groomed —
`/groom-backlog-item` resumes from the first missing section on re-run.

---

### State 4: In Milestone

**Trigger**: `/group-items-to-milestone` assigns the item to a GitHub milestone.

**What happens**:

- `metadata.milestone: {N}` written to per-item file
- GitHub Issue milestone field updated
- GitHub label: `status:groomed` removed, `status:in-milestone` added

**Where data lives**: Both local and GitHub, now with milestone linkage.

**Note**: This state is managed by `/group-items-to-milestone`, which is not documented in
the source files read for this draft. [VERIFY: exact command invoked by that skill]

---

### State 5: In Progress

**Trigger**: `/work-backlog-item <title>` — after RT-ICA returns APPROVED and the SAM plan
file is created.

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py update "{title}" \
  --plan "plan/tasks-{N}-{slug}.md" \
  --status in-progress \
  -R Jamie-BitFlight/claude_skills
```

**What gets written**:

- `metadata.plan: plan/tasks-{N}-{slug}.md` in per-item file frontmatter
- `metadata.status: in-progress` in frontmatter
- GitHub label: current status label removed, `status:in-progress` added

**Critical constraint**: `status:in-progress` MUST NOT be set before RT-ICA returns APPROVED
and the plan file exists. Setting it during grooming or RT-ICA checking is incorrect.

**Where data lives**: Both local and GitHub. Plan file exists at `plan/tasks-{N}-{slug}.md`.

---

### State 6: Done / Closed

**Trigger**: `/work-backlog-item close <title>` — after plan checklist is 100% complete and
acceptance criteria verification passes.

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py close "{title}" \
  --plan "plan/tasks-{N}-{slug}.md" \
  --checklist-pass \
  [-R Jamie-BitFlight/claude_skills]
```

**Preconditions enforced before this command is called**:

1. Plan file checklist: all `- [x]` (zero unchecked items)
2. Acceptance criteria verification agent returns PASS (per-criterion, not overall guess)

**What happens**:

- `metadata.status: done` written to per-item file
- GitHub label: `status:in-progress` removed, `status:done` added
- GitHub Issue closed

**Optional cleanup flag** (`--cleanup`) [VERIFY: whether this flag exists on `close` or only
on `resolve`]: removes the local per-item file after closing. Without `--cleanup`, the file
remains but has `status: done`.

**Terminal state (closed)**: `done` → `closed` transition happens only when
`/complete-milestone` archives the milestone. At that point `metadata.status: closed` is set
and a milestone completion archive is written to `.claude/milestones/v{N}-completion.md`.

---

### State 7: Resolved (won't-fix / obsolete)

**Trigger**: Any skill or `/work-backlog-item resolve <title>` when an item is invalid,
obsolete, or superseded.

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py resolve "{title or #N}" \
  --reason "reason text" \
  [-R Jamie-BitFlight/claude_skills]
```

**What happens**:

- `metadata.status: resolved` written to per-item file
- GitHub label: current status label removed, `status:resolved` added
- GitHub Issue closed (with resolution comment if `--reason` provided)
- `--cleanup` removes the local file [VERIFY: cleanup flag presence on resolve]

**Can be triggered from any state** — not just in-progress. An item can be resolved from
`needs-grooming`, `groomed`, `in-milestone`, or `in-progress`.

---

### State 8: Pulling from GitHub

**Trigger**: Manual `backlog pull` call to sync GitHub state back to local files.

**Command**:

```bash
uv run .claude/skills/backlog/scripts/backlog.py pull [--dry-run] [--force]
```

**What happens** [VERIFY: exact pull behavior — inferred from docstring]:

- Fetches current issue state from GitHub for each item with a `metadata.issue` field
- Overwrites or merges local file body with current issue body
- Updates `metadata.status` to match GitHub label state
- `--dry-run`: shows what would change without writing
- `--force`: overwrites local changes without prompting [VERIFY]

**Use case**: When a GitHub Issue is updated externally (e.g., via web UI or another agent),
`backlog pull` brings those changes into the local cache.

---

## 3. Data Flow Diagram

```mermaid
flowchart TD
    subgraph local["Local: .claude/backlog/"]
        LF["Per-item file\n{priority}-{slug}.md\n(frontmatter + body)"]
    end

    subgraph github["GitHub Issues"]
        GH["Issue #N\n(title + body + labels + milestone)"]
    end

    subgraph script["backlog.py (sole interface)"]
        ADD["backlog add"]
        SYNC["backlog sync"]
        GROOM["backlog groom"]
        UPDATE["backlog update"]
        CLOSE["backlog close"]
        RESOLVE["backlog resolve"]
        PULL["backlog pull"]
    end

    Create(["/create-backlog-item"]) --> ADD
    ADD -->|"Creates file\n.claude/backlog/{priority}-{slug}.md"| LF
    ADD -->|"P0/P1 + --create-issue\nCreates issue + writes metadata.issue"| GH

    LF -->|"P0/P1 items missing issue"| SYNC
    SYNC -->|"Creates GH issue\nwrites metadata.issue back"| LF
    SYNC --> GH

    Groom(["/groom-backlog-item"]) --> GROOM
    GROOM -->|"Writes sections to file\nSets metadata.groomed"| LF
    GROOM -->|"If item has issue:\nsyncs body to GH"| GH

    Work(["/work-backlog-item"]) --> UPDATE
    UPDATE -->|"Sets metadata.plan\nmetadata.status=in-progress"| LF
    UPDATE -->|"Updates labels"| GH

    CloseCmd(["/work-backlog-item close"]) --> CLOSE
    CLOSE -->|"Sets metadata.status=done"| LF
    CLOSE -->|"Closes issue"| GH

    ResolveCmd(["/work-backlog-item resolve"]) --> RESOLVE
    RESOLVE -->|"Sets metadata.status=resolved\n[--cleanup deletes local file]"| LF
    RESOLVE -->|"Closes issue + resolution comment"| GH

    GH -->|"External changes or drift"| PULL
    PULL -->|"Overwrites local with GH state"| LF

    classDef localonly fill:#e8f4e8,stroke:#4a9e4a
    classDef synced fill:#e8eaf4,stroke:#4a4a9e
    classDef terminal fill:#f4e8e8,stroke:#9e4a4a

    LF:::synced
    GH:::synced
```

### When items are local-only (no GitHub issue)

- P2 and Ideas items at creation — `backlog add` with `--no-create-issue`
- P0/P1 items before first `backlog sync` — if created without `--create-issue`
- Any item between creation and the next GitHub Action trigger [VERIFY: GH Action timing]

### When items get pushed to GitHub

- P0/P1 at creation if `--create-issue` passed or user confirms in guided mode
- On `backlog sync` — creates issues for all P0/P1 items missing them
- On `backlog groom` — syncs groomed body to existing issue
- On `backlog update --status in-progress` — updates labels
- On `backlog close` — closes issue
- On `backlog resolve` — closes issue with comment

### When local files get removed

- `backlog close --cleanup`: file deleted after issue is closed [VERIFY: flag exists]
- `backlog resolve --cleanup`: file deleted after issue is resolved [VERIFY: flag exists]
- After `/complete-milestone`: milestone archive written; [VERIFY: whether local files are
  deleted or only status is set to `closed`]

### Sync direction

- **Push (local → GitHub)**: `backlog add`, `backlog sync`, `backlog groom`, `backlog update`,
  `backlog close`, `backlog resolve`
- **Pull (GitHub → local)**: `backlog pull`
- **Write-back on create**: `backlog add --create-issue` and `backlog sync` write `metadata.issue`
  back to the local file after creating the GH issue (bidirectional in a single operation)

---

## 4. Label and Priority Mapping

### Status Labels (1:1 with states)

| Status | GitHub Label | Set by |
|--------|-------------|--------|
| `needs-grooming` | `status:needs-grooming` | `backlog add` |
| `groomed` | `status:groomed` | `backlog groom` (after all 7 sections present) |
| `blocked` | `status:blocked` | `backlog groom` (RT-ICA BLOCKED) or `backlog update` |
| `in-milestone` | `status:in-milestone` | `/group-items-to-milestone` |
| `in-progress` | `status:in-progress` | `backlog update --status in-progress` |
| `done` | `status:done` | `backlog close` |
| `resolved` | `status:resolved` | `backlog resolve` |
| `closed` | `status:closed` | `/complete-milestone` only |

Labels are exclusive — exactly one `status:*` label per issue at any time. The backlog script
manages label transitions; no direct `gh label` calls are permitted.

### Priority Labels (orthogonal to status)

| Priority | GitHub Label | Local file naming |
|----------|-------------|------------------|
| P0 | `priority:P0` | `.claude/backlog/p0-{slug}.md` |
| P1 | `priority:P1` | `.claude/backlog/p1-{slug}.md` |
| P2 | `priority:P2` | `.claude/backlog/p2-{slug}.md` |
| Ideas | `priority:Ideas` | `.claude/backlog/ideas-{slug}.md` |

Priority labels are set at creation and do not change unless the item is explicitly
re-prioritized. [VERIFY: whether `backlog update` supports `--priority` flag]

### Type Labels

| Type | GitHub Label |
|------|-------------|
| Feature | `type:feature` |
| Bug | `type:bug` |
| Refactor | `type:refactor` |
| Docs | `type:docs` |
| Chore | `type:chore` |

---

## 5. What Happens at Each Point

### After `backlog add`

```text
.claude/backlog/{priority}-{slug}.md  — CREATED
  frontmatter:
    name: "Item title"
    description: "one-sentence summary"
    metadata:
      topic: "item-title-slug"
      source: "Session observation"
      added: 2026-02-27
      priority: P1
      type: Feature
      status: needs-grooming
  body:
    ## Description
    {prose}

    ## Acceptance Criteria
    {bullet list — if provided}

    ## Research First
    {questions — if provided}

GitHub Issue: NOT YET CREATED (unless P0/P1 + --create-issue)
```

### After `backlog sync` (P0/P1 item gets issue)

```text
.claude/backlog/p1-{slug}.md  — MODIFIED
  frontmatter:
    metadata.issue: '#42'          ← written back by script

GitHub Issue #42:
  title:  "Item title"
  body:   {mirrored from local file body}
  labels: [priority:P1, status:needs-grooming]
  state:  open
```

### After `backlog groom` (all sections written)

```text
.claude/backlog/p1-{slug}.md  — MODIFIED
  frontmatter:
    metadata.groomed: 2026-02-27   ← set after all 7 sections present
    metadata.status: groomed       ← [VERIFY: whether groom sets status or only update does]
  body additions:
    ## Fact-Check
    ## RT-ICA
    ## Groomed
      ### Reproducibility
      ### Dependencies
      ### Skills
      ### Agents
      ### Prior Work
      (+ others)

GitHub Issue #42:
  body:   {updated to include groomed sections}
  labels: [priority:P1, status:groomed]  ← status:needs-grooming replaced
```

### After `backlog update --status in-progress`

```text
.claude/backlog/p1-{slug}.md  — MODIFIED
  frontmatter:
    metadata.plan: "plan/tasks-3-{slug}.md"
    metadata.status: in-progress

GitHub Issue #42:
  labels: [priority:P1, status:in-progress]  ← previous status label replaced
```

### After `backlog close --checklist-pass`

```text
.claude/backlog/p1-{slug}.md  — MODIFIED (or DELETED if --cleanup)
  frontmatter:
    metadata.status: done

GitHub Issue #42:
  state:  closed
  labels: [priority:P1, status:done]
```

### After `backlog resolve --reason "..."`

```text
.claude/backlog/p1-{slug}.md  — MODIFIED (or DELETED if --cleanup)
  frontmatter:
    metadata.status: resolved

GitHub Issue #42:
  state:  closed
  labels: [priority:P1, status:resolved]
  comment: resolution reason text appended
```

### After `backlog close --cleanup` (or equivalent with cleanup)

```text
.claude/backlog/p1-{slug}.md  — DELETED

GitHub Issue #42:  (state unchanged — already closed by backlog close)
```

### After PR merge + next `backlog sync`

```text
Already-closed issues (state: closed on GitHub) are skipped by backlog sync.
The sync command only creates issues for P0/P1 items that have no issue yet.
Closed issues are not re-opened or re-synced.  [VERIFY: exact skip logic in sync]
```

---

## 6. Item File Structure (Annotated)

```yaml
---
name: "Fix error recovery in rollback"           # title; matches GH issue title
description: "Rollback does not handle partial…"  # one-sentence summary
metadata:
  topic: "fix-error-recovery-in-rollback"         # kebab-case slug, max 60 chars
  source: "Code review 2026-02-20"                # trigger
  added: 2026-02-20                               # creation date
  priority: P1                                    # P0|P1|P2|Ideas
  type: Bug                                       # Feature|Bug|Refactor|Docs|Chore
  status: in-progress                             # current state (see state machine)
  groomed: 2026-02-21                             # set by groom-backlog-item
  issue: '#42'                                    # GitHub issue number
  milestone: 3                                    # GitHub milestone number
  plan: plan/tasks-5-fix-error-recovery.md        # SAM task file path
---

## Description

{prose — what the problem is, not how to fix it}

## Acceptance Criteria

- Running `command X` produces `output Y`
- File `.claude/backlog/p1-{slug}.md` exists with correct frontmatter

## Research First

{questions to answer before grooming}

## Suggested Location

`plugins/plugin-creator/scripts/`

## Fact-Check

Claims checked: 3
VERIFIED: 2 | REFUTED: 1 | INCONCLUSIVE: 0
Refuted claims: [...]
Citations: [...]

## RT-ICA

Goal: {one sentence}
Conditions:
1. {condition} | Status: AVAILABLE | Info needed: —
Decision: APPROVED
Missing: None

## Groomed

### Reproducibility
### Dependencies
### Skills
### Agents
### Prior Work
### Files
### Decision

## Acceptance Criteria Verification

[PASS] Running `command X` produces `output Y` — verified at src/main.py:42
[PASS] File exists with correct frontmatter — confirmed at .claude/backlog/p1-…
Overall: PASS (2/2 criteria met)
```

---

## 7. Testing Checklist

Items to verify in the next session by running the commands and observing actual output.

### Data Architecture

- [ ] Confirm `backlog add` with `--no-create-issue` produces no GitHub API call (check with `--dry-run` if available, or observe GH issue list before/after)
- [ ] Confirm `backlog add` with `--create-issue` writes `metadata.issue: '#N'` to the local file (read file after command)
- [ ] Confirm `backlog sync` skips items that already have `metadata.issue` set
- [ ] Confirm `backlog sync` with `--dry-run` shows what would be created without writing

### State Transitions

- [ ] Confirm `backlog groom "{title}" --section "Fact-Check" --content "..."` appends without overwriting existing sections
- [ ] Confirm `metadata.groomed` is set only after all 7 required sections are present (try with 6 sections and verify field is absent)
- [ ] Confirm `backlog update --status in-progress` requires a prior `--plan` to be set, or can set status independently
- [ ] Confirm `backlog close` without `--checklist-pass` flag is rejected (expected: error or warning)
- [ ] Confirm `backlog resolve` without `--reason` is rejected

### Cleanup Behavior

- [ ] Verify whether `--cleanup` flag exists on `backlog close` (check `backlog close --help`)
- [ ] Verify whether `--cleanup` flag exists on `backlog resolve` (check `backlog resolve --help`)
- [ ] Confirm whether `backlog close --cleanup` deletes the local file or only marks it deleted
- [ ] Confirm what `/complete-milestone` does to local per-item files (deletes or sets `status: closed`)

### Pull / Bidirectional Sync

- [ ] Run `backlog pull --dry-run` and confirm it shows current GH state vs local state
- [ ] Confirm `backlog pull` overwrites `metadata.status` to match GH label
- [ ] Confirm `backlog pull` does not overwrite `metadata.plan` or `metadata.groomed` with empty values from GH

### Priority and Label Mapping

- [ ] Confirm P2 and Ideas items never get GH issues via `backlog sync` (even if present in backlog dir)
- [ ] Confirm label transitions are atomic: old label removed and new label added in same API call [VERIFY with `gh issue view N --json labels`]
- [ ] Verify `backlog update --priority` exists or confirm re-prioritization path

### GitHub Action Integration

- [ ] Confirm GitHub Action triggers on `.claude/backlog/` file changes (read `.github/workflows/` for trigger definition)
- [ ] Confirm Action calls `backlog sync` (not a different command)
- [ ] Confirm Action runs with GITHUB_TOKEN available

### Post-Merge Behavior

- [ ] After merging a PR that fixes `#N`, confirm issue is closed on GH
- [ ] Run `backlog sync` after merge and confirm closed items are skipped
- [ ] Confirm `backlog list` excludes or marks closed/resolved items

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.