@comfanion/workflow 4.37.1 → 4.38.0-dev.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/workflow",
3
- "version": "4.37.1",
3
+ "version": "4.38.0-dev.1",
4
4
  "description": "Initialize OpenCode Workflow system for AI-assisted development with semantic code search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.37.1",
3
- "buildDate": "2026-01-26T20:31:11.486Z",
2
+ "version": "4.38.0-dev.1",
3
+ "buildDate": "2026-01-26T23:39:37.098Z",
4
4
  "files": [
5
5
  "config.yaml",
6
6
  "FLOW.yaml",
@@ -254,6 +254,83 @@ pipeline:
254
254
  # IMPLEMENTATION PHASE
255
255
  # =========================================================================
256
256
 
257
+ - id: dev-sprint
258
+ name: Sprint Implementation (Full Workflow)
259
+ description: Implement entire sprint - all epics with auto-compaction
260
+ phase: implementation
261
+ command: /dev-sprint [sprint-number]
262
+ agent: dev
263
+ skills:
264
+ - dev-story
265
+ - test-design
266
+ - code-review
267
+ artifacts:
268
+ input:
269
+ - docs/sprint-artifacts/sprint-status.yaml
270
+ - docs/sprint-artifacts/backlog/epic-*.md
271
+ - CLAUDE.md
272
+ output:
273
+ - All epic implementations
274
+ - Updated sprint-status.yaml
275
+ - Sprint summary report
276
+ workflow:
277
+ description: |
278
+ Execute all epics in sprint sequentially:
279
+ 1. Read sprint-status.yaml, find epics
280
+ 2. For each epic: /dev-epic → compact
281
+ 3. Continue until all epics done
282
+ 4. Run sprint integration tests
283
+ config:
284
+ auto_compact: "config.yaml → epic_workflow.auto_compact"
285
+ auto_fix: "config.yaml → epic_workflow.auto_fix"
286
+ next: dev-epic # Can also run individual epics
287
+
288
+ - id: dev-epic
289
+ name: Epic Implementation (Full Workflow)
290
+ description: Implement entire epic - all stories with auto-compaction
291
+ phase: implementation
292
+ command: /dev-epic [epic-path]
293
+ agent: dev
294
+ skills:
295
+ - dev-story
296
+ - test-design
297
+ - code-review
298
+ artifacts:
299
+ input:
300
+ - docs/sprint-artifacts/backlog/epic-*.md
301
+ - docs/sprint-artifacts/sprint-*/.sprint-state/epic-*-state.yaml
302
+ - CLAUDE.md
303
+ output:
304
+ - All story implementations
305
+ - Epic state file (updated)
306
+ - Epic summary report
307
+ workflow:
308
+ description: |
309
+ Execute all stories in epic sequentially:
310
+ 1. Read epic file, find stories
311
+ 2. For each story: /dev-story → @reviewer → compact
312
+ 3. Auto-fix review issues (max 3 attempts)
313
+ 4. Continue until all stories done
314
+ 5. Run epic integration tests
315
+ state_management:
316
+ location: "docs/sprint-artifacts/sprint-N/.sprint-state/epic-XX-state.yaml"
317
+ preserves:
318
+ - Current story index
319
+ - Completed stories
320
+ - Pending stories
321
+ - Review status
322
+ compaction:
323
+ trigger: "After each story completion"
324
+ restores:
325
+ - Epic state file (progress)
326
+ - Next story file (what to do)
327
+ - CLAUDE.md, PRD, Architecture (context)
328
+ config:
329
+ auto_compact: "config.yaml → epic_workflow.auto_compact"
330
+ auto_fix: "config.yaml → epic_workflow.auto_fix"
331
+ max_fix_attempts: "config.yaml → epic_workflow.max_fix_attempts"
332
+ next: dev-story # Can also run individual stories
333
+
257
334
  - id: dev-story
258
335
  name: Story Implementation
259
336
  description: Implement story using red-green-refactor cycle
@@ -96,9 +96,31 @@ permission:
96
96
  <phase name="1. Discovery">
97
97
  <action>Search for related documents (search → then glob/grep if needed)</action>
98
98
  <action>Read existing architecture, PRD, related modules</action>
99
- <action>If PRD exists: Read "Project Classification" section to understand size</action>
99
+ <action critical="MANDATORY">Read PRD "Project Classification" section (first section) to understand project size</action>
100
+ <action>If no PRD: Load skill `architecture-design` → check size guidelines table</action>
100
101
  <action>Identify what needs to be created/updated</action>
101
102
  </phase>
103
+
104
+ <size-awareness critical="MANDATORY">
105
+ BEFORE writing architecture, you MUST know project size:
106
+
107
+ 1. Read PRD → "Project Classification" section
108
+ 2. Note the size: TOY/SMALL/MEDIUM/LARGE/ENTERPRISE
109
+ 3. Load skill: architecture-design → see size guidelines table
110
+ 4. Adapt your architecture depth:
111
+ - TOY: 200-500 lines, simple diagram
112
+ - SMALL: 500-1000 lines, C4 Context+Container+Component
113
+ - MEDIUM: 1000-2000 lines, full C4 + break into MODULES
114
+ - LARGE: 2000-4000 lines, multiple files, DOMAINS
115
+ - ENTERPRISE: 4000+ lines, per-domain files
116
+
117
+ Example:
118
+ - PRD says "TOY" → Write 350 lines, 3 components, NO modules
119
+ - PRD says "MEDIUM" → Write 1500 lines, 3 MODULES with Unit docs
120
+
121
+ DON'T write 2000-line architecture for Tetris!
122
+ DON'T write 500-line architecture for E-commerce!
123
+ </size-awareness>
102
124
 
103
125
  <phase name="2. Planning">
104
126
  <action>Create tasklist with todowrite()</action>
@@ -148,8 +148,25 @@ permission:
148
148
  <instruction>BEFORE starting ANY work (PRD, epics, stories):</instruction>
149
149
 
150
150
  <step n="1">If PRD exists: Read "Project Classification" section (first section)</step>
151
- <step n="2">If no PRD: Load skill `prd-writing` to understand size classification</step>
152
- <step n="3">Adapt your approach based on size</step>
151
+ <step n="2">If no PRD yet: Load skill `prd-writing` → read "How to Classify Project Size" section</step>
152
+ <step n="3">Determine project size based on scope/complexity/data/integrations (NOT timeline!)</step>
153
+ <step n="4">If creating PRD: Fill "Project Classification" section FIRST before writing anything else</step>
154
+ <step n="5">Adapt your approach based on size</step>
155
+
156
+ <classification-reminder>
157
+ When creating PRD, you MUST:
158
+ 1. Load skill: prd-writing
159
+ 2. Read the classification guide in the skill
160
+ 3. Ask user about: scope, data model, integrations, team size
161
+ 4. Classify: TOY/SMALL/MEDIUM/LARGE/ENTERPRISE
162
+ 5. Fill Project Classification table in PRD (first section!)
163
+ 6. Then write rest of PRD according to that size
164
+
165
+ Example questions:
166
+ - "How many database tables do you expect?" (5-10 = SMALL, 20+ = MEDIUM)
167
+ - "How many external integrations?" (0-2 = SMALL, 3-5 = MEDIUM)
168
+ - "Is this a single app or multiple modules?" (single = SMALL, modules = MEDIUM)
169
+ </classification-reminder>
153
170
 
154
171
  <key-principle>
155
172
  TOY/SMALL → Flat structure, no modules
@@ -0,0 +1,169 @@
1
+ ---
2
+ description: Execute full epic - implement all stories sequentially with auto-compaction between stories
3
+ agent: dev
4
+ ---
5
+
6
+ # /dev-epic Command
7
+
8
+ Implement entire epic by executing all stories with automatic compaction and context preservation.
9
+
10
+ ## Process
11
+
12
+ ### Phase 1: Epic Setup
13
+ 1. Find or load epic file (from path or sprint-status.yaml)
14
+ 2. Parse all story references from epic
15
+ 3. Load project context (CLAUDE.md, docs/prd.md, docs/architecture.md)
16
+ 4. **Create TODO list from epic** (critical for compaction!):
17
+ - Parse epic file, extract all stories
18
+ - For each story: read story file, count tasks
19
+ - Add stories to TODO with task counts
20
+ - Add epic-level tasks (integration tests, acceptance criteria)
21
+ ```
22
+ [ ] Story 1: User Registration (12 tasks)
23
+ [ ] Story 2: Login Flow (8 tasks)
24
+ [ ] Story 3: Password Reset (6 tasks)
25
+ [ ] Run epic integration tests
26
+ [ ] Verify all acceptance criteria
27
+ ```
28
+ 5. **Create epic state file:** `docs/sprint-artifacts/sprint-N/.sprint-state/epic-XX-state.yaml`
29
+ 6. Mark epic as `in-progress`
30
+
31
+ ### Phase 2: Story Execution Loop (for each story)
32
+
33
+ 7. **Mark story as `in_progress` in TODO** (e.g., "Story 1: User Registration")
34
+ 8. Execute story via `/dev-story` workflow:
35
+ - RED → GREEN → REFACTOR
36
+ - @coder implements tasks
37
+ - @reviewer validates (if auto_review: true)
38
+ 9. **Mark story as `completed` in TODO** (✓ Story 1: User Registration)
39
+ 10. **Update epic state file**:
40
+ - Move story from `pending_stories` → `completed_stories`
41
+ - Add metadata (tasks_completed, tests_added, review_status)
42
+ - Increment `current_story_index`
43
+ - Set `next_action: "Execute story-XX-XX.md"` (next story filename)
44
+ - Update `last_compaction` timestamp
45
+ 11. **Trigger compaction** (if `epic_workflow.auto_compact: true`)
46
+ 12. **After compaction:**
47
+ - Plugin reads TODO → sees next pending story
48
+ - Plugin reads epic state → gets story path
49
+ - Agent continues next story automatically
50
+
51
+ ### Phase 3: Epic Completion
52
+
53
+ 13. All stories done → **mark integration test TODO as `in_progress`**
54
+ 14. Run epic integration tests (if configured)
55
+ 15. **Mark integration test TODO as `completed`**
56
+ 16. Update epic state: `status: "done"`
57
+ 17. **Clear TODO** (all tasks done)
58
+ 18. Generate epic summary
59
+
60
+ ## TODO List
61
+
62
+ **Create at epic start:**
63
+ ```
64
+ [ ] Story 1: User Registration
65
+ [ ] Story 2: Login Flow
66
+ [ ] Story 3: Password Reset
67
+ [ ] Run epic integration tests
68
+ [ ] Verify acceptance criteria
69
+ ```
70
+
71
+ **Update after each story:**
72
+ - Mark story `completed` in TODO
73
+ - Mark next story `in_progress` in TODO
74
+ - TODO survives compaction - plugin shows it to agent
75
+
76
+ ## Epic State File Format
77
+
78
+ **Location:** `docs/sprint-artifacts/sprint-N/.sprint-state/epic-XX-state.yaml`
79
+
80
+ ```yaml
81
+ epic_id: "PROJ-E01"
82
+ epic_title: "User Authentication"
83
+ epic_path: "docs/sprint-artifacts/backlog/epic-01-user-auth.md"
84
+ sprint: "sprint-1"
85
+ status: "in-progress"
86
+
87
+ current_story_index: 1
88
+ total_stories: 3
89
+
90
+ completed_stories:
91
+ - path: "docs/sprint-artifacts/sprint-1/stories/story-01-01-registration.md"
92
+ title: "User Registration"
93
+ tasks_completed: 12
94
+ tests_added: 45
95
+ review_status: "approved"
96
+ completed_at: "2026-01-27T10:15:00Z"
97
+
98
+ pending_stories:
99
+ - path: "docs/sprint-artifacts/sprint-1/stories/story-01-02-login.md"
100
+ title: "Login Flow"
101
+ - path: "docs/sprint-artifacts/sprint-1/stories/story-01-03-password-reset.md"
102
+ title: "Password Reset"
103
+
104
+ next_action: "Execute story-01-02-login.md"
105
+ last_compaction: "2026-01-27T10:15:00Z"
106
+ ```
107
+
108
+ ## Compaction Strategy
109
+
110
+ **After compaction, agent reads (minimal context):**
111
+ 1. Epic state file (progress + next action)
112
+ 2. Next story file (from `next_action`)
113
+ 3. CLAUDE.md, docs/prd.md, docs/architecture.md
114
+
115
+ **Agent does NOT re-read:**
116
+ - ❌ Epic file (info in state)
117
+ - ❌ Completed stories
118
+ - ❌ Previous tasks
119
+
120
+ **Context savings: ~68% less than reading all files**
121
+
122
+ ## Configuration
123
+
124
+ From `config.yaml → epic_workflow`:
125
+
126
+ ```yaml
127
+ epic_workflow:
128
+ auto_compact: true # Compact between stories
129
+ auto_fix: true # Auto-fix review issues
130
+ max_fix_attempts: 3 # Max fix attempts before HALT
131
+ pause_between_stories: false # Continue automatically
132
+ test_after_each_story: false # Skip per-story integration tests
133
+ test_after_epic: true # Run epic integration tests at end
134
+ ```
135
+
136
+ ## IMPORTANT SKILLS TO LOAD
137
+
138
+ - `dev-story` - Story implementation workflow
139
+ - `test-design` - Test writing patterns
140
+ - `code-review` - Review and validation
141
+
142
+ ## Output
143
+
144
+ - All story implementations (code + tests)
145
+ - Epic state file (updated)
146
+ - Updated epic file (stories marked `[x]`)
147
+ - Epic summary report
148
+
149
+ ## HALT Conditions
150
+
151
+ The workflow will HALT and ask for input when:
152
+ - Story fails 3 times (implementation/tests)
153
+ - Code review fails after max_fix_attempts
154
+ - Missing dependencies
155
+ - Ambiguous requirements
156
+ - Integration tests fail
157
+
158
+ ## Epic Status Flow
159
+
160
+ ```
161
+ ready-for-dev → in-progress → [story 1] → compact → [story 2] → compact → ... → done
162
+ ```
163
+
164
+ ## Next Steps After Completion
165
+
166
+ - Epic marked `done` in epic state file
167
+ - All stories marked `done`
168
+ - If part of `/dev-sprint`: continue to next epic automatically
169
+ - If standalone: ready for sprint review
@@ -0,0 +1,178 @@
1
+ ---
2
+ description: Execute full sprint - implement all epics sequentially with auto-compaction between epics
3
+ agent: dev
4
+ ---
5
+
6
+ # /dev-sprint Command
7
+
8
+ Implement entire sprint by executing all epics with automatic compaction.
9
+
10
+ ## Process
11
+
12
+ ### Phase 1: Sprint Setup
13
+ 1. Find sprint (from number or sprint-status.yaml)
14
+ 2. Read `sprint-status.yaml`
15
+ 3. Parse all epics in sprint
16
+ 4. Load project context (CLAUDE.md, docs/prd.md, docs/architecture.md)
17
+ 5. **Create TODO list from sprint** (critical for compaction!):
18
+ - Parse sprint-status.yaml, extract all epics
19
+ - For each epic: read epic file, count stories and tasks
20
+ - Add epics to TODO with story/task counts
21
+ - Add sprint-level tasks (integration tests, acceptance criteria, metrics)
22
+ ```
23
+ [ ] Epic 1: User Authentication (3 stories, 26 tasks)
24
+ [ ] Epic 2: Product Catalog (5 stories, 42 tasks)
25
+ [ ] Epic 3: Shopping Cart (4 stories, 31 tasks)
26
+ [ ] Run sprint integration tests
27
+ [ ] Verify sprint acceptance criteria
28
+ [ ] Generate sprint metrics
29
+ ```
30
+ 6. Mark sprint as `in-progress` in sprint-status.yaml
31
+
32
+ ### Phase 2: Epic Execution Loop (for each epic)
33
+
34
+ 7. **Mark epic as `in_progress` in TODO** (e.g., "Epic 1: User Authentication")
35
+ 8. Execute epic via `/dev-epic` workflow:
36
+ - Epic creates its own TODO for stories
37
+ - Epic executes all stories
38
+ - Auto-compacts between stories
39
+ - Auto-fixes code review issues
40
+ 9. **Mark epic as `completed` in TODO** (✓ Epic 1: User Authentication)
41
+ 10. **Update sprint-status.yaml**:
42
+ - Mark epic as `done`
43
+ - Update `stories_completed` count
44
+ - Find next epic
45
+ 11. **Trigger compaction** (if `epic_workflow.auto_compact: true`)
46
+ 12. **After compaction:**
47
+ - Plugin reads TODO → sees next pending epic
48
+ - Plugin reads sprint-status.yaml → gets epic path
49
+ - Agent continues next epic automatically
50
+
51
+ ### Phase 3: Sprint Completion
52
+
53
+ 13. All epics done → **mark integration test TODO as `in_progress`**
54
+ 14. Run sprint integration tests (if configured)
55
+ 15. **Mark integration test TODO as `completed`**
56
+ 16. **Mark acceptance criteria TODO as `in_progress`**
57
+ 17. Verify sprint acceptance criteria
58
+ 18. **Mark acceptance criteria TODO as `completed`**
59
+ 19. **Mark metrics TODO as `in_progress`**
60
+ 20. Generate sprint metrics (velocity, completion rate, etc.)
61
+ 21. **Mark metrics TODO as `completed`**
62
+ 22. Update sprint-status.yaml: `status: "done"`
63
+ 23. **Clear TODO** (all tasks done)
64
+ 24. Generate sprint summary
65
+
66
+ ## TODO List
67
+
68
+ **Create at sprint start:**
69
+ ```
70
+ [ ] Epic 1: User Authentication (3 stories)
71
+ [ ] Epic 2: Product Catalog (5 stories)
72
+ [ ] Epic 3: Shopping Cart (4 stories)
73
+ [ ] Run sprint integration tests
74
+ [ ] Verify sprint acceptance criteria
75
+ [ ] Generate sprint metrics
76
+ ```
77
+
78
+ **Update after each epic:**
79
+ - Mark epic `completed` in TODO
80
+ - Mark next epic `in_progress` in TODO
81
+ - TODO survives compaction - plugin shows it to agent
82
+
83
+ **Note:** Each epic creates its own TODO for stories, clears it when done
84
+
85
+ ## Sprint State Tracking
86
+
87
+ **Location:** `docs/sprint-artifacts/sprint-status.yaml`
88
+
89
+ ```yaml
90
+ sprints:
91
+ - id: sprint-1
92
+ name: "Sprint 1 - Core Features"
93
+ status: in-progress
94
+ start_date: "2026-01-20"
95
+ end_date: "2026-02-03"
96
+
97
+ epics:
98
+ - id: PROJ-E01
99
+ title: "User Authentication"
100
+ path: "docs/sprint-artifacts/backlog/epic-01-user-auth.md"
101
+ status: done
102
+ stories_completed: 3
103
+ stories_total: 3
104
+
105
+ - id: PROJ-E02
106
+ title: "Product Catalog"
107
+ path: "docs/sprint-artifacts/backlog/epic-02-catalog.md"
108
+ status: in-progress # ← Current epic
109
+ stories_completed: 2
110
+ stories_total: 5
111
+
112
+ - id: PROJ-E03
113
+ title: "Shopping Cart"
114
+ path: "docs/sprint-artifacts/backlog/epic-03-cart.md"
115
+ status: ready-for-dev
116
+ stories_total: 4
117
+ ```
118
+
119
+ Each epic also has state file in `.sprint-state/epic-XX-state.yaml`
120
+
121
+ ## Compaction Strategy
122
+
123
+ **After compaction, agent reads:**
124
+ 1. sprint-status.yaml (knows which epic is next)
125
+ 2. Next epic file
126
+ 3. Next epic state file (if exists)
127
+ 4. CLAUDE.md, docs/prd.md, docs/architecture.md
128
+
129
+ **Agent does NOT re-read:**
130
+ - ❌ Completed epic files
131
+ - ❌ Completed story files
132
+ - ❌ Previous epic states
133
+
134
+ ## Configuration
135
+
136
+ From `config.yaml → epic_workflow`:
137
+
138
+ ```yaml
139
+ epic_workflow:
140
+ auto_compact: true # Compact between epics
141
+ auto_fix: true # Auto-fix review issues
142
+ pause_between_stories: false # Continue automatically
143
+ ```
144
+
145
+ ## IMPORTANT SKILLS TO LOAD
146
+
147
+ - `dev-story` - Story implementation workflow
148
+ - `test-design` - Test writing patterns
149
+ - `code-review` - Review and validation
150
+
151
+ ## Output
152
+
153
+ - All epic implementations (code + tests)
154
+ - Updated sprint-status.yaml
155
+ - Sprint summary report
156
+ - Sprint metrics (velocity, completion rate)
157
+
158
+ ## HALT Conditions
159
+
160
+ The workflow will HALT and ask for input when:
161
+ - Epic fails repeatedly (3+ failed stories)
162
+ - Multiple stories rejected by @reviewer
163
+ - Sprint deadline approaching (< 20% time, > 50% work)
164
+ - Missing dependencies
165
+ - Sprint integration tests fail
166
+
167
+ ## Sprint Status Flow
168
+
169
+ ```
170
+ planned → in-progress → [epic 1] → compact → [epic 2] → compact → ... → done
171
+ ```
172
+
173
+ ## Next Steps After Completion
174
+
175
+ - Sprint marked `done` in sprint-status.yaml
176
+ - All epics and stories marked `done`
177
+ - Ready for sprint review/retrospective
178
+ - Run `/retrospective` to capture learnings
@@ -197,6 +197,53 @@ development:
197
197
  - NUMBERS # Add metrics/numbers
198
198
  - LINK # Add links/references
199
199
 
200
+ # =============================================================================
201
+ # EPIC WORKFLOW (/dev-epic command)
202
+ # =============================================================================
203
+ epic_workflow:
204
+ # Auto-compact between stories (saves context, continues next story)
205
+ # When true: story done → compact → restore context → next story
206
+ # When false: story done → ask user to continue
207
+ auto_compact: true
208
+
209
+ # Auto-fix code review issues
210
+ # When true: review failed → @coder fixes → re-review → continue
211
+ # When false: review failed → HALT, ask user
212
+ auto_fix: true
213
+
214
+ # Max fix attempts before HALT (prevents infinite loops)
215
+ max_fix_attempts: 3
216
+
217
+ # Pause between stories for manual review
218
+ # When true: story done → show summary → ask to continue
219
+ # When false: story done → immediately start next story
220
+ pause_between_stories: false
221
+
222
+ # Run integration tests after each story
223
+ # When true: story done → run integration tests → continue
224
+ # When false: skip per-story integration tests
225
+ test_after_each_story: false
226
+
227
+ # Run integration tests after epic complete
228
+ # When true: all stories done → run epic integration tests
229
+ # When false: skip epic integration tests
230
+ test_after_epic: true
231
+
232
+ # Compaction strategy
233
+ compaction:
234
+ # Save epic state to sprint-status.yaml
235
+ save_epic_state: true
236
+
237
+ # Files to preserve in context after compaction
238
+ preserve_files:
239
+ - "CLAUDE.md"
240
+ - "AGENTS.md"
241
+ - "docs/prd.md"
242
+ - "docs/architecture.md"
243
+ - "docs/coding-standards/README.md"
244
+ - "docs/coding-standards/patterns.md"
245
+ # Epic file and next story added dynamically
246
+
200
247
  # =============================================================================
201
248
  # CHANGELOG
202
249
  # =============================================================================
@@ -52,10 +52,11 @@ Checks for updates and shows a toast notification if a newer version is availabl
52
52
 
53
53
  ### custom-compaction.ts
54
54
 
55
- Intelligent session compaction that preserves flow context.
55
+ Intelligent session compaction that preserves flow context with epic workflow support.
56
56
 
57
57
  **Features:**
58
58
  - Tracks todo list and story task status
59
+ - **Epic workflow state preservation** (new!)
59
60
  - Identifies critical documentation files for context
60
61
  - Generates smart continuation prompts
61
62
  - Differentiates between completed and interrupted tasks
@@ -68,8 +69,31 @@ Intelligent session compaction that preserves flow context.
68
69
  |----------|-------------------|
69
70
  | **Task Completed** | Summary of completed work, next steps, validation reminders |
70
71
  | **Task Interrupted** | Current task, what was done, resume instructions, file list |
72
+ | **Epic in Progress** | Epic state file, current story, next action, minimal context |
73
+
74
+ **Epic Workflow Support:**
75
+
76
+ When `/dev-epic` is running, the plugin:
77
+ 1. Finds active epic state file in `sprint-N/.sprint-state/epic-XX-state.yaml`
78
+ 2. Reads current story from epic state
79
+ 3. Generates minimal read commands:
80
+ - Epic state file (progress tracking)
81
+ - Next story file (what to do)
82
+ - CLAUDE.md, PRD, Architecture (context)
83
+ 4. Agent resumes automatically without re-reading completed stories
84
+
85
+ **Epic State File Location:**
86
+ ```
87
+ docs/sprint-artifacts/
88
+ sprint-1/
89
+ .sprint-state/
90
+ epic-01-state.yaml # Tracks epic-01 progress
91
+ epic-02-state.yaml # Tracks epic-02 progress
92
+ ```
71
93
 
72
94
  **Critical Files Passed to Context:**
95
+
96
+ **For regular /dev-story:**
73
97
  - `CLAUDE.md` - Project coding standards
74
98
  - `AGENTS.md` - Agent definitions
75
99
  - `project-context.md` - Project overview
@@ -79,6 +103,13 @@ Intelligent session compaction that preserves flow context.
79
103
  - `docs/coding-standards/*.md` - Coding patterns
80
104
  - Active story file (if in progress)
81
105
 
106
+ **For /dev-epic workflow:**
107
+ - Epic state file (e.g., `sprint-1/.sprint-state/epic-01-state.yaml`)
108
+ - Next story file (from epic state)
109
+ - `CLAUDE.md`, `AGENTS.md`, `docs/prd.md`, `docs/architecture.md`
110
+ - ❌ **NOT** completed story files (saves context!)
111
+ - ❌ **NOT** epic file (info in state file)
112
+
82
113
  ## Installation
83
114
 
84
115
  Plugins in `.opencode/plugins/` are automatically loaded by OpenCode.
@@ -44,6 +44,7 @@ interface SessionContext {
44
44
  story: StoryContext | null
45
45
  relevantFiles: string[]
46
46
  activeAgent: string | null
47
+ activeCommand: string | null // /dev-story, /dev-epic, /dev-sprint
47
48
  }
48
49
 
49
50
  // Base files ALL agents need after compaction (to remember who they are)
@@ -116,6 +117,7 @@ const MUST_READ_FILES: Record<string, string[]> = {
116
117
  "CLAUDE.md",
117
118
  "docs/prd.md",
118
119
  "docs/architecture.md",
120
+ // epic state path added dynamically (if in epic workflow)
119
121
  // story path added dynamically
120
122
  ],
121
123
  coder: [
@@ -173,13 +175,28 @@ export const CustomCompactionPlugin: Plugin = async (ctx) => {
173
175
  /**
174
176
  * Generate Read commands that agent MUST execute after compaction
175
177
  */
176
- function generateReadCommands(agent: string | null, story: StoryContext | null): string {
178
+ async function generateReadCommands(agent: string | null, story: StoryContext | null, activeCommand: string | null): Promise<string> {
177
179
  const agentKey = (typeof agent === 'string' ? agent.toLowerCase() : null) || "default"
178
180
  const filesToRead = [...(MUST_READ_FILES[agentKey] || MUST_READ_FILES.default)]
179
181
 
180
- // For dev/coder: add story file if active
181
- if ((agentKey === "dev" || agentKey === "coder") && story) {
182
- filesToRead.unshift(story.path) // Story first!
182
+ // For dev/coder: add command file first
183
+ if ((agentKey === "dev" || agentKey === "coder") && activeCommand) {
184
+ const commandFile = activeCommand.replace("/", "") + ".md"
185
+ filesToRead.unshift(`.opencode/commands/${commandFile}`)
186
+ }
187
+
188
+ // For dev/coder: add epic state file if in epic workflow
189
+ if ((agentKey === "dev" || agentKey === "coder")) {
190
+ const epicState = await getActiveEpicState()
191
+ if (epicState) {
192
+ // Epic state file (has all context)
193
+ filesToRead.unshift(epicState.statePath.replace(directory + "/", ""))
194
+ }
195
+
196
+ // Then story file if active
197
+ if (story) {
198
+ filesToRead.unshift(story.path) // Story first!
199
+ }
183
200
  }
184
201
 
185
202
  const commands = filesToRead.map((f, i) => `${i + 1}. Read("${f}")`).join("\n")
@@ -203,8 +220,158 @@ DO NOT skip this step. DO NOT ask user what to do. Just read these files first.`
203
220
  }
204
221
  }
205
222
 
223
+ interface EpicState {
224
+ statePath: string
225
+ epicId: string
226
+ epicTitle: string
227
+ status: string
228
+ currentStoryIndex: number
229
+ totalStories: number
230
+ nextAction: string | null
231
+ nextStoryPath: string | null
232
+ completedCount: number
233
+ pendingCount: number
234
+ }
235
+
236
+ async function getActiveEpicState(): Promise<EpicState | null> {
237
+ try {
238
+ // Search for epic state files in all sprint folders
239
+ const sprintArtifactsPath = join(directory, "docs", "sprint-artifacts")
240
+ const entries = await readdir(sprintArtifactsPath)
241
+
242
+ for (const entry of entries) {
243
+ if (entry.startsWith("sprint-")) {
244
+ const statePath = join(sprintArtifactsPath, entry, ".sprint-state")
245
+ try {
246
+ const stateFiles = await readdir(statePath)
247
+ for (const stateFile of stateFiles) {
248
+ if (stateFile.endsWith("-state.yaml")) {
249
+ const fullPath = join(statePath, stateFile)
250
+ const content = await readFile(fullPath, "utf-8")
251
+
252
+ // Check if this epic is in-progress
253
+ if (content.includes("status: \"in-progress\"") || content.includes("status: in-progress")) {
254
+ // Parse epic state
255
+ const epicIdMatch = content.match(/epic_id:\s*["']?([^"'\n]+)["']?/i)
256
+ const epicTitleMatch = content.match(/epic_title:\s*["']?([^"'\n]+)["']?/i)
257
+ const statusMatch = content.match(/status:\s*["']?([^"'\n]+)["']?/i)
258
+ const currentIndexMatch = content.match(/current_story_index:\s*(\d+)/i)
259
+ const totalStoriesMatch = content.match(/total_stories:\s*(\d+)/i)
260
+ const nextActionMatch = content.match(/next_action:\s*["']?([^"'\n]+)["']?/i)
261
+
262
+ // Count completed/pending stories
263
+ const completedSection = content.match(/completed_stories:([\s\S]*?)(?=pending_stories:|$)/i)
264
+ const pendingSection = content.match(/pending_stories:([\s\S]*?)(?=\n\w+:|$)/i)
265
+
266
+ const completedCount = completedSection
267
+ ? (completedSection[1].match(/- path:/g) || []).length
268
+ : 0
269
+ const pendingCount = pendingSection
270
+ ? (pendingSection[1].match(/- path:/g) || []).length
271
+ : 0
272
+
273
+ // Extract next story path from next_action
274
+ let nextStoryPath: string | null = null
275
+ if (nextActionMatch) {
276
+ const actionText = nextActionMatch[1]
277
+ const storyFileMatch = actionText.match(/story-[\w-]+\.md/i)
278
+ if (storyFileMatch) {
279
+ // Find full path in pending_stories
280
+ const pathMatch = content.match(new RegExp(`path:\\s*["']?([^"'\\n]*${storyFileMatch[0]}[^"'\\n]*)["']?`, 'i'))
281
+ if (pathMatch) {
282
+ nextStoryPath = pathMatch[1]
283
+ }
284
+ }
285
+ }
286
+
287
+ return {
288
+ statePath: fullPath.replace(directory + "/", ""),
289
+ epicId: epicIdMatch?.[1] || "unknown",
290
+ epicTitle: epicTitleMatch?.[1] || "Unknown Epic",
291
+ status: statusMatch?.[1] || "in-progress",
292
+ currentStoryIndex: currentIndexMatch ? parseInt(currentIndexMatch[1]) : 0,
293
+ totalStories: totalStoriesMatch ? parseInt(totalStoriesMatch[1]) : 0,
294
+ nextAction: nextActionMatch?.[1] || null,
295
+ nextStoryPath,
296
+ completedCount,
297
+ pendingCount
298
+ }
299
+ }
300
+ }
301
+ }
302
+ } catch {
303
+ // No .sprint-state folder in this sprint
304
+ }
305
+ }
306
+ }
307
+ return null
308
+ } catch {
309
+ return null
310
+ }
311
+ }
312
+
206
313
  async function getActiveStory(): Promise<StoryContext | null> {
207
314
  try {
315
+ // First, try to find epic state file
316
+ const epicState = await getActiveEpicState()
317
+ if (epicState) {
318
+ // Parse epic state to get current story
319
+ const storyPathMatch = epicState.content.match(/next_action:\s*["']?Execute\s+(.+?)["']?$/m)
320
+ if (storyPathMatch) {
321
+ const storyFileName = storyPathMatch[1]
322
+ // Find story file
323
+ const sprintMatch = epicState.statePath.match(/sprint-(\d+)/)
324
+ if (sprintMatch) {
325
+ const storyPath = `docs/sprint-artifacts/sprint-${sprintMatch[1]}/stories/${storyFileName}`
326
+ const storyContent = await readFile(join(directory, storyPath), "utf-8")
327
+
328
+ const titleMatch = storyContent.match(/^#\s+(.+)/m)
329
+ const statusMatch = storyContent.match(/\*\*Status:\*\*\s*(\w+)/i)
330
+
331
+ const completedTasks: string[] = []
332
+ const pendingTasks: string[] = []
333
+ let currentTask: string | null = null
334
+
335
+ // Parse tasks with more detail
336
+ const taskRegex = /- \[([ x])\]\s+\*\*T(\d+)\*\*[:\s]+(.+?)(?=\n|$)/g
337
+ let match
338
+ while ((match = taskRegex.exec(storyContent)) !== null) {
339
+ const [, checked, taskId, taskName] = match
340
+ const taskInfo = `T${taskId}: ${taskName.trim()}`
341
+ if (checked === "x") {
342
+ completedTasks.push(taskInfo)
343
+ } else {
344
+ if (!currentTask) currentTask = taskInfo
345
+ pendingTasks.push(taskInfo)
346
+ }
347
+ }
348
+
349
+ // Parse acceptance criteria
350
+ const acceptanceCriteria: string[] = []
351
+ const acSection = storyContent.match(/## Acceptance Criteria[\s\S]*?(?=##|$)/i)
352
+ if (acSection) {
353
+ const acRegex = /- \[([ x])\]\s+(.+?)(?=\n|$)/g
354
+ while ((match = acRegex.exec(acSection[0])) !== null) {
355
+ const [, checked, criteria] = match
356
+ acceptanceCriteria.push(`${checked === "x" ? "✅" : "⬜"} ${criteria.trim()}`)
357
+ }
358
+ }
359
+
360
+ return {
361
+ path: storyPath,
362
+ title: titleMatch?.[1] || "Unknown Story",
363
+ status: statusMatch?.[1] || "unknown",
364
+ currentTask,
365
+ completedTasks,
366
+ pendingTasks,
367
+ acceptanceCriteria,
368
+ fullContent: storyContent
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+ // Fallback: try old sprint-status.yaml format
208
375
  const sprintStatusPath = join(directory, "docs", "sprint-artifacts", "sprint-status.yaml")
209
376
  const content = await readFile(sprintStatusPath, "utf-8")
210
377
 
@@ -300,21 +467,72 @@ DO NOT skip this step. DO NOT ask user what to do. Just read these files first.`
300
467
  return relevantPaths
301
468
  }
302
469
 
470
+ async function detectActiveCommand(todos: TaskStatus[], epicState: EpicState | null): Promise<string | null> {
471
+ // Detect command from TODO structure
472
+ if (todos.length === 0) return null
473
+
474
+ // Check if TODOs are epics (sprint mode)
475
+ const hasEpicTodos = todos.some(t => t.content.toLowerCase().includes("epic"))
476
+ if (hasEpicTodos) return "/dev-sprint"
477
+
478
+ // Check if TODOs are stories (epic mode)
479
+ const hasStoryTodos = todos.some(t => t.content.toLowerCase().includes("story"))
480
+ if (hasStoryTodos || epicState) return "/dev-epic"
481
+
482
+ // Regular story mode
483
+ return "/dev-story"
484
+ }
485
+
303
486
  async function buildContext(agent: string | null): Promise<SessionContext> {
304
487
  const [todos, story] = await Promise.all([
305
488
  getTodoList(),
306
489
  getActiveStory()
307
490
  ])
308
491
 
492
+ const epicState = await getActiveEpicState()
309
493
  const relevantFiles = await getRelevantFiles(agent, story)
494
+ const activeCommand = await detectActiveCommand(todos, epicState)
310
495
 
311
- return { todos, story, relevantFiles, activeAgent: agent }
496
+ return { todos, story, relevantFiles, activeAgent: agent, activeCommand }
312
497
  }
313
498
 
314
- function formatDevContext(ctx: SessionContext): string {
499
+ async function formatDevContext(ctx: SessionContext): Promise<string> {
315
500
  const sections: string[] = []
316
501
 
317
- if (ctx.story) {
502
+ // Check if we're in epic workflow
503
+ const epicState = await getActiveEpicState()
504
+
505
+ if (epicState) {
506
+ // Epic/Sprint workflow mode - show epic progress
507
+ const progress = epicState.totalStories > 0
508
+ ? ((epicState.completedCount / epicState.totalStories) * 100).toFixed(0)
509
+ : 0
510
+
511
+ sections.push(`## 🎯 Epic Workflow: ${epicState.epicTitle}
512
+
513
+ **Epic ID:** ${epicState.epicId}
514
+ **Epic State:** \`${epicState.statePath}\` ← READ THIS FIRST
515
+ **Progress:** ${progress}% (${epicState.completedCount}/${epicState.totalStories} stories)
516
+
517
+ ### Next Action (DO THIS NOW)
518
+ \`\`\`
519
+ ${epicState.nextAction || "All stories complete - run epic integration tests"}
520
+ \`\`\`
521
+
522
+ ${epicState.nextStoryPath ? `**Next Story:** \`${epicState.nextStoryPath}\` ← READ THIS SECOND` : ""}
523
+
524
+ ### Epic Progress
525
+ **Completed Stories:** ${epicState.completedCount}
526
+ **Pending Stories:** ${epicState.pendingCount}
527
+ **Current Index:** ${epicState.currentStoryIndex}
528
+
529
+ ---
530
+
531
+ 💡 **Note:** If this is part of /dev-sprint, after epic completes:
532
+ 1. Update sprint-status.yaml (mark epic done)
533
+ 2. Continue to next epic automatically`)
534
+ } else if (ctx.story) {
535
+ // Regular story mode
318
536
  const s = ctx.story
319
537
  const total = s.completedTasks.length + s.pendingTasks.length
320
538
  const progress = total > 0 ? (s.completedTasks.length / total * 100).toFixed(0) : 0
@@ -433,13 +651,13 @@ ${ctx.relevantFiles.map(f => `- \`${f}\``).join("\n")}`)
433
651
  return sections.join("\n\n---\n\n")
434
652
  }
435
653
 
436
- function formatContext(ctx: SessionContext): string {
654
+ async function formatContext(ctx: SessionContext): Promise<string> {
437
655
  const agent = ctx.activeAgent?.toLowerCase()
438
656
 
439
657
  switch (agent) {
440
658
  case "dev":
441
659
  case "coder":
442
- return formatDevContext(ctx)
660
+ return await formatDevContext(ctx)
443
661
  case "architect":
444
662
  return formatArchitectContext(ctx)
445
663
  case "pm":
@@ -453,12 +671,15 @@ ${ctx.relevantFiles.map(f => `- \`${f}\``).join("\n")}`)
453
671
  }
454
672
  }
455
673
 
456
- function formatInstructions(ctx: SessionContext): string {
674
+ async function formatInstructions(ctx: SessionContext): Promise<string> {
457
675
  const agent = ctx.activeAgent?.toLowerCase()
458
676
  const hasInProgressTasks = ctx.todos.some(t => t.status === "in_progress")
459
677
  const hasInProgressStory = ctx.story?.status === "in-progress"
678
+
679
+ // Check if we're in epic workflow
680
+ const epicState = await getActiveEpicState()
460
681
 
461
- if (!hasInProgressTasks && !hasInProgressStory) {
682
+ if (!hasInProgressTasks && !hasInProgressStory && !epicState) {
462
683
  return `## Status: COMPLETED ✅
463
684
 
464
685
  Previous task was completed successfully.
@@ -469,7 +690,67 @@ Previous task was completed successfully.
469
690
  3. Ask user for next task`
470
691
  }
471
692
 
472
- // Dev-specific instructions
693
+ // Sprint workflow instructions
694
+ if (ctx.activeCommand === "/dev-sprint" && (agent === "dev" || agent === "coder")) {
695
+ const nextEpicTodo = ctx.todos.find(t => t.status === "in_progress" && t.content.toLowerCase().includes("epic"))
696
+ return `## Status: SPRINT IN PROGRESS 🔄
697
+
698
+ **Active Command:** ${ctx.activeCommand}
699
+ **Active Agent:** @${agent}
700
+ **Next Epic:** ${nextEpicTodo?.content || "check TODO"}
701
+
702
+ ### Resume Protocol (AUTOMATIC - DO NOT ASK USER)
703
+ 1. **Read command:** \`.opencode/commands/dev-sprint.md\`
704
+ 2. **Read sprint-status.yaml**
705
+ 3. **Find next epic** from TODO or sprint-status.yaml
706
+ 4. **Execute epic** via /dev-epic workflow
707
+ 5. **After epic done:**
708
+ - Update sprint-status.yaml (mark epic done)
709
+ - Update TODO (mark epic completed, next epic in_progress)
710
+ - Continue next epic automatically
711
+
712
+ ### DO NOT
713
+ - Ask user what to do (TODO + sprint-status.yaml tell you)
714
+ - Re-read completed epics
715
+ - Wait for confirmation between epics (auto-continue)
716
+
717
+ ### IMPORTANT
718
+ This is /dev-sprint autopilot mode. Execute epics sequentially until sprint done.`
719
+ }
720
+
721
+ // Epic workflow instructions
722
+ if ((ctx.activeCommand === "/dev-epic" || epicState) && (agent === "dev" || agent === "coder")) {
723
+ return `## Status: EPIC IN PROGRESS 🔄
724
+
725
+ **Active Command:** ${ctx.activeCommand || "/dev-epic"}
726
+ **Active Agent:** @${agent}
727
+ **Epic:** ${epicState?.epicTitle || "check epic state"}
728
+ **Next Action:** ${epicState?.nextAction || "check TODO"}
729
+
730
+ ### Resume Protocol (AUTOMATIC - DO NOT ASK USER)
731
+ 1. **Read command:** \`.opencode/commands/dev-epic.md\`
732
+ 2. **Read epic state:** \`${epicState?.statePath || "find in .sprint-state/"}\`
733
+ 3. **Read next story:** \`${epicState?.nextStoryPath || "check epic state"}\`
734
+ 4. **Load skill:** \`.opencode/skills/dev-story/SKILL.md\`
735
+ 5. **Execute story** following /dev-story workflow
736
+ 6. **After story done:**
737
+ - Update epic state file (move story to completed)
738
+ - Update TODO (mark story completed, next story in_progress)
739
+ - Increment current_story_index
740
+ - Set next_action to next story
741
+ - Continue next story automatically
742
+
743
+ ### DO NOT
744
+ - Ask user what to do (epic state + TODO tell you)
745
+ - Re-read completed stories
746
+ - Re-read epic file (info in state)
747
+ - Wait for confirmation between stories (auto-continue)
748
+
749
+ ### IMPORTANT
750
+ This is /dev-epic autopilot mode. Execute stories sequentially until epic done.`
751
+ }
752
+
753
+ // Dev-specific instructions (regular story)
473
754
  if ((agent === "dev" || agent === "coder") && ctx.story) {
474
755
  return `## Status: IN PROGRESS 🔄
475
756
 
@@ -554,9 +835,9 @@ Previous task was completed successfully.
554
835
  await log(directory, ` todos: ${ctx.todos.length}`)
555
836
  await log(directory, ` relevantFiles: ${ctx.relevantFiles.length}`)
556
837
 
557
- const context = formatContext(ctx)
558
- const instructions = formatInstructions(ctx)
559
- const readCommands = generateReadCommands(agent, ctx.story)
838
+ const context = await formatContext(ctx)
839
+ const instructions = await formatInstructions(ctx)
840
+ const readCommands = await generateReadCommands(agent, ctx.story, ctx.activeCommand)
560
841
 
561
842
  // Agent identity reminder
562
843
  const agentIdentity = agent