mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: 添加GitHub回复任务,支持在问题存在github_url时自动评论
This commit is contained in:
@@ -138,7 +138,7 @@ Generate multiple candidate solutions when:
|
|||||||
**Task Decomposition** following schema:
|
**Task Decomposition** following schema:
|
||||||
```javascript
|
```javascript
|
||||||
function decomposeTasks(issue, exploration) {
|
function decomposeTasks(issue, exploration) {
|
||||||
return groups.map(group => ({
|
const tasks = groups.map(group => ({
|
||||||
id: `T${taskId++}`, // Pattern: ^T[0-9]+$
|
id: `T${taskId++}`, // Pattern: ^T[0-9]+$
|
||||||
title: group.title,
|
title: group.title,
|
||||||
scope: inferScope(group), // Module path
|
scope: inferScope(group), // Module path
|
||||||
@@ -161,7 +161,35 @@ function decomposeTasks(issue, exploration) {
|
|||||||
},
|
},
|
||||||
depends_on: inferDependencies(group, tasks),
|
depends_on: inferDependencies(group, tasks),
|
||||||
priority: calculatePriority(group) // 1-5 (1=highest)
|
priority: calculatePriority(group) // 1-5 (1=highest)
|
||||||
}))
|
}));
|
||||||
|
|
||||||
|
// GitHub Reply Task: Add final task if issue has github_url
|
||||||
|
if (issue.github_url || issue.github_number) {
|
||||||
|
const lastTaskId = tasks[tasks.length - 1]?.id;
|
||||||
|
tasks.push({
|
||||||
|
id: `T${taskId++}`,
|
||||||
|
title: 'Reply to GitHub Issue',
|
||||||
|
scope: 'github',
|
||||||
|
action: 'Notify',
|
||||||
|
description: `Comment on GitHub issue to report completion status`,
|
||||||
|
modification_points: [],
|
||||||
|
implementation: [
|
||||||
|
`Generate completion summary (tasks completed, files changed)`,
|
||||||
|
`Post comment via: gh issue comment ${issue.github_number || extractNumber(issue.github_url)} --body "..."`,
|
||||||
|
`Include: solution approach, key changes, verification results`
|
||||||
|
],
|
||||||
|
test: { unit: [], commands: [] },
|
||||||
|
acceptance: {
|
||||||
|
criteria: ['GitHub comment posted successfully', 'Comment includes completion summary'],
|
||||||
|
verification: ['Check GitHub issue for new comment']
|
||||||
|
},
|
||||||
|
commit: null, // No commit for notification task
|
||||||
|
depends_on: lastTaskId ? [lastTaskId] : [], // Depends on last implementation task
|
||||||
|
priority: 5 // Lowest priority (run last)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return tasks;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -284,6 +312,7 @@ Each line is a solution JSON containing tasks. Schema: `cat .claude/workflows/cl
|
|||||||
7. Write solutions to `.workflow/issues/solutions/{issue-id}.jsonl` (append mode)
|
7. Write solutions to `.workflow/issues/solutions/{issue-id}.jsonl` (append mode)
|
||||||
8. For HIGH complexity: generate 2-3 candidate solutions
|
8. For HIGH complexity: generate 2-3 candidate solutions
|
||||||
9. **Solution ID format**: `SOL-{issue-id}-{N}` (e.g., `SOL-GH-123-1`, `SOL-GH-123-2`)
|
9. **Solution ID format**: `SOL-{issue-id}-{N}` (e.g., `SOL-GH-123-1`, `SOL-GH-123-2`)
|
||||||
|
10. **GitHub Reply Task**: If issue has `github_url` or `github_number`, add final task to comment on GitHub issue with completion summary
|
||||||
|
|
||||||
**CONFLICT AVOIDANCE** (for batch processing of similar issues):
|
**CONFLICT AVOIDANCE** (for batch processing of similar issues):
|
||||||
1. **File isolation**: Each issue's solution should target distinct files when possible
|
1. **File isolation**: Each issue's solution should target distinct files when possible
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ interface Issue {
|
|||||||
source_url?: string;
|
source_url?: string;
|
||||||
labels?: string[];
|
labels?: string[];
|
||||||
|
|
||||||
|
// GitHub binding (for non-GitHub sources that publish to GitHub)
|
||||||
|
github_url?: string; // https://github.com/owner/repo/issues/123
|
||||||
|
github_number?: number; // 123
|
||||||
|
|
||||||
// Optional structured fields
|
// Optional structured fields
|
||||||
expected_behavior?: string;
|
expected_behavior?: string;
|
||||||
actual_behavior?: string;
|
actual_behavior?: string;
|
||||||
@@ -165,7 +169,30 @@ if (clarityScore < 2 && (!issueData.context || issueData.context.length < 20)) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 5: Create Issue
|
### Phase 5: GitHub Publishing Decision (Non-GitHub Sources)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// For non-GitHub sources, ask if user wants to publish to GitHub
|
||||||
|
let publishToGitHub = false;
|
||||||
|
|
||||||
|
if (issueData.source !== 'github') {
|
||||||
|
const publishAnswer = AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: 'Would you like to publish this issue to GitHub?',
|
||||||
|
header: 'Publish',
|
||||||
|
multiSelect: false,
|
||||||
|
options: [
|
||||||
|
{ label: 'Yes, publish to GitHub', description: 'Create issue on GitHub and link it' },
|
||||||
|
{ label: 'No, keep local only', description: 'Store as local issue without GitHub sync' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
publishToGitHub = publishAnswer.answers?.['Publish']?.includes('Yes');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 6: Create Issue
|
||||||
|
|
||||||
**Summary Display:**
|
**Summary Display:**
|
||||||
- Show ID, title, source, affected files (if any)
|
- Show ID, title, source, affected files (if any)
|
||||||
@@ -220,8 +247,64 @@ EOF
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**GitHub Publishing** (if user opted in):
|
||||||
|
```javascript
|
||||||
|
// Step 1: Create local issue FIRST
|
||||||
|
const localIssue = createLocalIssue(issueData); // ccw issue create
|
||||||
|
|
||||||
|
// Step 2: Publish to GitHub if requested
|
||||||
|
if (publishToGitHub) {
|
||||||
|
const ghResult = Bash(`gh issue create --title "${issueData.title}" --body "${issueData.context}"`);
|
||||||
|
// Parse GitHub URL from output
|
||||||
|
const ghUrl = ghResult.match(/https:\/\/github\.com\/[\w-]+\/[\w-]+\/issues\/\d+/)?.[0];
|
||||||
|
const ghNumber = parseInt(ghUrl?.match(/\/issues\/(\d+)/)?.[1]);
|
||||||
|
|
||||||
|
if (ghNumber) {
|
||||||
|
// Step 3: Update local issue with GitHub binding
|
||||||
|
Bash(`ccw issue update ${localIssue.id} --github-url "${ghUrl}" --github-number ${ghNumber}`);
|
||||||
|
// Or via pipe:
|
||||||
|
// echo '{"github_url":"${ghUrl}","github_number":${ghNumber}}' | ccw issue update ${localIssue.id}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Workflow:**
|
||||||
|
```
|
||||||
|
1. Create local issue (ISS-YYYYMMDD-NNN) → stored in .workflow/issues.jsonl
|
||||||
|
2. If publishToGitHub:
|
||||||
|
a. gh issue create → returns GitHub URL
|
||||||
|
b. Update local issue with github_url + github_number binding
|
||||||
|
3. Both local and GitHub issues exist, linked together
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example with GitHub Publishing:**
|
||||||
|
```bash
|
||||||
|
# User creates text issue
|
||||||
|
/issue:new "Login fails with special chars. Expected: success. Actual: 500"
|
||||||
|
|
||||||
|
# System asks: "Would you like to publish this issue to GitHub?"
|
||||||
|
# User selects: "Yes, publish to GitHub"
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ✓ Local issue created: ISS-20251229-001
|
||||||
|
# ✓ Published to GitHub: https://github.com/org/repo/issues/123
|
||||||
|
# ✓ GitHub binding saved to local issue
|
||||||
|
# → Next step: /issue:plan ISS-20251229-001
|
||||||
|
|
||||||
|
# Resulting issue JSON:
|
||||||
|
{
|
||||||
|
"id": "ISS-20251229-001",
|
||||||
|
"title": "Login fails with special chars",
|
||||||
|
"source": "text",
|
||||||
|
"github_url": "https://github.com/org/repo/issues/123",
|
||||||
|
"github_number": 123,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
**Completion:**
|
**Completion:**
|
||||||
- Display created issue ID
|
- Display created issue ID
|
||||||
|
- Show GitHub URL (if published)
|
||||||
- Show next step: `/issue:plan <id>`
|
- Show next step: `/issue:plan <id>`
|
||||||
|
|
||||||
## Execution Flow
|
## Execution Flow
|
||||||
@@ -240,9 +323,16 @@ Phase 2: Data Extraction (branched by clarity)
|
|||||||
│ │ (3 files max) │ → feedback │
|
│ │ (3 files max) │ → feedback │
|
||||||
└────────────┴─────────────────┴──────────────┘
|
└────────────┴─────────────────┴──────────────┘
|
||||||
|
|
||||||
Phase 3: Create Issue
|
Phase 3: GitHub Publishing Decision (non-GitHub only)
|
||||||
|
├─ Source = github: Skip (already from GitHub)
|
||||||
|
└─ Source ≠ github: AskUserQuestion
|
||||||
|
├─ Yes → publishToGitHub = true
|
||||||
|
└─ No → publishToGitHub = false
|
||||||
|
|
||||||
|
Phase 4: Create Issue
|
||||||
├─ Score ≥ 2: Direct creation
|
├─ Score ≥ 2: Direct creation
|
||||||
└─ Score < 2: Confirm first → Create
|
└─ Score < 2: Confirm first → Create
|
||||||
|
└─ If publishToGitHub: gh issue create → link URL
|
||||||
|
|
||||||
Note: Deep exploration & lifecycle deferred to /issue:plan
|
Note: Deep exploration & lifecycle deferred to /issue:plan
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -198,8 +198,9 @@ ${issueList}
|
|||||||
2. Load project context files
|
2. Load project context files
|
||||||
3. Explore codebase (ACE semantic search)
|
3. Explore codebase (ACE semantic search)
|
||||||
4. Plan solution with tasks (schema: solution-schema.json)
|
4. Plan solution with tasks (schema: solution-schema.json)
|
||||||
5. Write solution to: .workflow/issues/solutions/{issue-id}.jsonl
|
5. **If github_url exists**: Add final task to comment on GitHub issue
|
||||||
6. Single solution → auto-bind; Multiple → return for selection
|
6. Write solution to: .workflow/issues/solutions/{issue-id}.jsonl
|
||||||
|
7. Single solution → auto-bind; Multiple → return for selection
|
||||||
|
|
||||||
### Rules
|
### Rules
|
||||||
- Solution ID format: SOL-{issue-id}-{seq}
|
- Solution ID format: SOL-{issue-id}-{seq}
|
||||||
|
|||||||
Reference in New Issue
Block a user