mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
refactor(issue): simplify extended_context and add follow-up questions
- Replace discovery_context with minimal extended_context (3 fields: location, suggested_fix, notes) - Add Phase 4.5: intelligent follow-up questions for missing issue fields - Fix JSONL append to ensure proper newline handling - Update schema and plan.md to use new extended_context structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,16 +35,11 @@ interface Issue {
|
|||||||
affected_components?: string[];// Files/modules affected
|
affected_components?: string[];// Files/modules affected
|
||||||
reproduction_steps?: string[]; // Steps to reproduce
|
reproduction_steps?: string[]; // Steps to reproduce
|
||||||
|
|
||||||
// Discovery context (when source='discovery')
|
// Extended context (minimal, for planning hints)
|
||||||
discovery_context?: {
|
extended_context?: {
|
||||||
discovery_id: string; // Source discovery session
|
location?: string; // file:line when specific line matters
|
||||||
perspective: string; // bug, test, quality, etc.
|
|
||||||
category: string; // Finding category
|
|
||||||
file: string; // Primary affected file
|
|
||||||
line: number; // Line number
|
|
||||||
snippet?: string; // Code snippet
|
|
||||||
confidence: number; // Agent confidence (0-1)
|
|
||||||
suggested_fix?: string; // Suggested remediation
|
suggested_fix?: string; // Suggested remediation
|
||||||
|
notes?: string; // Additional notes (user clarifications or discovery hints)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Closed-loop requirements (guide plan generation)
|
// Closed-loop requirements (guide plan generation)
|
||||||
@@ -290,6 +285,108 @@ const lifecycle = {
|
|||||||
issueData.lifecycle_requirements = lifecycle;
|
issueData.lifecycle_requirements = lifecycle;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Phase 4.5: Follow-up Questions (Intelligent Suggestions)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Analyze parsed data and suggest follow-up questions for missing/unclear fields
|
||||||
|
const suggestions = [];
|
||||||
|
|
||||||
|
// Check for missing critical fields
|
||||||
|
if (!issueData.expected_behavior) {
|
||||||
|
suggestions.push({
|
||||||
|
field: 'expected_behavior',
|
||||||
|
question: 'What is the expected behavior?',
|
||||||
|
hint: 'Describe what should happen when working correctly'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!issueData.actual_behavior && issueData.source !== 'discovery') {
|
||||||
|
suggestions.push({
|
||||||
|
field: 'actual_behavior',
|
||||||
|
question: 'What is the actual behavior?',
|
||||||
|
hint: 'Describe what currently happens (error message, wrong output, etc.)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!issueData.affected_components?.length) {
|
||||||
|
suggestions.push({
|
||||||
|
field: 'affected_components',
|
||||||
|
question: 'Which files or modules are affected?',
|
||||||
|
hint: 'e.g., src/auth/login.ts, src/api/users.ts'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!issueData.reproduction_steps?.length && issueData.source === 'text') {
|
||||||
|
suggestions.push({
|
||||||
|
field: 'reproduction_steps',
|
||||||
|
question: 'How can this issue be reproduced?',
|
||||||
|
hint: 'Step-by-step instructions to trigger the issue'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask follow-up questions if any suggestions exist
|
||||||
|
let userNotes = '';
|
||||||
|
if (suggestions.length > 0) {
|
||||||
|
console.log(`
|
||||||
|
## Suggested Clarifications
|
||||||
|
|
||||||
|
The following information would help with issue resolution:
|
||||||
|
${suggestions.map((s, i) => `${i+1}. **${s.question}** - ${s.hint}`).join('\n')}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const followUpAnswer = AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: 'Would you like to provide additional details?',
|
||||||
|
header: 'Clarify',
|
||||||
|
multiSelect: false,
|
||||||
|
options: [
|
||||||
|
{ label: 'Add details', description: 'Provide clarifications for suggested questions' },
|
||||||
|
{ label: 'Skip', description: 'Continue without additional details (Recommended)' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (followUpAnswer.includes('Add details')) {
|
||||||
|
// Collect additional notes via "Other" input
|
||||||
|
const notesAnswer = AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: 'Enter additional details (address any of the suggested questions):',
|
||||||
|
header: 'Details',
|
||||||
|
multiSelect: false,
|
||||||
|
options: [
|
||||||
|
{ label: 'Use template', description: 'Expected: ... | Actual: ... | Files: ...' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (notesAnswer.customText) {
|
||||||
|
userNotes = notesAnswer.customText;
|
||||||
|
|
||||||
|
// Parse structured input if provided
|
||||||
|
const expectedMatch = userNotes.match(/expected:\s*([^|]+)/i);
|
||||||
|
const actualMatch = userNotes.match(/actual:\s*([^|]+)/i);
|
||||||
|
const filesMatch = userNotes.match(/files?:\s*([^|]+)/i);
|
||||||
|
|
||||||
|
if (expectedMatch && !issueData.expected_behavior) {
|
||||||
|
issueData.expected_behavior = expectedMatch[1].trim();
|
||||||
|
}
|
||||||
|
if (actualMatch && !issueData.actual_behavior) {
|
||||||
|
issueData.actual_behavior = actualMatch[1].trim();
|
||||||
|
}
|
||||||
|
if (filesMatch && !issueData.affected_components?.length) {
|
||||||
|
issueData.affected_components = filesMatch[1].split(/[,\s]+/).filter(f => f.includes('/') || f.includes('.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store user notes in extended context
|
||||||
|
issueData.extended_context = {
|
||||||
|
...(issueData.extended_context || {}),
|
||||||
|
notes: userNotes || null
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### Phase 5: User Confirmation
|
### Phase 5: User Confirmation
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -377,6 +474,9 @@ const newIssue = {
|
|||||||
affected_components: issueData.affected_components || [],
|
affected_components: issueData.affected_components || [],
|
||||||
reproduction_steps: issueData.reproduction_steps || [],
|
reproduction_steps: issueData.reproduction_steps || [],
|
||||||
|
|
||||||
|
// Extended context (universal)
|
||||||
|
extended_context: issueData.extended_context || null,
|
||||||
|
|
||||||
// Closed-loop lifecycle requirements
|
// Closed-loop lifecycle requirements
|
||||||
lifecycle_requirements: issueData.lifecycle_requirements || {
|
lifecycle_requirements: issueData.lifecycle_requirements || {
|
||||||
test_strategy: 'auto',
|
test_strategy: 'auto',
|
||||||
@@ -395,9 +495,11 @@ const newIssue = {
|
|||||||
// Ensure directory exists
|
// Ensure directory exists
|
||||||
Bash('mkdir -p .workflow/issues');
|
Bash('mkdir -p .workflow/issues');
|
||||||
|
|
||||||
// Append to issues.jsonl
|
// Append to issues.jsonl with proper newline handling
|
||||||
const issuesPath = '.workflow/issues/issues.jsonl';
|
const issuesPath = '.workflow/issues/issues.jsonl';
|
||||||
Bash(`echo '${JSON.stringify(newIssue)}' >> "${issuesPath}"`);
|
const jsonLine = JSON.stringify(newIssue);
|
||||||
|
// Ensure file ends with newline before appending, then append with trailing newline
|
||||||
|
Bash(`[ -s "${issuesPath}" ] && [ -n "$(tail -c 1 "${issuesPath}")" ] && printf '\\n' >> "${issuesPath}"; printf '%s\\n' '${jsonLine}' >> "${issuesPath}"`);
|
||||||
|
|
||||||
console.log(`
|
console.log(`
|
||||||
## Issue Created
|
## Issue Created
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ ${issueList}
|
|||||||
### Steps
|
### Steps
|
||||||
1. Fetch: \`ccw issue status <id> --json\`
|
1. Fetch: \`ccw issue status <id> --json\`
|
||||||
2. Load project context (project-tech.json + project-guidelines.json)
|
2. Load project context (project-tech.json + project-guidelines.json)
|
||||||
3. **If source=discovery**: Use discovery_context (file, line, snippet, suggested_fix) as planning hints
|
3. **If extended_context exists**: Use extended_context (location, suggested_fix, notes) as planning hints
|
||||||
4. Explore (ACE) → Plan solution (respecting guidelines)
|
4. Explore (ACE) → Plan solution (respecting guidelines)
|
||||||
5. Register & bind: \`ccw issue bind <id> --solution <file>\`
|
5. Register & bind: \`ccw issue bind <id> --solution <file>\`
|
||||||
|
|
||||||
|
|||||||
@@ -42,43 +42,21 @@
|
|||||||
"items": { "type": "string" },
|
"items": { "type": "string" },
|
||||||
"description": "Issue labels/tags"
|
"description": "Issue labels/tags"
|
||||||
},
|
},
|
||||||
"discovery_context": {
|
"extended_context": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Enriched context from issue:discover (only when source=discovery)",
|
"description": "Minimal extended context for planning hints",
|
||||||
"properties": {
|
"properties": {
|
||||||
"discovery_id": {
|
"location": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Source discovery session ID"
|
"description": "file:line format (e.g., 'src/auth.ts:42')"
|
||||||
},
|
|
||||||
"perspective": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["bug", "ux", "test", "quality", "security", "performance", "maintainability", "best-practices"]
|
|
||||||
},
|
|
||||||
"category": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Finding category (e.g., edge-case, race-condition)"
|
|
||||||
},
|
|
||||||
"file": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Primary affected file"
|
|
||||||
},
|
|
||||||
"line": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Line number in primary file"
|
|
||||||
},
|
|
||||||
"snippet": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Code snippet showing the issue"
|
|
||||||
},
|
|
||||||
"confidence": {
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 1,
|
|
||||||
"description": "Agent confidence score"
|
|
||||||
},
|
},
|
||||||
"suggested_fix": {
|
"suggested_fix": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Suggested remediation from discovery"
|
"description": "Suggested remediation"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Additional notes (user clarifications or discovery hints)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -143,15 +121,10 @@
|
|||||||
"context": "Connection pool cleanup only happens when MAX_POOL_SIZE is reached...",
|
"context": "Connection pool cleanup only happens when MAX_POOL_SIZE is reached...",
|
||||||
"source": "discovery",
|
"source": "discovery",
|
||||||
"labels": ["bug", "resource-leak", "critical"],
|
"labels": ["bug", "resource-leak", "critical"],
|
||||||
"discovery_context": {
|
"extended_context": {
|
||||||
"discovery_id": "DSC-20251228-182237",
|
"location": "storage/sqlite_store.py:59",
|
||||||
"perspective": "bug",
|
"suggested_fix": "Implement periodic cleanup or weak references",
|
||||||
"category": "resource-leak",
|
"notes": null
|
||||||
"file": "storage/sqlite_store.py",
|
|
||||||
"line": 59,
|
|
||||||
"snippet": "if len(self._pool) >= self.MAX_POOL_SIZE:\n self._cleanup_stale_connections()",
|
|
||||||
"confidence": 0.85,
|
|
||||||
"suggested_fix": "Implement periodic cleanup or weak references"
|
|
||||||
},
|
},
|
||||||
"affected_components": ["storage/sqlite_store.py"],
|
"affected_components": ["storage/sqlite_store.py"],
|
||||||
"lifecycle_requirements": {
|
"lifecycle_requirements": {
|
||||||
|
|||||||
Reference in New Issue
Block a user