claude-code-workflow 6.3.48 → 6.3.49

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.
Files changed (211) hide show
  1. package/.claude/CLAUDE.md +6 -8
  2. package/.claude/agents/action-planning-agent.md +28 -45
  3. package/.claude/agents/cli-lite-planning-agent.md +93 -1
  4. package/.claude/agents/code-developer.md +144 -27
  5. package/.claude/commands/ccw-coordinator.md +175 -21
  6. package/.claude/commands/ccw-debug.md +832 -0
  7. package/.claude/commands/ccw.md +90 -9
  8. package/.claude/commands/cli/cli-init.md +1 -0
  9. package/.claude/commands/issue/convert-to-plan.md +718 -0
  10. package/.claude/commands/issue/from-brainstorm.md +382 -0
  11. package/.claude/commands/memory/tips.md +332 -0
  12. package/.claude/commands/workflow/analyze-with-file.md +804 -0
  13. package/.claude/commands/workflow/brainstorm/auto-parallel.md +18 -43
  14. package/.claude/commands/workflow/brainstorm/role-analysis.md +705 -0
  15. package/.claude/commands/workflow/brainstorm-with-file.md +1153 -0
  16. package/.claude/commands/workflow/debug-with-file.md +7 -5
  17. package/.claude/commands/workflow/execute.md +6 -4
  18. package/.claude/commands/workflow/lite-plan.md +2 -2
  19. package/.claude/commands/workflow/plan-verify.md +162 -327
  20. package/.claude/commands/workflow/plan.md +162 -26
  21. package/.claude/commands/workflow/replan.md +78 -2
  22. package/.claude/commands/workflow/{review-fix.md → review-cycle-fix.md} +6 -6
  23. package/.claude/commands/workflow/review-module-cycle.md +2 -2
  24. package/.claude/commands/workflow/review-session-cycle.md +2 -2
  25. package/.claude/commands/workflow/tools/conflict-resolution.md +16 -26
  26. package/.claude/commands/workflow/tools/context-gather.md +81 -118
  27. package/.claude/commands/workflow/tools/task-generate-agent.md +94 -10
  28. package/.claude/skills/ccw-help/command.json +4 -4
  29. package/.claude/skills/lite-skill-generator/SKILL.md +650 -0
  30. package/.claude/skills/lite-skill-generator/templates/simple-skill.md +68 -0
  31. package/.claude/skills/lite-skill-generator/templates/style-guide.md +64 -0
  32. package/.claude/skills/skill-generator/SKILL.md +277 -85
  33. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +4 -15
  34. package/.claude/skills/skill-generator/phases/02-structure-generation.md +72 -17
  35. package/.claude/skills/skill-generator/phases/03-phase-generation.md +218 -51
  36. package/.claude/skills/skill-generator/phases/04-specs-templates.md +111 -41
  37. package/.claude/skills/skill-generator/phases/05-validation.md +139 -56
  38. package/.claude/skills/skill-generator/templates/autonomous-action.md +78 -268
  39. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +14 -0
  40. package/.claude/skills/skill-generator/templates/code-analysis-action.md +12 -0
  41. package/.claude/skills/skill-generator/templates/llm-action.md +12 -0
  42. package/.claude/skills/skill-generator/templates/script-template.md +368 -0
  43. package/.claude/skills/skill-generator/templates/sequential-phase.md +14 -0
  44. package/.claude/skills/skill-generator/templates/skill-md.md +14 -0
  45. package/.claude/skills/skill-tuning/SKILL.md +130 -266
  46. package/.claude/skills/skill-tuning/phases/orchestrator.md +95 -283
  47. package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +90 -198
  48. package/.claude/skills/skill-tuning/specs/tuning-strategies.md +193 -1345
  49. package/.claude/workflows/cli-templates/schemas/plan-verify-agent-schema.json +47 -0
  50. package/.claude/workflows/cli-templates/schemas/verify-json-schema.json +158 -0
  51. package/.claude/workflows/cli-tools-usage.md +1 -1
  52. package/.codex/AGENTS.md +1 -3
  53. package/.codex/prompts/analyze-with-file.md +607 -0
  54. package/.codex/prompts/brainstorm-to-cycle.md +455 -0
  55. package/.codex/prompts/brainstorm-with-file.md +933 -0
  56. package/.codex/prompts/debug-with-file.md +15 -20
  57. package/.codex/skills/ccw-cli-tools/SKILL.md +559 -0
  58. package/ccw/dist/commands/cli.d.ts.map +1 -1
  59. package/ccw/dist/commands/cli.js +29 -5
  60. package/ccw/dist/commands/cli.js.map +1 -1
  61. package/ccw/dist/commands/issue.d.ts +2 -0
  62. package/ccw/dist/commands/issue.d.ts.map +1 -1
  63. package/ccw/dist/commands/issue.js +62 -20
  64. package/ccw/dist/commands/issue.js.map +1 -1
  65. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  66. package/ccw/dist/config/litellm-api-config-manager.js +5 -3
  67. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  68. package/ccw/dist/config/litellm-provider-models.d.ts +73 -0
  69. package/ccw/dist/config/litellm-provider-models.d.ts.map +1 -0
  70. package/ccw/dist/config/litellm-provider-models.js +172 -0
  71. package/ccw/dist/config/litellm-provider-models.js.map +1 -0
  72. package/ccw/dist/config/provider-models.d.ts +25 -51
  73. package/ccw/dist/config/provider-models.d.ts.map +1 -1
  74. package/ccw/dist/config/provider-models.js +84 -149
  75. package/ccw/dist/config/provider-models.js.map +1 -1
  76. package/ccw/dist/config/storage-paths.d.ts.map +1 -1
  77. package/ccw/dist/config/storage-paths.js +23 -5
  78. package/ccw/dist/config/storage-paths.js.map +1 -1
  79. package/ccw/dist/core/auth/csrf-middleware.js +3 -3
  80. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
  81. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  82. package/ccw/dist/core/dashboard-generator.js +3 -1
  83. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  84. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  85. package/ccw/dist/core/routes/claude-routes.js +206 -14
  86. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  87. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  88. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  89. package/ccw/dist/core/routes/commands-routes.d.ts +7 -0
  90. package/ccw/dist/core/routes/commands-routes.d.ts.map +1 -0
  91. package/ccw/dist/core/routes/commands-routes.js +480 -0
  92. package/ccw/dist/core/routes/commands-routes.js.map +1 -0
  93. package/ccw/dist/core/routes/model-routes.d.ts +11 -0
  94. package/ccw/dist/core/routes/model-routes.d.ts.map +1 -0
  95. package/ccw/dist/core/routes/model-routes.js +112 -0
  96. package/ccw/dist/core/routes/model-routes.js.map +1 -0
  97. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -1
  98. package/ccw/dist/core/routes/nav-status-routes.js +84 -1
  99. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -1
  100. package/ccw/dist/core/routes/provider-routes.d.ts +11 -0
  101. package/ccw/dist/core/routes/provider-routes.d.ts.map +1 -0
  102. package/ccw/dist/core/routes/provider-routes.js +67 -0
  103. package/ccw/dist/core/routes/provider-routes.js.map +1 -0
  104. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  105. package/ccw/dist/core/routes/skills-routes.js +219 -7
  106. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  107. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  108. package/ccw/dist/core/routes/system-routes.js +58 -6
  109. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  110. package/ccw/dist/core/server.d.ts.map +1 -1
  111. package/ccw/dist/core/server.js +13 -0
  112. package/ccw/dist/core/server.js.map +1 -1
  113. package/ccw/dist/mcp-server/index.js +2 -2
  114. package/ccw/dist/mcp-server/index.js.map +1 -1
  115. package/ccw/dist/tools/claude-cli-tools.d.ts +48 -11
  116. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  117. package/ccw/dist/tools/claude-cli-tools.js +146 -50
  118. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  119. package/ccw/dist/tools/cli-config-manager.d.ts +1 -13
  120. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  121. package/ccw/dist/tools/cli-config-manager.js +3 -27
  122. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  123. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
  124. package/ccw/dist/tools/cli-executor-core.js +7 -2
  125. package/ccw/dist/tools/cli-executor-core.js.map +1 -1
  126. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -1
  127. package/ccw/dist/tools/cli-history-store.d.ts +11 -0
  128. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  129. package/ccw/dist/tools/cli-history-store.js +82 -2
  130. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  131. package/ccw/dist/tools/command-registry.d.ts +7 -0
  132. package/ccw/dist/tools/command-registry.d.ts.map +1 -1
  133. package/ccw/dist/tools/command-registry.js +14 -1
  134. package/ccw/dist/tools/command-registry.js.map +1 -1
  135. package/ccw/dist/tools/generate-module-docs.d.ts.map +1 -1
  136. package/ccw/dist/tools/generate-module-docs.js +11 -7
  137. package/ccw/dist/tools/generate-module-docs.js.map +1 -1
  138. package/ccw/dist/tools/litellm-executor.d.ts +1 -0
  139. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  140. package/ccw/dist/tools/litellm-executor.js +11 -9
  141. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  142. package/ccw/dist/types/skill-types.d.ts +97 -0
  143. package/ccw/dist/types/skill-types.d.ts.map +1 -0
  144. package/ccw/dist/types/skill-types.js +6 -0
  145. package/ccw/dist/types/skill-types.js.map +1 -0
  146. package/ccw/src/commands/cli.ts +36 -5
  147. package/ccw/src/commands/issue.ts +81 -26
  148. package/ccw/src/config/litellm-api-config-manager.ts +5 -3
  149. package/ccw/src/config/litellm-provider-models.ts +222 -0
  150. package/ccw/src/config/provider-models.ts +91 -190
  151. package/ccw/src/config/storage-paths.ts +20 -5
  152. package/ccw/src/core/auth/csrf-middleware.ts +3 -3
  153. package/ccw/src/core/dashboard-generator.ts +3 -1
  154. package/ccw/src/core/routes/claude-routes.ts +233 -15
  155. package/ccw/src/core/routes/cli-routes.ts +2 -3
  156. package/ccw/src/core/routes/commands-routes.ts +620 -0
  157. package/ccw/src/core/routes/nav-status-routes.ts +95 -1
  158. package/ccw/src/core/routes/provider-routes.ts +78 -0
  159. package/ccw/src/core/routes/skills-routes.ts +266 -45
  160. package/ccw/src/core/routes/system-routes.ts +102 -50
  161. package/ccw/src/core/server.ts +13 -0
  162. package/ccw/src/mcp-server/index.ts +2 -2
  163. package/ccw/src/templates/dashboard-css/18-cli-settings.css +35 -0
  164. package/ccw/src/templates/dashboard-css/37-commands.css +193 -0
  165. package/ccw/src/templates/dashboard-js/components/navigation.js +4 -0
  166. package/ccw/src/templates/dashboard-js/i18n.js +116 -0
  167. package/ccw/src/templates/dashboard-js/views/cli-manager.js +249 -4
  168. package/ccw/src/templates/dashboard-js/views/commands-manager.js +503 -0
  169. package/ccw/src/templates/dashboard-js/views/issue-manager.js +7 -7
  170. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2 -7
  171. package/ccw/src/templates/dashboard-js/views/skills-manager.js +164 -23
  172. package/ccw/src/templates/dashboard.html +7 -0
  173. package/ccw/src/tools/claude-cli-tools.ts +170 -56
  174. package/ccw/src/tools/cli-config-manager.ts +2 -33
  175. package/ccw/src/tools/cli-executor-core.ts +8 -2
  176. package/ccw/src/tools/cli-history-store.ts +92 -2
  177. package/ccw/src/tools/command-registry.ts +16 -1
  178. package/ccw/src/tools/generate-module-docs.ts +11 -7
  179. package/ccw/src/tools/litellm-executor.ts +13 -9
  180. package/ccw/src/types/skill-types.ts +99 -0
  181. package/package.json +1 -1
  182. package/.claude/commands/enhance-prompt.md +0 -93
  183. package/.claude/commands/memory/code-map-memory.md +0 -687
  184. package/.claude/commands/memory/docs.md +0 -615
  185. package/.claude/commands/memory/load-skill-memory.md +0 -182
  186. package/.claude/commands/memory/skill-memory.md +0 -525
  187. package/.claude/commands/memory/swagger-docs.md +0 -773
  188. package/.claude/commands/memory/tech-research-rules.md +0 -310
  189. package/.claude/commands/memory/workflow-skill-memory.md +0 -517
  190. package/.claude/commands/task/breakdown.md +0 -208
  191. package/.claude/commands/task/create.md +0 -152
  192. package/.claude/commands/task/execute.md +0 -270
  193. package/.claude/commands/task/replan.md +0 -441
  194. package/.claude/commands/version.md +0 -254
  195. package/.claude/commands/workflow/action-plan-verify.md +0 -485
  196. package/.claude/commands/workflow/brainstorm/api-designer.md +0 -587
  197. package/.claude/commands/workflow/brainstorm/data-architect.md +0 -220
  198. package/.claude/commands/workflow/brainstorm/product-manager.md +0 -200
  199. package/.claude/commands/workflow/brainstorm/product-owner.md +0 -200
  200. package/.claude/commands/workflow/brainstorm/scrum-master.md +0 -200
  201. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  202. package/.claude/commands/workflow/brainstorm/system-architect.md +0 -389
  203. package/.claude/commands/workflow/brainstorm/ui-designer.md +0 -221
  204. package/.claude/commands/workflow/brainstorm/ux-expert.md +0 -221
  205. package/.claude/commands/workflow/debug.md +0 -331
  206. package/.claude/commands/workflow/develop-with-file.md +0 -1044
  207. package/.claude/skills/ccw-loop/README.md +0 -303
  208. package/.claude/skills/skill-generator/templates/script-bash.md +0 -277
  209. package/.claude/skills/skill-generator/templates/script-python.md +0 -198
  210. package/.codex/prompts/debug.md +0 -318
  211. package/ccw/src/core/routes/mcp-routes.ts.backup +0 -549
@@ -0,0 +1,718 @@
1
+ ---
2
+ name: convert-to-plan
3
+ description: Convert planning artifacts (lite-plan, workflow session, markdown) to issue solutions
4
+ argument-hint: "[-y|--yes] [--issue <id>] [--supplement] <SOURCE>"
5
+ allowed-tools: TodoWrite(*), Bash(*), Read(*), Write(*), Glob(*), AskUserQuestion(*)
6
+ ---
7
+
8
+ ## Auto Mode
9
+
10
+ When `--yes` or `-y`: Skip confirmation, auto-create issue and bind solution.
11
+
12
+ # Issue Convert-to-Plan Command (/issue:convert-to-plan)
13
+
14
+ ## Overview
15
+
16
+ Converts various planning artifact formats into issue workflow solutions with intelligent detection and automatic binding.
17
+
18
+ **Supported Sources** (auto-detected):
19
+ - **lite-plan**: `.workflow/.lite-plan/{slug}/plan.json`
20
+ - **workflow-session**: `WFS-xxx` ID or `.workflow/active/{session}/` folder
21
+ - **markdown**: Any `.md` file with implementation/task content
22
+ - **json**: Direct JSON files matching plan-json-schema
23
+
24
+ ## Quick Reference
25
+
26
+ ```bash
27
+ # Convert lite-plan to new issue (auto-creates issue)
28
+ /issue:convert-to-plan ".workflow/.lite-plan/implement-auth-2026-01-25"
29
+
30
+ # Convert workflow session to existing issue
31
+ /issue:convert-to-plan WFS-auth-impl --issue GH-123
32
+
33
+ # Supplement existing solution with additional tasks
34
+ /issue:convert-to-plan "./docs/additional-tasks.md" --issue ISS-001 --supplement
35
+
36
+ # Auto mode - skip confirmations
37
+ /issue:convert-to-plan ".workflow/.lite-plan/my-plan" -y
38
+ ```
39
+
40
+ ## Command Options
41
+
42
+ | Option | Description | Default |
43
+ |--------|-------------|---------|
44
+ | `<SOURCE>` | Planning artifact path or WFS-xxx ID | Required |
45
+ | `--issue <id>` | Bind to existing issue instead of creating new | Auto-create |
46
+ | `--supplement` | Add tasks to existing solution (requires --issue) | false |
47
+ | `-y, --yes` | Skip all confirmations | false |
48
+
49
+ ## Core Data Access Principle
50
+
51
+ **⚠️ Important**: Use CLI commands for all issue/solution operations.
52
+
53
+ | Operation | Correct | Incorrect |
54
+ |-----------|---------|-----------|
55
+ | Get issue | `ccw issue status <id> --json` | Read issues.jsonl directly |
56
+ | Create issue | `ccw issue init <id> --title "..."` | Write to issues.jsonl |
57
+ | Bind solution | `ccw issue bind <id> <sol-id>` | Edit issues.jsonl |
58
+ | List solutions | `ccw issue solutions --issue <id> --brief` | Read solutions/*.jsonl |
59
+
60
+ ## Solution Schema Reference
61
+
62
+ Target format for all extracted data (from solution-schema.json):
63
+
64
+ ```typescript
65
+ interface Solution {
66
+ id: string; // SOL-{issue-id}-{4-char-uid}
67
+ description?: string; // High-level summary
68
+ approach?: string; // Technical strategy
69
+ tasks: Task[]; // Required: at least 1 task
70
+ exploration_context?: object; // Optional: source context
71
+ analysis?: { risk, impact, complexity };
72
+ score?: number; // 0.0-1.0
73
+ is_bound: boolean;
74
+ created_at: string;
75
+ bound_at?: string;
76
+ }
77
+
78
+ interface Task {
79
+ id: string; // T1, T2, T3... (pattern: ^T[0-9]+$)
80
+ title: string; // Required: action verb + target
81
+ scope: string; // Required: module path or feature area
82
+ action: Action; // Required: Create|Update|Implement|...
83
+ description?: string;
84
+ modification_points?: Array<{file, target, change}>;
85
+ implementation: string[]; // Required: step-by-step guide
86
+ test?: { unit?, integration?, commands?, coverage_target? };
87
+ acceptance: { criteria: string[], verification: string[] }; // Required
88
+ commit?: { type, scope, message_template, breaking? };
89
+ depends_on?: string[];
90
+ priority?: number; // 1-5 (default: 3)
91
+ }
92
+
93
+ type Action = 'Create' | 'Update' | 'Implement' | 'Refactor' | 'Add' | 'Delete' | 'Configure' | 'Test' | 'Fix';
94
+ ```
95
+
96
+ ## Implementation
97
+
98
+ ### Phase 1: Parse Arguments & Detect Source Type
99
+
100
+ ```javascript
101
+ const input = userInput.trim();
102
+ const flags = parseFlags(userInput); // --issue, --supplement, -y/--yes
103
+
104
+ // Extract source path (first non-flag argument)
105
+ const source = extractSourceArg(input);
106
+
107
+ // Detect source type
108
+ function detectSourceType(source) {
109
+ // Check for WFS-xxx pattern (workflow session ID)
110
+ if (source.match(/^WFS-[\w-]+$/)) {
111
+ return { type: 'workflow-session-id', path: `.workflow/active/${source}` };
112
+ }
113
+
114
+ // Check if directory
115
+ const isDir = Bash(`test -d "${source}" && echo "dir" || echo "file"`).trim() === 'dir';
116
+
117
+ if (isDir) {
118
+ // Check for lite-plan indicator
119
+ const hasPlanJson = Bash(`test -f "${source}/plan.json" && echo "yes" || echo "no"`).trim() === 'yes';
120
+ if (hasPlanJson) {
121
+ return { type: 'lite-plan', path: source };
122
+ }
123
+
124
+ // Check for workflow session indicator
125
+ const hasSession = Bash(`test -f "${source}/workflow-session.json" && echo "yes" || echo "no"`).trim() === 'yes';
126
+ if (hasSession) {
127
+ return { type: 'workflow-session', path: source };
128
+ }
129
+ }
130
+
131
+ // Check file extensions
132
+ if (source.endsWith('.json')) {
133
+ return { type: 'json-file', path: source };
134
+ }
135
+ if (source.endsWith('.md')) {
136
+ return { type: 'markdown-file', path: source };
137
+ }
138
+
139
+ // Check if path exists at all
140
+ const exists = Bash(`test -e "${source}" && echo "yes" || echo "no"`).trim() === 'yes';
141
+ if (!exists) {
142
+ throw new Error(`E001: Source not found: ${source}`);
143
+ }
144
+
145
+ return { type: 'unknown', path: source };
146
+ }
147
+
148
+ const sourceInfo = detectSourceType(source);
149
+ if (sourceInfo.type === 'unknown') {
150
+ throw new Error(`E002: Unable to detect source format for: ${source}`);
151
+ }
152
+
153
+ console.log(`Detected source type: ${sourceInfo.type}`);
154
+ ```
155
+
156
+ ### Phase 2: Extract Data Using Format-Specific Extractor
157
+
158
+ ```javascript
159
+ let extracted = { title: '', approach: '', tasks: [], metadata: {} };
160
+
161
+ switch (sourceInfo.type) {
162
+ case 'lite-plan':
163
+ extracted = extractFromLitePlan(sourceInfo.path);
164
+ break;
165
+ case 'workflow-session':
166
+ case 'workflow-session-id':
167
+ extracted = extractFromWorkflowSession(sourceInfo.path);
168
+ break;
169
+ case 'markdown-file':
170
+ extracted = await extractFromMarkdownAI(sourceInfo.path);
171
+ break;
172
+ case 'json-file':
173
+ extracted = extractFromJsonFile(sourceInfo.path);
174
+ break;
175
+ }
176
+
177
+ // Validate extraction
178
+ if (!extracted.tasks || extracted.tasks.length === 0) {
179
+ throw new Error('E006: No tasks extracted from source');
180
+ }
181
+
182
+ // Ensure task IDs are normalized to T1, T2, T3...
183
+ extracted.tasks = normalizeTaskIds(extracted.tasks);
184
+
185
+ console.log(`Extracted: ${extracted.tasks.length} tasks`);
186
+ ```
187
+
188
+ #### Extractor: Lite-Plan
189
+
190
+ ```javascript
191
+ function extractFromLitePlan(folderPath) {
192
+ const planJson = Read(`${folderPath}/plan.json`);
193
+ const plan = JSON.parse(planJson);
194
+
195
+ return {
196
+ title: plan.summary?.split('.')[0]?.trim() || 'Untitled Plan',
197
+ description: plan.summary,
198
+ approach: plan.approach,
199
+ tasks: plan.tasks.map(t => ({
200
+ id: t.id,
201
+ title: t.title,
202
+ scope: t.scope || '',
203
+ action: t.action || 'Implement',
204
+ description: t.description || t.title,
205
+ modification_points: t.modification_points || [],
206
+ implementation: Array.isArray(t.implementation) ? t.implementation : [t.implementation || ''],
207
+ test: t.verification ? {
208
+ unit: t.verification.unit_tests,
209
+ integration: t.verification.integration_tests,
210
+ commands: t.verification.manual_checks
211
+ } : {},
212
+ acceptance: {
213
+ criteria: Array.isArray(t.acceptance) ? t.acceptance : [t.acceptance || ''],
214
+ verification: t.verification?.manual_checks || []
215
+ },
216
+ depends_on: t.depends_on || [],
217
+ priority: 3
218
+ })),
219
+ metadata: {
220
+ source_type: 'lite-plan',
221
+ source_path: folderPath,
222
+ complexity: plan.complexity,
223
+ estimated_time: plan.estimated_time,
224
+ exploration_angles: plan._metadata?.exploration_angles || [],
225
+ original_timestamp: plan._metadata?.timestamp
226
+ }
227
+ };
228
+ }
229
+ ```
230
+
231
+ #### Extractor: Workflow Session
232
+
233
+ ```javascript
234
+ function extractFromWorkflowSession(sessionPath) {
235
+ // Load session metadata
236
+ const sessionJson = Read(`${sessionPath}/workflow-session.json`);
237
+ const session = JSON.parse(sessionJson);
238
+
239
+ // Load IMPL_PLAN.md for approach (if exists)
240
+ let approach = '';
241
+ const implPlanPath = `${sessionPath}/IMPL_PLAN.md`;
242
+ const hasImplPlan = Bash(`test -f "${implPlanPath}" && echo "yes" || echo "no"`).trim() === 'yes';
243
+ if (hasImplPlan) {
244
+ const implPlan = Read(implPlanPath);
245
+ // Extract overview/approach section
246
+ const overviewMatch = implPlan.match(/##\s*(?:Overview|Approach|Strategy)\s*\n([\s\S]*?)(?=\n##|$)/i);
247
+ approach = overviewMatch?.[1]?.trim() || implPlan.split('\n').slice(0, 10).join('\n');
248
+ }
249
+
250
+ // Load all task JSONs from .task folder
251
+ const taskFiles = Glob({ pattern: `${sessionPath}/.task/IMPL-*.json` });
252
+ const tasks = taskFiles.map(f => {
253
+ const taskJson = Read(f);
254
+ const task = JSON.parse(taskJson);
255
+ return {
256
+ id: task.id?.replace(/^IMPL-0*/, 'T') || 'T1', // IMPL-001 → T1
257
+ title: task.title,
258
+ scope: task.scope || inferScopeFromTask(task),
259
+ action: capitalizeAction(task.type) || 'Implement',
260
+ description: task.description,
261
+ modification_points: task.implementation?.modification_points || [],
262
+ implementation: task.implementation?.steps || [],
263
+ test: task.implementation?.test || {},
264
+ acceptance: {
265
+ criteria: task.acceptance_criteria || [],
266
+ verification: task.verification_steps || []
267
+ },
268
+ commit: task.commit,
269
+ depends_on: (task.depends_on || []).map(d => d.replace(/^IMPL-0*/, 'T')),
270
+ priority: task.priority || 3
271
+ };
272
+ });
273
+
274
+ return {
275
+ title: session.name || session.description?.split('.')[0] || 'Workflow Session',
276
+ description: session.description || session.name,
277
+ approach: approach || session.description,
278
+ tasks: tasks,
279
+ metadata: {
280
+ source_type: 'workflow-session',
281
+ source_path: sessionPath,
282
+ session_id: session.id,
283
+ created_at: session.created_at
284
+ }
285
+ };
286
+ }
287
+
288
+ function inferScopeFromTask(task) {
289
+ if (task.implementation?.modification_points?.length) {
290
+ const files = task.implementation.modification_points.map(m => m.file);
291
+ // Find common directory prefix
292
+ const dirs = files.map(f => f.split('/').slice(0, -1).join('/'));
293
+ return [...new Set(dirs)][0] || '';
294
+ }
295
+ return '';
296
+ }
297
+
298
+ function capitalizeAction(type) {
299
+ if (!type) return 'Implement';
300
+ const map = { feature: 'Implement', bugfix: 'Fix', refactor: 'Refactor', test: 'Test', docs: 'Update' };
301
+ return map[type.toLowerCase()] || type.charAt(0).toUpperCase() + type.slice(1);
302
+ }
303
+ ```
304
+
305
+ #### Extractor: Markdown (AI-Assisted via Gemini)
306
+
307
+ ```javascript
308
+ async function extractFromMarkdownAI(filePath) {
309
+ const fileContent = Read(filePath);
310
+
311
+ // Use Gemini CLI for intelligent extraction
312
+ const cliPrompt = `PURPOSE: Extract implementation plan from markdown document for issue solution conversion. Must output ONLY valid JSON.
313
+ TASK: • Analyze document structure • Identify title/summary • Extract approach/strategy section • Parse tasks from any format (lists, tables, sections, code blocks) • Normalize each task to solution schema
314
+ MODE: analysis
315
+ CONTEXT: Document content provided below
316
+ EXPECTED: Valid JSON object with format:
317
+ {
318
+ "title": "extracted title",
319
+ "approach": "extracted approach/strategy",
320
+ "tasks": [
321
+ {
322
+ "id": "T1",
323
+ "title": "task title",
324
+ "scope": "module or feature area",
325
+ "action": "Implement|Update|Create|Fix|Refactor|Add|Delete|Configure|Test",
326
+ "description": "what to do",
327
+ "implementation": ["step 1", "step 2"],
328
+ "acceptance": ["criteria 1", "criteria 2"]
329
+ }
330
+ ]
331
+ }
332
+ CONSTRAINTS: Output ONLY valid JSON - no markdown, no explanation | Action must be one of: Create, Update, Implement, Refactor, Add, Delete, Configure, Test, Fix | Tasks must have id, title, scope, action, implementation (array), acceptance (array)
333
+
334
+ DOCUMENT CONTENT:
335
+ ${fileContent}`;
336
+
337
+ // Execute Gemini CLI
338
+ const result = Bash(`ccw cli -p '${cliPrompt.replace(/'/g, "'\\''")}' --tool gemini --mode analysis`, { timeout: 120000 });
339
+
340
+ // Parse JSON from result (may be wrapped in markdown code block)
341
+ let jsonText = result.trim();
342
+ const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)```/);
343
+ if (jsonMatch) {
344
+ jsonText = jsonMatch[1].trim();
345
+ }
346
+
347
+ try {
348
+ const extracted = JSON.parse(jsonText);
349
+
350
+ // Normalize tasks
351
+ const tasks = (extracted.tasks || []).map((t, i) => ({
352
+ id: t.id || `T${i + 1}`,
353
+ title: t.title || 'Untitled task',
354
+ scope: t.scope || '',
355
+ action: validateAction(t.action) || 'Implement',
356
+ description: t.description || t.title,
357
+ modification_points: t.modification_points || [],
358
+ implementation: Array.isArray(t.implementation) ? t.implementation : [t.implementation || ''],
359
+ test: t.test || {},
360
+ acceptance: {
361
+ criteria: Array.isArray(t.acceptance) ? t.acceptance : [t.acceptance || ''],
362
+ verification: t.verification || []
363
+ },
364
+ depends_on: t.depends_on || [],
365
+ priority: t.priority || 3
366
+ }));
367
+
368
+ return {
369
+ title: extracted.title || 'Extracted Plan',
370
+ description: extracted.summary || extracted.title,
371
+ approach: extracted.approach || '',
372
+ tasks: tasks,
373
+ metadata: {
374
+ source_type: 'markdown',
375
+ source_path: filePath,
376
+ extraction_method: 'gemini-ai'
377
+ }
378
+ };
379
+ } catch (e) {
380
+ // Provide more context for debugging
381
+ throw new Error(`E005: Failed to extract tasks from markdown. Gemini response was not valid JSON. Error: ${e.message}. Response preview: ${jsonText.substring(0, 200)}...`);
382
+ }
383
+ }
384
+
385
+ function validateAction(action) {
386
+ const validActions = ['Create', 'Update', 'Implement', 'Refactor', 'Add', 'Delete', 'Configure', 'Test', 'Fix'];
387
+ if (!action) return null;
388
+ const normalized = action.charAt(0).toUpperCase() + action.slice(1).toLowerCase();
389
+ return validActions.includes(normalized) ? normalized : null;
390
+ }
391
+ ```
392
+
393
+ #### Extractor: JSON File
394
+
395
+ ```javascript
396
+ function extractFromJsonFile(filePath) {
397
+ const content = Read(filePath);
398
+ const plan = JSON.parse(content);
399
+
400
+ // Detect if it's already solution format or plan format
401
+ if (plan.tasks && Array.isArray(plan.tasks)) {
402
+ // Map tasks to normalized format
403
+ const tasks = plan.tasks.map((t, i) => ({
404
+ id: t.id || `T${i + 1}`,
405
+ title: t.title,
406
+ scope: t.scope || '',
407
+ action: t.action || 'Implement',
408
+ description: t.description || t.title,
409
+ modification_points: t.modification_points || [],
410
+ implementation: Array.isArray(t.implementation) ? t.implementation : [t.implementation || ''],
411
+ test: t.test || t.verification || {},
412
+ acceptance: normalizeAcceptance(t.acceptance),
413
+ depends_on: t.depends_on || [],
414
+ priority: t.priority || 3
415
+ }));
416
+
417
+ return {
418
+ title: plan.summary?.split('.')[0] || plan.title || 'JSON Plan',
419
+ description: plan.summary || plan.description,
420
+ approach: plan.approach,
421
+ tasks: tasks,
422
+ metadata: {
423
+ source_type: 'json',
424
+ source_path: filePath,
425
+ complexity: plan.complexity,
426
+ original_metadata: plan._metadata
427
+ }
428
+ };
429
+ }
430
+
431
+ throw new Error('E002: JSON file does not contain valid plan structure (missing tasks array)');
432
+ }
433
+
434
+ function normalizeAcceptance(acceptance) {
435
+ if (!acceptance) return { criteria: [], verification: [] };
436
+ if (typeof acceptance === 'object' && acceptance.criteria) return acceptance;
437
+ if (Array.isArray(acceptance)) return { criteria: acceptance, verification: [] };
438
+ return { criteria: [String(acceptance)], verification: [] };
439
+ }
440
+ ```
441
+
442
+ ### Phase 3: Normalize Task IDs
443
+
444
+ ```javascript
445
+ function normalizeTaskIds(tasks) {
446
+ return tasks.map((t, i) => ({
447
+ ...t,
448
+ id: `T${i + 1}`,
449
+ // Also normalize depends_on references
450
+ depends_on: (t.depends_on || []).map(d => {
451
+ // Handle various ID formats: IMPL-001, T1, 1, etc.
452
+ const num = d.match(/\d+/)?.[0];
453
+ return num ? `T${parseInt(num)}` : d;
454
+ })
455
+ }));
456
+ }
457
+ ```
458
+
459
+ ### Phase 4: Resolve Issue (Create or Find)
460
+
461
+ ```javascript
462
+ let issueId = flags.issue;
463
+ let existingSolution = null;
464
+
465
+ if (issueId) {
466
+ // Validate issue exists
467
+ let issueCheck;
468
+ try {
469
+ issueCheck = Bash(`ccw issue status ${issueId} --json 2>/dev/null`).trim();
470
+ if (!issueCheck || issueCheck === '') {
471
+ throw new Error('empty response');
472
+ }
473
+ } catch (e) {
474
+ throw new Error(`E003: Issue not found: ${issueId}`);
475
+ }
476
+
477
+ const issue = JSON.parse(issueCheck);
478
+
479
+ // Check if issue already has bound solution
480
+ if (issue.bound_solution_id && !flags.supplement) {
481
+ throw new Error(`E004: Issue ${issueId} already has bound solution (${issue.bound_solution_id}). Use --supplement to add tasks.`);
482
+ }
483
+
484
+ // Load existing solution for supplement mode
485
+ if (flags.supplement && issue.bound_solution_id) {
486
+ try {
487
+ const solResult = Bash(`ccw issue solution ${issue.bound_solution_id} --json`).trim();
488
+ existingSolution = JSON.parse(solResult);
489
+ console.log(`Loaded existing solution with ${existingSolution.tasks.length} tasks`);
490
+ } catch (e) {
491
+ throw new Error(`Failed to load existing solution: ${e.message}`);
492
+ }
493
+ }
494
+ } else {
495
+ // Create new issue via ccw issue create (auto-generates correct ID)
496
+ // Smart extraction: title from content, priority from complexity
497
+ const title = extracted.title || 'Converted Plan';
498
+ const context = extracted.description || extracted.approach || title;
499
+
500
+ // Auto-determine priority based on complexity
501
+ const complexityMap = { high: 2, medium: 3, low: 4 };
502
+ const priority = complexityMap[extracted.metadata.complexity?.toLowerCase()] || 3;
503
+
504
+ try {
505
+ // Use heredoc to avoid shell escaping issues
506
+ const createResult = Bash(`ccw issue create << 'EOF'
507
+ {
508
+ "title": ${JSON.stringify(title)},
509
+ "context": ${JSON.stringify(context)},
510
+ "priority": ${priority},
511
+ "source": "converted"
512
+ }
513
+ EOF`).trim();
514
+
515
+ // Parse result to get created issue ID
516
+ const created = JSON.parse(createResult);
517
+ issueId = created.id;
518
+ console.log(`Created issue: ${issueId} (priority: ${priority})`);
519
+ } catch (e) {
520
+ throw new Error(`Failed to create issue: ${e.message}`);
521
+ }
522
+ }
523
+ ```
524
+
525
+ ### Phase 5: Generate Solution
526
+
527
+ ```javascript
528
+ // Generate solution ID
529
+ function generateSolutionId(issueId) {
530
+ const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
531
+ let uid = '';
532
+ for (let i = 0; i < 4; i++) {
533
+ uid += chars[Math.floor(Math.random() * chars.length)];
534
+ }
535
+ return `SOL-${issueId}-${uid}`;
536
+ }
537
+
538
+ let solution;
539
+ const solutionId = generateSolutionId(issueId);
540
+
541
+ if (flags.supplement && existingSolution) {
542
+ // Supplement mode: merge with existing solution
543
+ const maxTaskId = Math.max(...existingSolution.tasks.map(t => parseInt(t.id.slice(1))));
544
+
545
+ const newTasks = extracted.tasks.map((t, i) => ({
546
+ ...t,
547
+ id: `T${maxTaskId + i + 1}`
548
+ }));
549
+
550
+ solution = {
551
+ ...existingSolution,
552
+ tasks: [...existingSolution.tasks, ...newTasks],
553
+ approach: existingSolution.approach + '\n\n[Supplementary] ' + (extracted.approach || ''),
554
+ updated_at: new Date().toISOString()
555
+ };
556
+
557
+ console.log(`Supplementing: ${existingSolution.tasks.length} existing + ${newTasks.length} new = ${solution.tasks.length} total tasks`);
558
+ } else {
559
+ // New solution
560
+ solution = {
561
+ id: solutionId,
562
+ description: extracted.description || extracted.title,
563
+ approach: extracted.approach,
564
+ tasks: extracted.tasks,
565
+ exploration_context: extracted.metadata.exploration_angles ? {
566
+ exploration_angles: extracted.metadata.exploration_angles
567
+ } : undefined,
568
+ analysis: {
569
+ risk: 'medium',
570
+ impact: 'medium',
571
+ complexity: extracted.metadata.complexity?.toLowerCase() || 'medium'
572
+ },
573
+ is_bound: false,
574
+ created_at: new Date().toISOString(),
575
+ _conversion_metadata: {
576
+ source_type: extracted.metadata.source_type,
577
+ source_path: extracted.metadata.source_path,
578
+ converted_at: new Date().toISOString()
579
+ }
580
+ };
581
+ }
582
+ ```
583
+
584
+ ### Phase 6: Confirm & Persist
585
+
586
+ ```javascript
587
+ // Display preview
588
+ console.log(`
589
+ ## Conversion Summary
590
+
591
+ **Issue**: ${issueId}
592
+ **Solution**: ${flags.supplement ? existingSolution.id : solutionId}
593
+ **Tasks**: ${solution.tasks.length}
594
+ **Mode**: ${flags.supplement ? 'Supplement' : 'New'}
595
+
596
+ ### Tasks:
597
+ ${solution.tasks.map(t => `- ${t.id}: ${t.title} [${t.action}]`).join('\n')}
598
+ `);
599
+
600
+ // Confirm if not auto mode
601
+ if (!flags.yes && !flags.y) {
602
+ const confirm = AskUserQuestion({
603
+ questions: [{
604
+ question: `Create solution for issue ${issueId} with ${solution.tasks.length} tasks?`,
605
+ header: 'Confirm',
606
+ multiSelect: false,
607
+ options: [
608
+ { label: 'Yes, create solution', description: 'Create and bind solution' },
609
+ { label: 'Cancel', description: 'Abort without changes' }
610
+ ]
611
+ }]
612
+ });
613
+
614
+ if (!confirm.answers?.['Confirm']?.includes('Yes')) {
615
+ console.log('Cancelled.');
616
+ return;
617
+ }
618
+ }
619
+
620
+ // Persist solution (following issue-plan-agent pattern)
621
+ Bash(`mkdir -p .workflow/issues/solutions`);
622
+
623
+ const solutionFile = `.workflow/issues/solutions/${issueId}.jsonl`;
624
+
625
+ if (flags.supplement) {
626
+ // Supplement mode: update existing solution line atomically
627
+ try {
628
+ const existingContent = Read(solutionFile);
629
+ const lines = existingContent.trim().split('\n').filter(l => l);
630
+ const updatedLines = lines.map(line => {
631
+ const sol = JSON.parse(line);
632
+ if (sol.id === existingSolution.id) {
633
+ return JSON.stringify(solution);
634
+ }
635
+ return line;
636
+ });
637
+ // Atomic write: write entire content at once
638
+ Write({ file_path: solutionFile, content: updatedLines.join('\n') + '\n' });
639
+ console.log(`✓ Updated solution: ${existingSolution.id}`);
640
+ } catch (e) {
641
+ throw new Error(`Failed to update solution: ${e.message}`);
642
+ }
643
+
644
+ // Note: No need to rebind - solution is already bound to issue
645
+ } else {
646
+ // New solution: append to JSONL file (following issue-plan-agent pattern)
647
+ try {
648
+ const solutionLine = JSON.stringify(solution);
649
+
650
+ // Read existing content, append new line, write atomically
651
+ const existing = Bash(`test -f "${solutionFile}" && cat "${solutionFile}" || echo ""`).trim();
652
+ const newContent = existing ? existing + '\n' + solutionLine + '\n' : solutionLine + '\n';
653
+ Write({ file_path: solutionFile, content: newContent });
654
+
655
+ console.log(`✓ Created solution: ${solutionId}`);
656
+ } catch (e) {
657
+ throw new Error(`Failed to write solution: ${e.message}`);
658
+ }
659
+
660
+ // Bind solution to issue
661
+ try {
662
+ Bash(`ccw issue bind ${issueId} ${solutionId}`);
663
+ console.log(`✓ Bound solution to issue`);
664
+ } catch (e) {
665
+ // Cleanup: remove solution file on bind failure
666
+ try {
667
+ Bash(`rm -f "${solutionFile}"`);
668
+ } catch (cleanupError) {
669
+ // Ignore cleanup errors
670
+ }
671
+ throw new Error(`Failed to bind solution: ${e.message}`);
672
+ }
673
+
674
+ // Update issue status to planned
675
+ try {
676
+ Bash(`ccw issue update ${issueId} --status planned`);
677
+ } catch (e) {
678
+ throw new Error(`Failed to update issue status: ${e.message}`);
679
+ }
680
+ }
681
+ ```
682
+
683
+ ### Phase 7: Summary
684
+
685
+ ```javascript
686
+ console.log(`
687
+ ## Done
688
+
689
+ **Issue**: ${issueId}
690
+ **Solution**: ${flags.supplement ? existingSolution.id : solutionId}
691
+ **Tasks**: ${solution.tasks.length}
692
+ **Status**: planned
693
+
694
+ ### Next Steps:
695
+ - \`/issue:queue\` → Form execution queue
696
+ - \`ccw issue status ${issueId}\` → View issue details
697
+ - \`ccw issue solution ${flags.supplement ? existingSolution.id : solutionId}\` → View solution
698
+ `);
699
+ ```
700
+
701
+ ## Error Handling
702
+
703
+ | Error | Code | Resolution |
704
+ |-------|------|------------|
705
+ | Source not found | E001 | Check path exists |
706
+ | Invalid source format | E002 | Verify file contains valid plan structure |
707
+ | Issue not found | E003 | Check issue ID or omit --issue to create new |
708
+ | Solution already bound | E004 | Use --supplement to add tasks |
709
+ | AI extraction failed | E005 | Check markdown structure, try simpler format |
710
+ | No tasks extracted | E006 | Source must contain at least 1 task |
711
+
712
+ ## Related Commands
713
+
714
+ - `/issue:plan` - Generate solutions from issue exploration
715
+ - `/issue:queue` - Form execution queue from bound solutions
716
+ - `/issue:execute` - Execute queue with DAG parallelism
717
+ - `ccw issue status <id>` - View issue details
718
+ - `ccw issue solution <id>` - View solution details