Speclet Ticket Skill
Convert a large draft document into individual tickets for isolated implementation sessions.
What I Do
- Read
.speclet/draft.mdand identify discrete work items - Create ticket folders at
.speclet/tickets/TICKET-N/ - Generate ticket metadata at
.speclet/tickets/TICKET-N/ticket.json - Copy general draft to
.speclet/tickets/TICKET-N/ticket-draft.md - Create/update
.speclet/tickets/index.jsonfor centralized status tracking - Delete root
draft.mdonly after ALL tickets are successfully created - Enable ticket-by-ticket workflow: one ticket → one session → full speclet cycle
When to Use Me
Use this when:
- A draft contains multiple independent fixes/features
- The combined scope would overwhelm LLM context
- You want to work on items one at a time across sessions
Your Task
Step 1: Read the Draft
Read .speclet/draft.md
Identify discrete work items. Each item that can be implemented independently = 1 ticket.
Splitting Rule: 1 ticket = 1 friction/problem. Maximum atomicity.
Step 2: Ask Clarifying Questions (if needed)
If the draft is ambiguous about how to split, ask questions with lettered options.
Example:
1. How should I group these items?
A. One ticket per file mentioned ⭐ Recommended — maximum isolation
B. Group by feature area
C. Group by complexity
D. Keep as single ticket
**Reason for recommendation:** Isolated tickets prevent context bleed and allow
prioritization between sessions.
Global Rules
Always Show Recommendation + Reason
When asking questions with options, ALWAYS:
- Mark the recommended option with ⭐
- Add
**Reason for recommendation:**explaining why
Example format:
1. [Question]?
A. Option A
B. Option B ⭐ Recommended — [brief reason]
C. Option C
**Reason for recommendation:** [Detailed explanation of why B is best]
Step 3: Create Ticket Files and Folders
For each discrete item:
- Create ticket folder:
.speclet/tickets/TICKET-N/ - Copy draft to folder:
.speclet/tickets/TICKET-N/ticket-draft.md - Create ticket JSON:
.speclet/tickets/TICKET-N/ticket.json
IMPORTANT: Complete ALL tickets before proceeding to Step 4. Do NOT delete draft.md until all tickets exist.
Ticket JSON Structure
{
"specletVersion": "1.0",
"id": "TICKET-1",
"title": "Short descriptive title",
"description": "2-3 sentences explaining the problem/friction and desired outcome",
"files": ["path/to/likely/affected/file.ts"],
"sourceContext": ".speclet/draft.md",
"preliminaryCriteria": [
"Preliminary acceptance criterion (will be refined in speclet-draft)",
"Another criterion"
],
"priority": 1,
"dependsOn": [],
"retryHints": [],
"status": "pending"
}
Field Descriptions
| Field | Required | Description |
|-------|----------|-------------|
| specletVersion | Yes | Always "1.0" — identifies this as a speclet ticket |
| id | Yes | Unique identifier (TICKET-1, TICKET-2, etc.) |
| title | Yes | Short title (< 80 chars) |
| description | Yes | 2-3 sentences explaining the problem and desired outcome |
| files | Yes | Array of likely affected files (best guess, refined later) |
| sourceContext | Yes | Absolute path to the original source document with optional anchor |
| preliminaryCriteria | Yes | Initial acceptance criteria (refined during speclet-draft) |
| priority | Yes | Numeric priority (1 = highest) |
| dependsOn | No | Array of ticket IDs that must complete first |
| retryHints | No | Accumulated hints from failed attempts |
| status | Yes | One of: pending, in_progress, done, blocked |
specletVersion Field (CRITICAL)
The specletVersion field is mandatory. It serves two purposes:
- Identification: Allows
speclet-draftto recognize this as a speclet-generated ticket - Compatibility: Future versions can check compatibility
If specletVersion is missing, other skills will NOT recognize this as a speclet ticket.
sourceContext Best Practices
The sourceContext field must point to the original source of the requirement:
✅ Good sourceContext values:
.speclet/draft.mdGitHub Issue #123Code review comment on PR #456
❌ Bad sourceContext values:
TICKET-1.json— Self-referential"From the analysis"— Not traceable
Step 4: Create/Update Index
Create or update .speclet/tickets/index.json:
{
"specletVersion": "1.0",
"source": "docs/original-analysis.md",
"createdAt": "2025-01-09T15:30:00Z",
"tickets": [
{
"id": "TICKET-1",
"title": "Fix empty state guidance",
"status": "pending",
"priority": 1
},
{
"id": "TICKET-2",
"title": "Improve serial scanner UX",
"status": "pending",
"priority": 2
}
]
}
Note: The source field in index.json should point to the original source document .speclet/draft.md.
Step 5: Delete Root Draft (ONLY AFTER ALL TICKETS CREATED)
Pre-condition check (MANDATORY):
Before deleting, verify:
- All ticket folders exist:
.speclet/tickets/TICKET-1/,.speclet/tickets/TICKET-2/, etc. - Each folder has
ticket.jsonandticket-draft.md index.jsonexists and lists all tickets
# Verification command
ls .speclet/tickets/*/ticket.json | wc -l # Should equal number of tickets
ls .speclet/tickets/*/ticket-draft.md | wc -l # Should equal number of tickets
Only if verification passes:
rm .speclet/draft.md
If verification fails: STOP. Do not delete draft.md. Report which tickets are missing.
This ensures:
- No confusion about which draft to use
- Clean state for next workflow
- Each ticket has its own
ticket-draft.mdas context
Step 6: Confirm with User
After creating tickets, summarize:
✅ Created N tickets from draft.md
| ID | Title | Priority | Dependencies |
|----|-------|----------|--------------|
| TICKET-1 | [title] | 1 | - |
| TICKET-2 | [title] | 2 | TICKET-1 |
📁 Structure created:
.speclet/tickets/
├── index.json
├── TICKET-1/
│ ├── ticket.json
│ └── ticket-draft.md
├── TICKET-2/
│ ├── ticket.json
│ └── ticket-draft.md
🗑️ Deleted: .speclet/draft.md
**Next steps:**
1. Start new session
2. Pick a ticket: "Use speclet-draft for TICKET-1"
3. Complete full cycle: draft → spec → loop
4. Come back for next ticket
Workflow Integration
PHASE 1: Analysis (this session)
────────────────────────────────
speclet-draft (general analysis)
│
▼
.speclet/draft.md
│
▼
speclet-ticket (this skill)
│
├── Creates .speclet/tickets/TICKET-N/ticket.json
├── Creates .speclet/tickets/TICKET-N/ticket-draft.md
├── Creates .speclet/tickets/index.json
├── Verifies ALL tickets created successfully
├── Deletes .speclet/draft.md (only after verification)
└── END of session
════════════════════════════════════════════════════════════
PHASE 2: Per-ticket work (new session)
──────────────────────────────────────
User: "speclet-draft for TICKET-1"
│
├── Reads .speclet/tickets/TICKET-1/ticket.json (validates specletVersion)
├── Reads .speclet/tickets/TICKET-1/ticket-draft.md
├── Asks clarifying questions
└── Creates .speclet/draft.md (refined)
│
▼
speclet-spec → .speclet/spec.json
│
▼
speclet-loop → implements
│
▼
On completion:
├── Move draft.md → tickets/TICKET-1/draft.md
├── Move spec.json → tickets/TICKET-1/spec.json
├── Update ticket.json status to "done"
└── Ready for next ticket
Post-Completion Artifact Preservation
After completing a ticket with speclet-loop, preserve artifacts:
# Move refined draft (keeps ticket-draft.md as original context)
mv .speclet/draft.md .speclet/tickets/TICKET-1/draft.md
# Move spec
mv .speclet/spec.json .speclet/tickets/TICKET-1/spec.json
# Update ticket status
# Edit .speclet/tickets/TICKET-1/ticket.json: "status": "done"
Final structure for completed ticket:
.speclet/tickets/TICKET-1/
├── ticket.json ← Metadata (status: done)
├── ticket-draft.md ← Original context (from speclet-ticket)
├── draft.md ← Refined draft (from speclet-draft for TICKET-1)
└── spec.json ← Implementation spec (from speclet-spec)
Rules
- One friction = one ticket — Maximum atomicity
- specletVersion required — All tickets must have
"specletVersion": "1.0" - ticket-draft.md in each folder — Copy of general draft for context
- Delete root draft after tickets — Clean state for next workflow
- Dependencies are declarative — Field exists but no automated blocking
- Preliminary criteria only — Real criteria come from speclet-draft
- Status tracking — Update index.json when ticket status changes
- sourceContext = original source — Point to real origin, not speclet artifacts
Output
- Ticket folders:
.speclet/tickets/TICKET-N/ - Ticket metadata:
.speclet/tickets/TICKET-N/ticket.json - Ticket context:
.speclet/tickets/TICKET-N/ticket-draft.md - Central index:
.speclet/tickets/index.json - Root draft: DELETED (only after all tickets verified)
When complete:
"Tickets created in
.speclet/tickets/. Root draft deleted. Start new session and use: speclet-draft for TICKET-1"