claude-code-workflow 6.3.4 → 6.3.6
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/.claude/agents/issue-plan-agent.md +859 -0
- package/.claude/agents/issue-queue-agent.md +702 -0
- package/.claude/commands/issue/execute.md +453 -0
- package/.claude/commands/issue/manage.md +865 -0
- package/.claude/commands/issue/new.md +484 -0
- package/.claude/commands/issue/plan.md +421 -0
- package/.claude/commands/issue/queue.md +354 -0
- package/.claude/commands/{clean.md → workflow/clean.md} +5 -5
- package/.claude/commands/workflow/docs/analyze.md +1467 -0
- package/.claude/commands/workflow/docs/copyright.md +1265 -0
- package/.claude/commands/workflow/execute.md +0 -1
- package/.claude/commands/workflow/tools/conflict-resolution.md +76 -240
- package/.claude/commands/workflow/tools/context-gather.md +0 -2
- package/.claude/commands/workflow/tools/task-generate-agent.md +81 -8
- package/.claude/commands/workflow/tools/task-generate-tdd.md +0 -9
- package/.claude/commands/workflow/tools/test-context-gather.md +2 -3
- package/.claude/commands/workflow/tools/test-task-generate.md +0 -2
- package/.claude/skills/_shared/mermaid-utils.md +584 -0
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +0 -2
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +1 -2
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +1 -8
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +1 -4
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +0 -2
- package/.claude/skills/copyright-docs/SKILL.md +132 -0
- package/.claude/skills/copyright-docs/phases/01-metadata-collection.md +78 -0
- package/.claude/skills/copyright-docs/phases/01.5-project-exploration.md +150 -0
- package/.claude/skills/copyright-docs/phases/02-deep-analysis.md +664 -0
- package/.claude/skills/copyright-docs/phases/02.5-consolidation.md +192 -0
- package/.claude/skills/copyright-docs/phases/04-document-assembly.md +261 -0
- package/.claude/skills/copyright-docs/phases/05-compliance-refinement.md +192 -0
- package/.claude/skills/copyright-docs/specs/cpcc-requirements.md +121 -0
- package/.claude/skills/copyright-docs/templates/agent-base.md +200 -0
- package/.claude/skills/project-analyze/SKILL.md +162 -0
- package/.claude/skills/project-analyze/phases/01-requirements-discovery.md +79 -0
- package/.claude/skills/project-analyze/phases/02-project-exploration.md +176 -0
- package/.claude/skills/project-analyze/phases/03-deep-analysis.md +854 -0
- package/.claude/skills/project-analyze/phases/03.5-consolidation.md +233 -0
- package/.claude/skills/project-analyze/phases/04-report-generation.md +217 -0
- package/.claude/skills/project-analyze/phases/05-iterative-refinement.md +124 -0
- package/.claude/skills/project-analyze/specs/quality-standards.md +115 -0
- package/.claude/skills/project-analyze/specs/writing-style.md +152 -0
- package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +79 -65
- package/.claude/workflows/cli-templates/schemas/issue-task-jsonl-schema.json +136 -0
- package/.claude/workflows/cli-templates/schemas/issues-jsonl-schema.json +74 -0
- package/.claude/workflows/cli-templates/schemas/queue-schema.json +136 -0
- package/.claude/workflows/cli-templates/schemas/registry-schema.json +94 -0
- package/.claude/workflows/cli-templates/schemas/solution-schema.json +120 -0
- package/.claude/workflows/cli-templates/schemas/solutions-jsonl-schema.json +125 -0
- package/.codex/prompts/issue-execute.md +266 -0
- package/README.md +11 -1
- package/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +25 -0
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/commands/cli.d.ts.map +1 -1
- package/ccw/dist/commands/cli.js +46 -8
- package/ccw/dist/commands/cli.js.map +1 -1
- package/ccw/dist/commands/issue.d.ts +21 -0
- package/ccw/dist/commands/issue.d.ts.map +1 -0
- package/ccw/dist/commands/issue.js +895 -0
- package/ccw/dist/commands/issue.js.map +1 -0
- package/ccw/dist/core/dashboard-generator-patch.js +1 -0
- package/ccw/dist/core/dashboard-generator-patch.js.map +1 -1
- package/ccw/dist/core/routes/cli-routes.js +2 -2
- package/ccw/dist/core/routes/cli-routes.js.map +1 -1
- package/ccw/dist/core/routes/issue-routes.d.ts +34 -0
- package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/issue-routes.js +487 -0
- package/ccw/dist/core/routes/issue-routes.js.map +1 -0
- package/ccw/dist/core/server.d.ts.map +1 -1
- package/ccw/dist/core/server.js +17 -2
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.d.ts +7 -3
- package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.js +31 -17
- package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
- package/ccw/dist/tools/smart-search.d.ts +25 -0
- package/ccw/dist/tools/smart-search.d.ts.map +1 -1
- package/ccw/dist/tools/smart-search.js +121 -17
- package/ccw/dist/tools/smart-search.js.map +1 -1
- package/ccw/src/cli.ts +26 -0
- package/ccw/src/commands/cli.ts +49 -7
- package/ccw/src/commands/issue.ts +1184 -0
- package/ccw/src/core/dashboard-generator-patch.ts +1 -0
- package/ccw/src/core/routes/cli-routes.ts +3 -3
- package/ccw/src/core/routes/issue-routes.ts +559 -0
- package/ccw/src/core/server.ts +17 -2
- package/ccw/src/templates/dashboard-css/32-issue-manager.css +2544 -0
- package/ccw/src/templates/dashboard-css/33-cli-stream-viewer.css +467 -0
- package/ccw/src/templates/dashboard-js/components/cli-history.js +40 -13
- package/ccw/src/templates/dashboard-js/components/cli-status.js +26 -2
- package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +461 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +8 -0
- package/ccw/src/templates/dashboard-js/components/notifications.js +16 -0
- package/ccw/src/templates/dashboard-js/i18n.js +290 -2
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +5 -0
- package/ccw/src/templates/dashboard-js/views/history.js +19 -4
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +11 -5
- package/ccw/src/templates/dashboard-js/views/issue-manager.js +1546 -0
- package/ccw/src/templates/dashboard.html +55 -0
- package/ccw/src/tools/claude-cli-tools.ts +37 -20
- package/ccw/src/tools/smart-search.ts +157 -16
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/config.py +5 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/hybrid_search.py +144 -11
- package/codex-lens/src/codexlens/search/ranking.py +267 -1
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/chunker.py +55 -10
- package/package.json +2 -2
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: new
|
|
3
|
+
description: Create structured issue from GitHub URL or text description, extracting key elements into issues.jsonl
|
|
4
|
+
argument-hint: "<github-url | text-description> [--priority 1-5] [--labels label1,label2]"
|
|
5
|
+
allowed-tools: TodoWrite(*), Bash(*), Read(*), Write(*), WebFetch(*), AskUserQuestion(*)
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Issue New Command (/issue:new)
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Creates a new structured issue from either:
|
|
13
|
+
1. **GitHub Issue URL** - Fetches and parses issue content via `gh` CLI
|
|
14
|
+
2. **Text Description** - Parses natural language into structured fields
|
|
15
|
+
|
|
16
|
+
Outputs a well-formed issue entry to `.workflow/issues/issues.jsonl`.
|
|
17
|
+
|
|
18
|
+
## Issue Structure (Closed-Loop)
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
interface Issue {
|
|
22
|
+
id: string; // GH-123 or ISS-YYYYMMDD-HHMMSS
|
|
23
|
+
title: string; // Issue title (clear, concise)
|
|
24
|
+
status: 'registered'; // Initial status
|
|
25
|
+
priority: number; // 1 (critical) to 5 (low)
|
|
26
|
+
context: string; // Problem description
|
|
27
|
+
source: 'github' | 'text'; // Input source type
|
|
28
|
+
source_url?: string; // GitHub URL if applicable
|
|
29
|
+
labels?: string[]; // Categorization labels
|
|
30
|
+
|
|
31
|
+
// Structured extraction
|
|
32
|
+
problem_statement: string; // What is the problem?
|
|
33
|
+
expected_behavior?: string; // What should happen?
|
|
34
|
+
actual_behavior?: string; // What actually happens?
|
|
35
|
+
affected_components?: string[];// Files/modules affected
|
|
36
|
+
reproduction_steps?: string[]; // Steps to reproduce
|
|
37
|
+
|
|
38
|
+
// Closed-loop requirements (guide plan generation)
|
|
39
|
+
lifecycle_requirements: {
|
|
40
|
+
test_strategy: 'unit' | 'integration' | 'e2e' | 'manual' | 'auto';
|
|
41
|
+
regression_scope: 'affected' | 'related' | 'full'; // Which tests to run
|
|
42
|
+
acceptance_type: 'automated' | 'manual' | 'both'; // How to verify
|
|
43
|
+
commit_strategy: 'per-task' | 'squash' | 'atomic'; // Commit granularity
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Metadata
|
|
47
|
+
bound_solution_id: null;
|
|
48
|
+
solution_count: 0;
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at: string;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Task Lifecycle (Each Task is Closed-Loop)
|
|
55
|
+
|
|
56
|
+
When `/issue:plan` generates tasks, each task MUST include:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
interface SolutionTask {
|
|
60
|
+
id: string;
|
|
61
|
+
title: string;
|
|
62
|
+
scope: string;
|
|
63
|
+
action: string;
|
|
64
|
+
|
|
65
|
+
// Phase 1: Implementation
|
|
66
|
+
implementation: string[]; // Step-by-step implementation
|
|
67
|
+
modification_points: { file: string; target: string; change: string }[];
|
|
68
|
+
|
|
69
|
+
// Phase 2: Testing
|
|
70
|
+
test: {
|
|
71
|
+
unit?: string[]; // Unit test requirements
|
|
72
|
+
integration?: string[]; // Integration test requirements
|
|
73
|
+
commands?: string[]; // Test commands to run
|
|
74
|
+
coverage_target?: number; // Minimum coverage %
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Phase 3: Regression
|
|
78
|
+
regression: string[]; // Regression check commands/points
|
|
79
|
+
|
|
80
|
+
// Phase 4: Acceptance
|
|
81
|
+
acceptance: {
|
|
82
|
+
criteria: string[]; // Testable acceptance criteria
|
|
83
|
+
verification: string[]; // How to verify each criterion
|
|
84
|
+
manual_checks?: string[]; // Manual verification if needed
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Phase 5: Commit
|
|
88
|
+
commit: {
|
|
89
|
+
type: 'feat' | 'fix' | 'refactor' | 'test' | 'docs' | 'chore';
|
|
90
|
+
scope: string; // e.g., "auth", "api"
|
|
91
|
+
message_template: string; // Commit message template
|
|
92
|
+
breaking?: boolean;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
depends_on: string[];
|
|
96
|
+
executor: 'codex' | 'gemini' | 'agent' | 'auto';
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Usage
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# From GitHub URL
|
|
104
|
+
/issue:new https://github.com/owner/repo/issues/123
|
|
105
|
+
|
|
106
|
+
# From text description
|
|
107
|
+
/issue:new "Login fails when password contains special characters. Expected: successful login. Actual: 500 error. Affects src/auth/*"
|
|
108
|
+
|
|
109
|
+
# With options
|
|
110
|
+
/issue:new <url-or-text> --priority 2 --labels "bug,auth"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Implementation
|
|
114
|
+
|
|
115
|
+
### Phase 1: Input Detection
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
const input = userInput.trim();
|
|
119
|
+
const flags = parseFlags(userInput); // --priority, --labels
|
|
120
|
+
|
|
121
|
+
// Detect input type
|
|
122
|
+
const isGitHubUrl = input.match(/github\.com\/[\w-]+\/[\w-]+\/issues\/\d+/);
|
|
123
|
+
const isGitHubShort = input.match(/^#(\d+)$/); // #123 format
|
|
124
|
+
|
|
125
|
+
let issueData = {};
|
|
126
|
+
|
|
127
|
+
if (isGitHubUrl || isGitHubShort) {
|
|
128
|
+
// GitHub issue - fetch via gh CLI
|
|
129
|
+
issueData = await fetchGitHubIssue(input);
|
|
130
|
+
} else {
|
|
131
|
+
// Text description - parse structure
|
|
132
|
+
issueData = await parseTextDescription(input);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Phase 2: GitHub Issue Fetching
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
async function fetchGitHubIssue(urlOrNumber) {
|
|
140
|
+
let issueRef;
|
|
141
|
+
|
|
142
|
+
if (urlOrNumber.startsWith('http')) {
|
|
143
|
+
// Extract owner/repo/number from URL
|
|
144
|
+
const match = urlOrNumber.match(/github\.com\/([\w-]+)\/([\w-]+)\/issues\/(\d+)/);
|
|
145
|
+
if (!match) throw new Error('Invalid GitHub URL');
|
|
146
|
+
issueRef = `${match[1]}/${match[2]}#${match[3]}`;
|
|
147
|
+
} else {
|
|
148
|
+
// #123 format - use current repo
|
|
149
|
+
issueRef = urlOrNumber.replace('#', '');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Fetch via gh CLI
|
|
153
|
+
const result = Bash(`gh issue view ${issueRef} --json number,title,body,labels,state,url`);
|
|
154
|
+
const ghIssue = JSON.parse(result);
|
|
155
|
+
|
|
156
|
+
// Parse body for structure
|
|
157
|
+
const parsed = parseIssueBody(ghIssue.body);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
id: `GH-${ghIssue.number}`,
|
|
161
|
+
title: ghIssue.title,
|
|
162
|
+
source: 'github',
|
|
163
|
+
source_url: ghIssue.url,
|
|
164
|
+
labels: ghIssue.labels.map(l => l.name),
|
|
165
|
+
context: ghIssue.body,
|
|
166
|
+
...parsed
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function parseIssueBody(body) {
|
|
171
|
+
// Extract structured sections from markdown body
|
|
172
|
+
const sections = {};
|
|
173
|
+
|
|
174
|
+
// Problem/Description
|
|
175
|
+
const problemMatch = body.match(/##?\s*(problem|description|issue)[:\s]*([\s\S]*?)(?=##|$)/i);
|
|
176
|
+
if (problemMatch) sections.problem_statement = problemMatch[2].trim();
|
|
177
|
+
|
|
178
|
+
// Expected behavior
|
|
179
|
+
const expectedMatch = body.match(/##?\s*(expected|should)[:\s]*([\s\S]*?)(?=##|$)/i);
|
|
180
|
+
if (expectedMatch) sections.expected_behavior = expectedMatch[2].trim();
|
|
181
|
+
|
|
182
|
+
// Actual behavior
|
|
183
|
+
const actualMatch = body.match(/##?\s*(actual|current)[:\s]*([\s\S]*?)(?=##|$)/i);
|
|
184
|
+
if (actualMatch) sections.actual_behavior = actualMatch[2].trim();
|
|
185
|
+
|
|
186
|
+
// Steps to reproduce
|
|
187
|
+
const stepsMatch = body.match(/##?\s*(steps|reproduce)[:\s]*([\s\S]*?)(?=##|$)/i);
|
|
188
|
+
if (stepsMatch) {
|
|
189
|
+
const stepsText = stepsMatch[2].trim();
|
|
190
|
+
sections.reproduction_steps = stepsText
|
|
191
|
+
.split('\n')
|
|
192
|
+
.filter(line => line.match(/^\s*[\d\-\*]/))
|
|
193
|
+
.map(line => line.replace(/^\s*[\d\.\-\*]\s*/, '').trim());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Affected components (from file references)
|
|
197
|
+
const fileMatches = body.match(/`[^`]*\.(ts|js|tsx|jsx|py|go|rs)[^`]*`/g);
|
|
198
|
+
if (fileMatches) {
|
|
199
|
+
sections.affected_components = [...new Set(fileMatches.map(f => f.replace(/`/g, '')))];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Fallback: use entire body as problem statement
|
|
203
|
+
if (!sections.problem_statement) {
|
|
204
|
+
sections.problem_statement = body.substring(0, 500);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return sections;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Phase 3: Text Description Parsing
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
async function parseTextDescription(text) {
|
|
215
|
+
// Generate unique ID
|
|
216
|
+
const id = `ISS-${new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14)}`;
|
|
217
|
+
|
|
218
|
+
// Extract structured elements using patterns
|
|
219
|
+
const result = {
|
|
220
|
+
id,
|
|
221
|
+
source: 'text',
|
|
222
|
+
title: '',
|
|
223
|
+
problem_statement: '',
|
|
224
|
+
expected_behavior: null,
|
|
225
|
+
actual_behavior: null,
|
|
226
|
+
affected_components: [],
|
|
227
|
+
reproduction_steps: []
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Pattern: "Title. Description. Expected: X. Actual: Y. Affects: files"
|
|
231
|
+
const sentences = text.split(/\.(?=\s|$)/);
|
|
232
|
+
|
|
233
|
+
// First sentence as title
|
|
234
|
+
result.title = sentences[0]?.trim() || 'Untitled Issue';
|
|
235
|
+
|
|
236
|
+
// Look for keywords
|
|
237
|
+
for (const sentence of sentences) {
|
|
238
|
+
const s = sentence.trim();
|
|
239
|
+
|
|
240
|
+
if (s.match(/^expected:?\s*/i)) {
|
|
241
|
+
result.expected_behavior = s.replace(/^expected:?\s*/i, '');
|
|
242
|
+
} else if (s.match(/^actual:?\s*/i)) {
|
|
243
|
+
result.actual_behavior = s.replace(/^actual:?\s*/i, '');
|
|
244
|
+
} else if (s.match(/^affects?:?\s*/i)) {
|
|
245
|
+
const components = s.replace(/^affects?:?\s*/i, '').split(/[,\s]+/);
|
|
246
|
+
result.affected_components = components.filter(c => c.includes('/') || c.includes('.'));
|
|
247
|
+
} else if (s.match(/^steps?:?\s*/i)) {
|
|
248
|
+
result.reproduction_steps = s.replace(/^steps?:?\s*/i, '').split(/[,;]/);
|
|
249
|
+
} else if (!result.problem_statement && s.length > 10) {
|
|
250
|
+
result.problem_statement = s;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Fallback problem statement
|
|
255
|
+
if (!result.problem_statement) {
|
|
256
|
+
result.problem_statement = text.substring(0, 300);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Phase 4: Lifecycle Configuration
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// Ask for lifecycle requirements (or use smart defaults)
|
|
267
|
+
const lifecycleAnswer = AskUserQuestion({
|
|
268
|
+
questions: [
|
|
269
|
+
{
|
|
270
|
+
question: 'Test strategy for this issue?',
|
|
271
|
+
header: 'Test',
|
|
272
|
+
multiSelect: false,
|
|
273
|
+
options: [
|
|
274
|
+
{ label: 'auto', description: 'Auto-detect based on affected files (Recommended)' },
|
|
275
|
+
{ label: 'unit', description: 'Unit tests only' },
|
|
276
|
+
{ label: 'integration', description: 'Integration tests' },
|
|
277
|
+
{ label: 'e2e', description: 'End-to-end tests' },
|
|
278
|
+
{ label: 'manual', description: 'Manual testing only' }
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
question: 'Regression scope?',
|
|
283
|
+
header: 'Regression',
|
|
284
|
+
multiSelect: false,
|
|
285
|
+
options: [
|
|
286
|
+
{ label: 'affected', description: 'Only affected module tests (Recommended)' },
|
|
287
|
+
{ label: 'related', description: 'Affected + dependent modules' },
|
|
288
|
+
{ label: 'full', description: 'Full test suite' }
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
question: 'Commit strategy?',
|
|
293
|
+
header: 'Commit',
|
|
294
|
+
multiSelect: false,
|
|
295
|
+
options: [
|
|
296
|
+
{ label: 'per-task', description: 'One commit per task (Recommended)' },
|
|
297
|
+
{ label: 'atomic', description: 'Single commit for entire issue' },
|
|
298
|
+
{ label: 'squash', description: 'Squash at the end' }
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const lifecycle = {
|
|
305
|
+
test_strategy: lifecycleAnswer.test || 'auto',
|
|
306
|
+
regression_scope: lifecycleAnswer.regression || 'affected',
|
|
307
|
+
acceptance_type: 'automated',
|
|
308
|
+
commit_strategy: lifecycleAnswer.commit || 'per-task'
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
issueData.lifecycle_requirements = lifecycle;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Phase 5: User Confirmation
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
// Show parsed data and ask for confirmation
|
|
318
|
+
console.log(`
|
|
319
|
+
## Parsed Issue
|
|
320
|
+
|
|
321
|
+
**ID**: ${issueData.id}
|
|
322
|
+
**Title**: ${issueData.title}
|
|
323
|
+
**Source**: ${issueData.source}${issueData.source_url ? ` (${issueData.source_url})` : ''}
|
|
324
|
+
|
|
325
|
+
### Problem Statement
|
|
326
|
+
${issueData.problem_statement}
|
|
327
|
+
|
|
328
|
+
${issueData.expected_behavior ? `### Expected Behavior\n${issueData.expected_behavior}\n` : ''}
|
|
329
|
+
${issueData.actual_behavior ? `### Actual Behavior\n${issueData.actual_behavior}\n` : ''}
|
|
330
|
+
${issueData.affected_components?.length ? `### Affected Components\n${issueData.affected_components.map(c => `- ${c}`).join('\n')}\n` : ''}
|
|
331
|
+
${issueData.reproduction_steps?.length ? `### Reproduction Steps\n${issueData.reproduction_steps.map((s, i) => `${i+1}. ${s}`).join('\n')}\n` : ''}
|
|
332
|
+
|
|
333
|
+
### Lifecycle Configuration
|
|
334
|
+
- **Test Strategy**: ${lifecycle.test_strategy}
|
|
335
|
+
- **Regression Scope**: ${lifecycle.regression_scope}
|
|
336
|
+
- **Commit Strategy**: ${lifecycle.commit_strategy}
|
|
337
|
+
`);
|
|
338
|
+
|
|
339
|
+
// Ask user to confirm or edit
|
|
340
|
+
const answer = AskUserQuestion({
|
|
341
|
+
questions: [{
|
|
342
|
+
question: 'Create this issue?',
|
|
343
|
+
header: 'Confirm',
|
|
344
|
+
multiSelect: false,
|
|
345
|
+
options: [
|
|
346
|
+
{ label: 'Create', description: 'Save issue to issues.jsonl' },
|
|
347
|
+
{ label: 'Edit Title', description: 'Modify the issue title' },
|
|
348
|
+
{ label: 'Edit Priority', description: 'Change priority (1-5)' },
|
|
349
|
+
{ label: 'Cancel', description: 'Discard and exit' }
|
|
350
|
+
]
|
|
351
|
+
}]
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
if (answer.includes('Cancel')) {
|
|
355
|
+
console.log('Issue creation cancelled.');
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (answer.includes('Edit Title')) {
|
|
360
|
+
const titleAnswer = AskUserQuestion({
|
|
361
|
+
questions: [{
|
|
362
|
+
question: 'Enter new title:',
|
|
363
|
+
header: 'Title',
|
|
364
|
+
multiSelect: false,
|
|
365
|
+
options: [
|
|
366
|
+
{ label: issueData.title.substring(0, 40), description: 'Keep current' }
|
|
367
|
+
]
|
|
368
|
+
}]
|
|
369
|
+
});
|
|
370
|
+
// Handle custom input via "Other"
|
|
371
|
+
if (titleAnswer.customText) {
|
|
372
|
+
issueData.title = titleAnswer.customText;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Phase 6: Write to JSONL
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
// Construct final issue object
|
|
381
|
+
const priority = flags.priority ? parseInt(flags.priority) : 3;
|
|
382
|
+
const labels = flags.labels ? flags.labels.split(',').map(l => l.trim()) : [];
|
|
383
|
+
|
|
384
|
+
const newIssue = {
|
|
385
|
+
id: issueData.id,
|
|
386
|
+
title: issueData.title,
|
|
387
|
+
status: 'registered',
|
|
388
|
+
priority,
|
|
389
|
+
context: issueData.problem_statement,
|
|
390
|
+
source: issueData.source,
|
|
391
|
+
source_url: issueData.source_url || null,
|
|
392
|
+
labels: [...(issueData.labels || []), ...labels],
|
|
393
|
+
|
|
394
|
+
// Structured fields
|
|
395
|
+
problem_statement: issueData.problem_statement,
|
|
396
|
+
expected_behavior: issueData.expected_behavior || null,
|
|
397
|
+
actual_behavior: issueData.actual_behavior || null,
|
|
398
|
+
affected_components: issueData.affected_components || [],
|
|
399
|
+
reproduction_steps: issueData.reproduction_steps || [],
|
|
400
|
+
|
|
401
|
+
// Closed-loop lifecycle requirements
|
|
402
|
+
lifecycle_requirements: issueData.lifecycle_requirements || {
|
|
403
|
+
test_strategy: 'auto',
|
|
404
|
+
regression_scope: 'affected',
|
|
405
|
+
acceptance_type: 'automated',
|
|
406
|
+
commit_strategy: 'per-task'
|
|
407
|
+
},
|
|
408
|
+
|
|
409
|
+
// Metadata
|
|
410
|
+
bound_solution_id: null,
|
|
411
|
+
solution_count: 0,
|
|
412
|
+
created_at: new Date().toISOString(),
|
|
413
|
+
updated_at: new Date().toISOString()
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// Ensure directory exists
|
|
417
|
+
Bash('mkdir -p .workflow/issues');
|
|
418
|
+
|
|
419
|
+
// Append to issues.jsonl
|
|
420
|
+
const issuesPath = '.workflow/issues/issues.jsonl';
|
|
421
|
+
Bash(`echo '${JSON.stringify(newIssue)}' >> "${issuesPath}"`);
|
|
422
|
+
|
|
423
|
+
console.log(`
|
|
424
|
+
## Issue Created
|
|
425
|
+
|
|
426
|
+
**ID**: ${newIssue.id}
|
|
427
|
+
**Title**: ${newIssue.title}
|
|
428
|
+
**Priority**: ${newIssue.priority}
|
|
429
|
+
**Labels**: ${newIssue.labels.join(', ') || 'none'}
|
|
430
|
+
**Source**: ${newIssue.source}
|
|
431
|
+
|
|
432
|
+
### Next Steps
|
|
433
|
+
1. Plan solution: \`/issue:plan ${newIssue.id}\`
|
|
434
|
+
2. View details: \`ccw issue status ${newIssue.id}\`
|
|
435
|
+
3. Manage issues: \`/issue:manage\`
|
|
436
|
+
`);
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Examples
|
|
440
|
+
|
|
441
|
+
### GitHub Issue
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
/issue:new https://github.com/myorg/myrepo/issues/42 --priority 2
|
|
445
|
+
|
|
446
|
+
# Output:
|
|
447
|
+
## Issue Created
|
|
448
|
+
**ID**: GH-42
|
|
449
|
+
**Title**: Fix memory leak in WebSocket handler
|
|
450
|
+
**Priority**: 2
|
|
451
|
+
**Labels**: bug, performance
|
|
452
|
+
**Source**: github (https://github.com/myorg/myrepo/issues/42)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Text Description
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
/issue:new "API rate limiting not working. Expected: 429 after 100 requests. Actual: No limit. Affects src/middleware/rate-limit.ts"
|
|
459
|
+
|
|
460
|
+
# Output:
|
|
461
|
+
## Issue Created
|
|
462
|
+
**ID**: ISS-20251227-142530
|
|
463
|
+
**Title**: API rate limiting not working
|
|
464
|
+
**Priority**: 3
|
|
465
|
+
**Labels**: none
|
|
466
|
+
**Source**: text
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Error Handling
|
|
470
|
+
|
|
471
|
+
| Error | Resolution |
|
|
472
|
+
|-------|------------|
|
|
473
|
+
| Invalid GitHub URL | Show format hint, ask for correction |
|
|
474
|
+
| gh CLI not available | Fall back to WebFetch for public issues |
|
|
475
|
+
| Empty description | Prompt user for required fields |
|
|
476
|
+
| Duplicate issue ID | Auto-increment or suggest merge |
|
|
477
|
+
| Parse failure | Show raw input, ask for manual structuring |
|
|
478
|
+
|
|
479
|
+
## Related Commands
|
|
480
|
+
|
|
481
|
+
- `/issue:plan` - Plan solution for issue
|
|
482
|
+
- `/issue:manage` - Interactive issue management
|
|
483
|
+
- `ccw issue list` - List all issues
|
|
484
|
+
- `ccw issue status <id>` - View issue details
|