@houseofwolvesllc/claude-scrum-skill 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,471 @@
1
+ # Provider API Reference
2
+
3
+ This document maps project management operations to provider-specific API
4
+ calls. Skills reference this file when operating in remote mode (GitHub, Jira,
5
+ or Trello).
6
+
7
+ ## Authentication
8
+
9
+ ### GitHub
10
+
11
+ Requires `gh` CLI authenticated via `gh auth login`.
12
+
13
+ No environment variables needed — `gh` manages credentials internally.
14
+
15
+ ### Jira
16
+
17
+ Requires three environment variables:
18
+
19
+ | Variable | Description | Example |
20
+ |---|---|---|
21
+ | `JIRA_SITE` | Atlassian site URL (no trailing slash) | `https://yourcompany.atlassian.net` |
22
+ | `JIRA_EMAIL` | Atlassian account email | `user@example.com` |
23
+ | `JIRA_API_TOKEN` | API token from id.atlassian.com | `ATATT3x...` |
24
+
25
+ Generate a token at: Settings > Atlassian Account > Security > API Tokens
26
+
27
+ All requests use Basic auth:
28
+ ```bash
29
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
30
+ -H "Content-Type: application/json" \
31
+ "$JIRA_SITE/rest/api/3/..."
32
+ ```
33
+
34
+ ### Trello
35
+
36
+ Requires two environment variables:
37
+
38
+ | Variable | Description | Example |
39
+ |---|---|---|
40
+ | `TRELLO_API_KEY` | API key from trello.com/power-ups/admin | `a1b2c3d4...` |
41
+ | `TRELLO_TOKEN` | Auth token (generated via authorize URL) | `e5f6g7h8...` |
42
+
43
+ All requests pass credentials as query parameters:
44
+ ```bash
45
+ curl -s "https://api.trello.com/1/...?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN"
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Auth Verification
51
+
52
+ | Operation | GitHub | Jira | Trello |
53
+ |---|---|---|---|
54
+ | Check auth | `gh auth status` | `curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" "$JIRA_SITE/rest/api/3/myself"` | `curl -s "https://api.trello.com/1/members/me?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN"` |
55
+
56
+ ---
57
+
58
+ ## Epic Operations
59
+
60
+ Epics map to different concepts per provider:
61
+
62
+ | Concept | GitHub | Jira | Trello |
63
+ |---|---|---|---|
64
+ | Epic container | Milestone | Epic issue type (or Version) | List |
65
+
66
+ ### Create Epic
67
+
68
+ **GitHub:**
69
+ ```bash
70
+ gh api repos/<owner/repo>/milestones \
71
+ -f title="<Epic Name>" \
72
+ -f description="<description>" \
73
+ -f state="open"
74
+ ```
75
+
76
+ **Jira:**
77
+ ```bash
78
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
79
+ -H "Content-Type: application/json" \
80
+ -X POST "$JIRA_SITE/rest/api/3/issue" \
81
+ -d '{
82
+ "fields": {
83
+ "project": {"key": "<PROJECT_KEY>"},
84
+ "summary": "<Epic Name>",
85
+ "description": {"type":"doc","version":1,"content":[{"type":"paragraph","content":[{"type":"text","text":"<description>"}]}]},
86
+ "issuetype": {"name": "Epic"}
87
+ }
88
+ }'
89
+ ```
90
+
91
+ **Trello:**
92
+ ```bash
93
+ curl -s -X POST "https://api.trello.com/1/lists?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
94
+ -d "name=<Epic Name>&idBoard=<board-id>&pos=bottom"
95
+ ```
96
+
97
+ ### List Open Epics
98
+
99
+ **GitHub:**
100
+ ```bash
101
+ gh api repos/<owner/repo>/milestones \
102
+ --jq '.[] | select(.state=="open") | {number, title, open_issues, closed_issues}'
103
+ ```
104
+
105
+ **Jira:**
106
+ ```bash
107
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
108
+ "$JIRA_SITE/rest/api/3/search?jql=project=<KEY>+AND+issuetype=Epic+AND+status!=Done&fields=summary,status"
109
+ ```
110
+
111
+ **Trello:**
112
+ ```bash
113
+ curl -s "https://api.trello.com/1/boards/<board-id>/lists?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&filter=open"
114
+ ```
115
+
116
+ ### Close Epic
117
+
118
+ **GitHub:**
119
+ ```bash
120
+ gh api repos/<owner/repo>/milestones/<number> -X PATCH -f state="closed"
121
+ ```
122
+
123
+ **Jira:**
124
+ ```bash
125
+ # Transition the epic to Done (get transition ID first)
126
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
127
+ -X POST "$JIRA_SITE/rest/api/3/issue/<epic-key>/transitions" \
128
+ -H "Content-Type: application/json" \
129
+ -d '{"transition":{"id":"<done-transition-id>"}}'
130
+ ```
131
+
132
+ **Trello:**
133
+ ```bash
134
+ curl -s -X PUT "https://api.trello.com/1/lists/<list-id>/closed?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&value=true"
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Story/Issue Operations
140
+
141
+ | Concept | GitHub | Jira | Trello |
142
+ |---|---|---|---|
143
+ | Story | Issue | Issue (Story type) | Card |
144
+
145
+ ### Create Story
146
+
147
+ **GitHub:**
148
+ ```bash
149
+ gh issue create --repo <owner/repo> \
150
+ --title "<title>" \
151
+ --body "<body>" \
152
+ --label "type:story,executor:<type>,<priority>,epic:<slug>" \
153
+ --milestone "<Epic Name>"
154
+ ```
155
+
156
+ **Jira:**
157
+ ```bash
158
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
159
+ -H "Content-Type: application/json" \
160
+ -X POST "$JIRA_SITE/rest/api/3/issue" \
161
+ -d '{
162
+ "fields": {
163
+ "project": {"key": "<PROJECT_KEY>"},
164
+ "summary": "<title>",
165
+ "description": {"type":"doc","version":1,"content":[{"type":"paragraph","content":[{"type":"text","text":"<body>"}]}]},
166
+ "issuetype": {"name": "Story"},
167
+ "labels": ["executor:<type>", "<priority>"],
168
+ "customfield_<epic-link>": "<epic-key>"
169
+ }
170
+ }'
171
+ ```
172
+
173
+ Note: The epic link custom field ID varies per Jira instance. Discover it via:
174
+ ```bash
175
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" "$JIRA_SITE/rest/api/3/field" | jq '.[] | select(.name=="Epic Link")'
176
+ ```
177
+
178
+ **Trello:**
179
+ ```bash
180
+ curl -s -X POST "https://api.trello.com/1/cards?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
181
+ -d "name=<title>&desc=<body>&idList=<list-id>&idLabels=<label-ids>"
182
+ ```
183
+
184
+ ### List Stories
185
+
186
+ **GitHub:**
187
+ ```bash
188
+ gh issue list --repo <owner/repo> --state open --label "type:story" \
189
+ --json number,title,labels,milestone
190
+ ```
191
+
192
+ **Jira:**
193
+ ```bash
194
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
195
+ "$JIRA_SITE/rest/api/3/search?jql=project=<KEY>+AND+issuetype=Story+AND+status!=Done&fields=summary,status,labels,priority,customfield_<points>"
196
+ ```
197
+
198
+ **Trello:**
199
+ ```bash
200
+ curl -s "https://api.trello.com/1/lists/<list-id>/cards?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&fields=name,desc,labels,idMembers"
201
+ ```
202
+
203
+ ### Update Story Status
204
+
205
+ **GitHub:**
206
+ ```bash
207
+ # Close
208
+ gh issue close <number> --repo <owner/repo>
209
+ # Reopen
210
+ gh issue reopen <number> --repo <owner/repo>
211
+ ```
212
+
213
+ **Jira:**
214
+ ```bash
215
+ # Get available transitions
216
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
217
+ "$JIRA_SITE/rest/api/3/issue/<issue-key>/transitions"
218
+
219
+ # Apply transition
220
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
221
+ -X POST "$JIRA_SITE/rest/api/3/issue/<issue-key>/transitions" \
222
+ -H "Content-Type: application/json" \
223
+ -d '{"transition":{"id":"<transition-id>"}}'
224
+ ```
225
+
226
+ **Trello:**
227
+ ```bash
228
+ # Move card to a different list (e.g., Done list)
229
+ curl -s -X PUT "https://api.trello.com/1/cards/<card-id>?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
230
+ -d "idList=<done-list-id>"
231
+ ```
232
+
233
+ ### Add/Remove Labels
234
+
235
+ **GitHub:**
236
+ ```bash
237
+ gh issue edit <number> --repo <owner/repo> --add-label "<label>"
238
+ gh issue edit <number> --repo <owner/repo> --remove-label "<label>"
239
+ ```
240
+
241
+ **Jira:**
242
+ ```bash
243
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
244
+ -X PUT "$JIRA_SITE/rest/api/3/issue/<issue-key>" \
245
+ -H "Content-Type: application/json" \
246
+ -d '{"update":{"labels":[{"add":"<label>"}]}}'
247
+ ```
248
+
249
+ **Trello:**
250
+ ```bash
251
+ # Add label
252
+ curl -s -X POST "https://api.trello.com/1/cards/<card-id>/idLabels?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&value=<label-id>"
253
+ # Remove label
254
+ curl -s -X DELETE "https://api.trello.com/1/cards/<card-id>/idLabels/<label-id>?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN"
255
+ ```
256
+
257
+ ### Read Story Details
258
+
259
+ **GitHub:**
260
+ ```bash
261
+ gh issue view <number> --repo <owner/repo> --json number,title,body,labels,milestone,state
262
+ ```
263
+
264
+ **Jira:**
265
+ ```bash
266
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
267
+ "$JIRA_SITE/rest/api/3/issue/<issue-key>?fields=summary,description,status,labels,priority"
268
+ ```
269
+
270
+ **Trello:**
271
+ ```bash
272
+ curl -s "https://api.trello.com/1/cards/<card-id>?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&fields=name,desc,labels,idList,closed"
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Label Operations
278
+
279
+ ### Create Label
280
+
281
+ **GitHub:**
282
+ ```bash
283
+ gh label create "<name>" --color "<hex>" --description "<desc>" --repo <owner/repo>
284
+ ```
285
+
286
+ **Jira:**
287
+ ```bash
288
+ # Jira labels are created implicitly when applied to an issue.
289
+ # No separate create call needed.
290
+ ```
291
+
292
+ **Trello:**
293
+ ```bash
294
+ curl -s -X POST "https://api.trello.com/1/boards/<board-id>/labels?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
295
+ -d "name=<name>&color=<color>"
296
+ ```
297
+
298
+ Note: Trello has a fixed set of label colors: `green`, `yellow`, `orange`,
299
+ `red`, `purple`, `blue`, `sky`, `lime`, `pink`, `black`, `null` (no color).
300
+
301
+ ---
302
+
303
+ ## Sprint Operations
304
+
305
+ | Concept | GitHub | Jira | Trello |
306
+ |---|---|---|---|
307
+ | Sprint | Iteration field on Project | Sprint (Scrum board) | Convention: use lists named "Sprint N" |
308
+
309
+ ### Create/Start Sprint
310
+
311
+ **GitHub:**
312
+ ```bash
313
+ # Create via GraphQL — add an iteration to the Sprint field
314
+ gh api graphql -f query='mutation { ... }'
315
+ ```
316
+
317
+ **Jira:**
318
+ ```bash
319
+ # Get board ID
320
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
321
+ "$JIRA_SITE/rest/agile/1.0/board?projectKeyOrId=<KEY>"
322
+
323
+ # Create sprint
324
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
325
+ -X POST "$JIRA_SITE/rest/agile/1.0/sprint" \
326
+ -H "Content-Type: application/json" \
327
+ -d '{
328
+ "name": "Sprint <N>",
329
+ "startDate": "<ISO date>",
330
+ "endDate": "<ISO date>",
331
+ "originBoardId": <board-id>,
332
+ "goal": "<sprint goal>"
333
+ }'
334
+ ```
335
+
336
+ **Trello:**
337
+ ```bash
338
+ # Create a "Sprint N" list at the top of the board
339
+ curl -s -X POST "https://api.trello.com/1/lists?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
340
+ -d "name=Sprint <N>&idBoard=<board-id>&pos=top"
341
+ ```
342
+
343
+ ### Assign Story to Sprint
344
+
345
+ **GitHub:**
346
+ ```bash
347
+ # Update the Sprint iteration field via GraphQL
348
+ gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(...) }'
349
+ ```
350
+
351
+ **Jira:**
352
+ ```bash
353
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
354
+ -X POST "$JIRA_SITE/rest/agile/1.0/sprint/<sprint-id>/issue" \
355
+ -H "Content-Type: application/json" \
356
+ -d '{"issues":["<issue-key>"]}'
357
+ ```
358
+
359
+ **Trello:**
360
+ ```bash
361
+ # Move card to the sprint list
362
+ curl -s -X PUT "https://api.trello.com/1/cards/<card-id>?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
363
+ -d "idList=<sprint-list-id>"
364
+ ```
365
+
366
+ ### Complete Sprint
367
+
368
+ **GitHub:**
369
+ ```bash
370
+ # No explicit close — the iteration just ends by date
371
+ ```
372
+
373
+ **Jira:**
374
+ ```bash
375
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
376
+ -X POST "$JIRA_SITE/rest/agile/1.0/sprint/<sprint-id>" \
377
+ -H "Content-Type: application/json" \
378
+ -d '{"state":"closed"}'
379
+ ```
380
+
381
+ **Trello:**
382
+ ```bash
383
+ # Archive the sprint list
384
+ curl -s -X PUT "https://api.trello.com/1/lists/<sprint-list-id>/closed?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN&value=true"
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Project/Board Operations
390
+
391
+ ### Create Project/Board
392
+
393
+ **GitHub:**
394
+ ```bash
395
+ gh project create --owner <owner> --title "<name>"
396
+ ```
397
+
398
+ **Jira:**
399
+ ```bash
400
+ # Get the current user's account ID
401
+ ACCOUNT_ID=$(curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
402
+ "$JIRA_SITE/rest/api/3/myself" | jq -r '.accountId')
403
+
404
+ # Create a Scrum software project (preferred template)
405
+ curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
406
+ -X POST "$JIRA_SITE/rest/api/3/project" \
407
+ -H "Content-Type: application/json" \
408
+ -d '{
409
+ "key": "<PROJECT_KEY>",
410
+ "name": "<name>",
411
+ "projectTypeKey": "software",
412
+ "projectTemplateKey": "com.pyxis.greenhopper.jira:gh-scrum-template",
413
+ "leadAccountId": "'$ACCOUNT_ID'"
414
+ }'
415
+ ```
416
+ The Scrum template auto-creates a Scrum board with backlog and sprint support.
417
+ Save the project key to `config.json` after creation.
418
+
419
+ **Trello:**
420
+ ```bash
421
+ # Create board with no default lists (skill creates its own)
422
+ curl -s -X POST "https://api.trello.com/1/boards?key=$TRELLO_API_KEY&token=$TRELLO_TOKEN" \
423
+ -d "name=<name>&defaultLists=false"
424
+ ```
425
+ Save the board ID from the response to `config.json` after creation.
426
+
427
+ ---
428
+
429
+ ## PR / Code Review Operations
430
+
431
+ These are git-host-specific. Jira and Trello do not have native PR
432
+ functionality — PRs live in the git host (GitHub, Bitbucket, GitLab).
433
+
434
+ When using Jira or Trello as the project tracker with GitHub as the git host,
435
+ PR operations still use `gh`:
436
+
437
+ ```bash
438
+ gh pr create --repo <owner/repo> --base <base> --head <head> --title "<title>" --body "<body>"
439
+ gh pr merge <number> --repo <owner/repo> --squash
440
+ ```
441
+
442
+ If not using GitHub for git hosting, replace with direct git merges (same as
443
+ local mode):
444
+
445
+ ```bash
446
+ git checkout <base> && git merge <head> --no-ff -m "<message>"
447
+ git push origin <base>
448
+ ```
449
+
450
+ ---
451
+
452
+ ## Provider Limitations
453
+
454
+ ### Jira
455
+ - Epic link custom field ID varies per instance — must be discovered at runtime
456
+ - Transitions (status changes) require knowing the transition ID — query available transitions first
457
+ - Jira Cloud rate limits: 100 requests/minute for most endpoints
458
+ - Description uses Atlassian Document Format (ADF), not plain markdown
459
+
460
+ ### Trello
461
+ - No native sprint concept — sprints are modeled as lists
462
+ - No native story points — requires custom fields power-up
463
+ - Limited label colors (10 fixed options)
464
+ - No native issue dependencies — use checklist items or card links
465
+ - Cards don't have a "closed with resolution" concept — archived or moved to Done list
466
+ - Rate limit: 100 requests per 10 seconds per token
467
+
468
+ ### GitHub
469
+ - Project iteration fields require GraphQL for mutation
470
+ - Rate limit: 5000 requests/hour for authenticated requests
471
+ - Fine-grained PATs require explicit repo and permission scoping
@@ -9,16 +9,112 @@ Plan and populate the next sprint iteration for an existing GitHub Project.
9
9
 
10
10
  ## Before You Start
11
11
 
12
- 1. Read `../project-scaffold/references/CONVENTIONS.md` for all project management standards. Follow these conventions exactly.
13
- 2. **Terminology:** Always refer to milestones as **"epics"** in all user-facing text, summaries, and conversational output. The word "milestone" should only appear in GitHub API commands and code — never in communication with the user.
14
- 3. Confirm the `gh` CLI is authenticated by running `gh auth status`.
12
+ 1. Read `../shared/references/CONVENTIONS.md` for all project management standards. Follow these conventions exactly.
13
+ 2. Read `../shared/config.json` to determine the scaffolding mode (`scaffolding` key: `"local"`, `"github"`, `"jira"`, or `"trello"`, default: `"local"`). If `"local"`, also read the `paths.backlog` value (default: `.claude-scrum-skill/backlog`).
14
+ 3. Read `../shared/references/PROVIDERS.md` for provider-specific API commands when operating in remote mode.
15
+ 4. **Terminology:** Always refer to milestones as **"epics"** in all user-facing text, summaries, and conversational output. The word "milestone" should only appear in API commands and code — never in communication with the user.
16
+ 5. **If `scaffolding: "github"`:** Confirm the `gh` CLI is authenticated by running `gh auth status`.
17
+ 6. **If `scaffolding: "jira"`:** Verify `JIRA_SITE`, `JIRA_EMAIL`, and `JIRA_API_TOKEN` env vars are set.
18
+ 7. **If `scaffolding: "trello"`:** Verify `TRELLO_API_KEY` and `TRELLO_TOKEN` env vars are set.
19
+ 8. **If `scaffolding: "local"`:** Skip authentication. The backlog is file-based.
15
20
 
16
21
  ## Input
17
22
 
18
- `$ARGUMENTS` should be the repo identifier and optionally the project number.
19
- If not provided, detect from the current git remote or ask the user.
23
+ **GitHub mode:** `$ARGUMENTS` should be the repo identifier and optionally the project number. If not provided, detect from the current git remote or ask the user.
20
24
 
21
- ## Planning Procedure
25
+ **Jira/Trello mode:** `$ARGUMENTS` is ignored. Project key or board ID is read from config.json. Use the provider-specific API commands from PROVIDERS.md to list stories, create sprints, and assign stories — following the same planning logic as GitHub mode.
26
+
27
+ **Local mode:** `$ARGUMENTS` is ignored. Stories are read from the configured backlog path.
28
+
29
+ ---
30
+
31
+ ## Local Planning Procedure
32
+
33
+ When `scaffolding: "local"`, plan sprints by reading and updating local
34
+ backlog files.
35
+
36
+ ### Local Step 1: Assess Current State
37
+
38
+ Read the backlog directory structure:
39
+
40
+ ```bash
41
+ # List all epics
42
+ ls <backlog-path>/*/_ epic.md
43
+
44
+ # Read PROJECT.md for sprint history
45
+ cat <backlog-path>/PROJECT.md
46
+ ```
47
+
48
+ For each epic directory, read `_epic.md` (status) and all story files
49
+ (frontmatter). Gather:
50
+ - Stories by status (`backlog`, `ready`, `in-progress`, `done`)
51
+ - Any stories with `rolled-over` in their labels
52
+ - Dependency chains from `blocked_by` fields
53
+
54
+ ### Local Step 2: Calculate Capacity
55
+
56
+ Same as GitHub mode — ask the user or use defaults (20 points/sprint).
57
+
58
+ ### Local Step 3: Select Stories for Sprint
59
+
60
+ Same priority order as GitHub mode (rolled-over → unblocked → P0 → P1 → P2 →
61
+ dependencies-first). Read story points and priorities from frontmatter.
62
+
63
+ Present the proposed sprint to the user for confirmation.
64
+
65
+ ### Persona Assignment
66
+
67
+ Same as GitHub mode — check for `persona` field in story frontmatter. If
68
+ missing, apply defaults based on labels:
69
+
70
+ | Story labels | Default persona |
71
+ |---|---|
72
+ | `scope:infra`, `scope:ci`, `scope:deploy`, `scope:migration` | `ops` |
73
+ | `needs:design`, `needs:spike` | `research` |
74
+ | All other stories | `impl` (no change needed) |
75
+
76
+ Update the story file's frontmatter `persona` field.
77
+
78
+ ### Local Step 4: Assign Sprint
79
+
80
+ Create a sprint file at `<backlog-path>/sprints/sprint-<N>.md`:
81
+
82
+ ```markdown
83
+ ---
84
+ number: <N>
85
+ status: active
86
+ start: <ISO date>
87
+ end: <ISO date>
88
+ velocity_target: <points>
89
+ velocity_actual: null
90
+ ---
91
+
92
+ # Sprint <N>
93
+
94
+ ## Stories
95
+ | File | Title | Executor | Persona | Points | Priority | Status |
96
+ |------|-------|----------|---------|--------|----------|--------|
97
+ | core-api/001-user-auth.md | User auth endpoint | claude | impl | 5 | P1-high | ready |
98
+ ...
99
+ ```
100
+
101
+ Update each selected story's frontmatter:
102
+ - Set `sprint: <N>`
103
+ - Set `status: ready` (or `backlog` if dependencies aren't met)
104
+
105
+ ### Local Step 5: Ensure Branch Exists
106
+
107
+ Same as GitHub mode — create release branches from `development` for each
108
+ active epic. Git operations work identically in local mode.
109
+
110
+ ### Local Step 6: Generate Sprint Kickoff Summary
111
+
112
+ Same format as GitHub mode, but reference story file paths instead of issue
113
+ numbers.
114
+
115
+ ---
116
+
117
+ ## GitHub Planning Procedure
22
118
 
23
119
  ### Step 1: Assess Current State
24
120
 
@@ -97,6 +193,28 @@ For each story in the sprint:
97
193
  - Set Status to "Ready" (or "Backlog" if dependencies aren't met yet)
98
194
  - Verify labels are correct
99
195
 
196
+ ### Persona Assignment
197
+
198
+ For each story assigned to the sprint, check for an existing `persona:*`
199
+ label. If none exists, apply a default based on the story's other labels:
200
+
201
+ | Story labels | Default persona |
202
+ |---|---|
203
+ | `scope:infra`, `scope:ci`, `scope:deploy`, `scope:migration` | `persona:ops` |
204
+ | `needs:design`, `needs:spike` | `persona:research` |
205
+ | All other stories | No label needed (implicit `impl`) |
206
+
207
+ Apply the label:
208
+
209
+ ```bash
210
+ # Only if the story doesn't already have a persona:* label
211
+ gh issue edit <number> --repo <owner/repo> --add-label "persona:ops"
212
+ ```
213
+
214
+ This is a default heuristic. Users can override by manually labeling stories
215
+ before planning. The orchestrator reads whatever label is present at
216
+ execution time.
217
+
100
218
  ### Step 5: Ensure Branch Exists
101
219
 
102
220
  ```bash