mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
refactor(issue): enhance documentation and add core guidelines for data access
This commit is contained in:
@@ -16,7 +16,7 @@ Clear Input (GitHub URL, structured text) → Direct creation
|
|||||||
Unclear Input (vague description) → Minimal clarifying questions
|
Unclear Input (vague description) → Minimal clarifying questions
|
||||||
```
|
```
|
||||||
|
|
||||||
## Issue Structure (Simplified)
|
## Issue Structure
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface Issue {
|
interface Issue {
|
||||||
|
|||||||
@@ -16,15 +16,37 @@ Unified planning command using **issue-plan-agent** that combines exploration an
|
|||||||
- Multiple solutions → return for user selection
|
- Multiple solutions → return for user selection
|
||||||
- Agent handles file generation
|
- Agent handles file generation
|
||||||
|
|
||||||
|
## Core Guidelines
|
||||||
|
|
||||||
|
**⚠️ Data Access Principle**: Issues and solutions files can grow very large. To avoid context overflow:
|
||||||
|
|
||||||
|
| Operation | Correct | Incorrect |
|
||||||
|
|-----------|---------|-----------|
|
||||||
|
| List issues (brief) | `ccw issue list --status pending --brief` | `Read('issues.jsonl')` |
|
||||||
|
| Read issue details | `ccw issue status <id> --json` | `Read('issues.jsonl')` |
|
||||||
|
| Update status | `ccw issue update <id> --status ...` | Direct file edit |
|
||||||
|
| Bind solution | `ccw issue bind <id> <sol-id>` | Direct file edit |
|
||||||
|
|
||||||
|
**Output Options**:
|
||||||
|
- `--brief`: JSON with minimal fields (id, title, status, priority, tags)
|
||||||
|
- `--json`: Full JSON (agent use only)
|
||||||
|
|
||||||
|
**Orchestration vs Execution**:
|
||||||
|
- **Command (orchestrator)**: Use `--brief` for minimal context
|
||||||
|
- **Agent (executor)**: Fetch full details → `ccw issue status <id> --json`
|
||||||
|
|
||||||
|
**ALWAYS** use CLI commands for CRUD operations. **NEVER** read entire `issues.jsonl` or `solutions/*.jsonl` directly.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/issue:plan <issue-id>[,<issue-id>,...] [FLAGS]
|
/issue:plan [<issue-id>[,<issue-id>,...]] [FLAGS]
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
/issue:plan # Default: --all-pending
|
||||||
/issue:plan GH-123 # Single issue
|
/issue:plan GH-123 # Single issue
|
||||||
/issue:plan GH-123,GH-124,GH-125 # Batch (up to 3)
|
/issue:plan GH-123,GH-124,GH-125 # Batch (up to 3)
|
||||||
/issue:plan --all-pending # All pending issues
|
/issue:plan --all-pending # All pending issues (explicit)
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
--batch-size <n> Max issues per agent batch (default: 3)
|
--batch-size <n> Max issues per agent batch (default: 3)
|
||||||
@@ -62,14 +84,17 @@ Phase 4: Summary
|
|||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
|
|
||||||
### Phase 1: Issue Loading (ID + Title + Tags)
|
### Phase 1: Issue Loading (Brief Info Only)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const batchSize = flags.batchSize || 3;
|
const batchSize = flags.batchSize || 3;
|
||||||
let issues = []; // {id, title, tags}
|
let issues = []; // {id, title, tags} - brief info for grouping only
|
||||||
|
|
||||||
if (flags.allPending) {
|
// Default to --all-pending if no input provided
|
||||||
// Get pending issues with metadata via CLI (JSON output)
|
const useAllPending = flags.allPending || !userInput || userInput.trim() === '';
|
||||||
|
|
||||||
|
if (useAllPending) {
|
||||||
|
// Get pending issues with brief metadata via CLI
|
||||||
const result = Bash(`ccw issue list --status pending,registered --json`).trim();
|
const result = Bash(`ccw issue list --status pending,registered --json`).trim();
|
||||||
const parsed = result ? JSON.parse(result) : [];
|
const parsed = result ? JSON.parse(result) : [];
|
||||||
issues = parsed.map(i => ({ id: i.id, title: i.title || '', tags: i.tags || [] }));
|
issues = parsed.map(i => ({ id: i.id, title: i.title || '', tags: i.tags || [] }));
|
||||||
@@ -80,7 +105,7 @@ if (flags.allPending) {
|
|||||||
}
|
}
|
||||||
console.log(`Found ${issues.length} pending issues`);
|
console.log(`Found ${issues.length} pending issues`);
|
||||||
} else {
|
} else {
|
||||||
// Parse comma-separated issue IDs, fetch metadata
|
// Parse comma-separated issue IDs, fetch brief metadata
|
||||||
const ids = userInput.includes(',')
|
const ids = userInput.includes(',')
|
||||||
? userInput.split(',').map(s => s.trim())
|
? userInput.split(',').map(s => s.trim())
|
||||||
: [userInput.trim()];
|
: [userInput.trim()];
|
||||||
@@ -92,6 +117,7 @@ if (flags.allPending) {
|
|||||||
issues.push({ id, title: parsed.title || '', tags: parsed.tags || [] });
|
issues.push({ id, title: parsed.title || '', tags: parsed.tags || [] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Note: Agent fetches full issue content via `ccw issue status <id> --json`
|
||||||
|
|
||||||
// Semantic grouping via Gemini CLI (max 4 issues per group)
|
// Semantic grouping via Gemini CLI (max 4 issues per group)
|
||||||
async function groupBySimilarityGemini(issues) {
|
async function groupBySimilarityGemini(issues) {
|
||||||
@@ -172,7 +198,7 @@ ${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. Create solution: ccw issue solution <issue-id> --data '{...}'
|
5. Write solution to: .workflow/issues/solutions/{issue-id}.jsonl
|
||||||
6. Single solution → auto-bind; Multiple → return for selection
|
6. Single solution → auto-bind; Multiple → return for selection
|
||||||
|
|
||||||
### Rules
|
### Rules
|
||||||
@@ -258,8 +284,8 @@ for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Count planned issues via CLI
|
// Count planned issues via CLI
|
||||||
const plannedIds = Bash(`ccw issue list --status planned --ids`).trim();
|
const planned = JSON.parse(Bash(`ccw issue list --status planned --brief`) || '[]');
|
||||||
const plannedCount = plannedIds ? plannedIds.split('\n').length : 0;
|
const plannedCount = planned.length;
|
||||||
|
|
||||||
console.log(`
|
console.log(`
|
||||||
## Done: ${issues.length} issues → ${plannedCount} planned
|
## Done: ${issues.length} issues → ${plannedCount} planned
|
||||||
|
|||||||
@@ -21,6 +21,29 @@ Queue formation command using **issue-queue-agent** that analyzes all bound solu
|
|||||||
- Semantic priority calculation per solution (0.0-1.0)
|
- Semantic priority calculation per solution (0.0-1.0)
|
||||||
- Parallel/Sequential group assignment for solutions
|
- Parallel/Sequential group assignment for solutions
|
||||||
|
|
||||||
|
## Core Guidelines
|
||||||
|
|
||||||
|
**⚠️ Data Access Principle**: Issues and queue files can grow very large. To avoid context overflow:
|
||||||
|
|
||||||
|
| Operation | Correct | Incorrect |
|
||||||
|
|-----------|---------|-----------|
|
||||||
|
| List issues (brief) | `ccw issue list --status planned --brief` | `Read('issues.jsonl')` |
|
||||||
|
| List queue (brief) | `ccw issue queue --brief` | `Read('queues/*.json')` |
|
||||||
|
| Read issue details | `ccw issue status <id> --json` | `Read('issues.jsonl')` |
|
||||||
|
| Get next item | `ccw issue next --json` | `Read('queues/*.json')` |
|
||||||
|
| Update status | `ccw issue update <id> --status ...` | Direct file edit |
|
||||||
|
| Sync from queue | `ccw issue update --from-queue` | Direct file edit |
|
||||||
|
|
||||||
|
**Output Options**:
|
||||||
|
- `--brief`: JSON with minimal fields (id, status, counts)
|
||||||
|
- `--json`: Full JSON (agent use only)
|
||||||
|
|
||||||
|
**Orchestration vs Execution**:
|
||||||
|
- **Command (orchestrator)**: Use `--brief` for minimal context
|
||||||
|
- **Agent (executor)**: Fetch full details → `ccw issue status <id> --json`
|
||||||
|
|
||||||
|
**ALWAYS** use CLI commands for CRUD operations. **NEVER** read entire `issues.jsonl` or `queues/*.json` directly.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -203,15 +226,20 @@ if (result.clarifications?.length > 0) {
|
|||||||
|
|
||||||
### Phase 6: Status Update & Summary
|
### Phase 6: Status Update & Summary
|
||||||
|
|
||||||
**Status Update** (single command):
|
**Status Update** (MUST use CLI command, NOT direct file operations):
|
||||||
```bash
|
|
||||||
ccw issue update --from-queue [queue-id] --json
|
|
||||||
|
|
||||||
# Examples
|
```bash
|
||||||
|
# Option 1: Batch update from queue (recommended)
|
||||||
|
ccw issue update --from-queue [queue-id] --json
|
||||||
ccw issue update --from-queue --json # Use active queue
|
ccw issue update --from-queue --json # Use active queue
|
||||||
ccw issue update --from-queue QUE-xxx --json # Use specific queue
|
ccw issue update --from-queue QUE-xxx --json # Use specific queue
|
||||||
|
|
||||||
|
# Option 2: Individual issue update
|
||||||
|
ccw issue update <issue-id> --status queued
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**⚠️ IMPORTANT**: Do NOT directly modify `issues.jsonl`. Always use CLI command to ensure proper validation and history tracking.
|
||||||
|
|
||||||
**Output** (JSON):
|
**Output** (JSON):
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ export function run(argv: string[]): void {
|
|||||||
.option('--priority <n>', 'Task priority (1-5)')
|
.option('--priority <n>', 'Task priority (1-5)')
|
||||||
.option('--format <fmt>', 'Output format: json, markdown')
|
.option('--format <fmt>', 'Output format: json, markdown')
|
||||||
.option('--json', 'Output as JSON')
|
.option('--json', 'Output as JSON')
|
||||||
.option('--ids', 'List only IDs (one per line, for scripting)')
|
.option('--brief', 'Brief JSON output (minimal fields)')
|
||||||
.option('--force', 'Force operation')
|
.option('--force', 'Force operation')
|
||||||
// New options for solution/queue management
|
// New options for solution/queue management
|
||||||
.option('--solution <path>', 'Solution JSON file path')
|
.option('--solution <path>', 'Solution JSON file path')
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ interface IssueOptions {
|
|||||||
json?: boolean;
|
json?: boolean;
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
fail?: boolean;
|
fail?: boolean;
|
||||||
ids?: boolean; // List only IDs (one per line)
|
brief?: boolean; // List brief info only (id, title, status, priority, tags) - JSON format
|
||||||
data?: string; // JSON data for create
|
data?: string; // JSON data for create
|
||||||
fromQueue?: boolean | string; // Sync statuses from queue (true=active, string=specific queue ID)
|
fromQueue?: boolean | string; // Sync statuses from queue (true=active, string=specific queue ID)
|
||||||
}
|
}
|
||||||
@@ -714,9 +714,17 @@ async function listAction(issueId: string | undefined, options: IssueOptions): P
|
|||||||
issues = issues.filter(i => statuses.includes(i.status));
|
issues = issues.filter(i => statuses.includes(i.status));
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDs only mode (one per line, for scripting)
|
// Brief mode: minimal fields only (id, title, status, priority, tags, bound_solution_id)
|
||||||
if (options.ids) {
|
if (options.brief) {
|
||||||
issues.forEach(i => console.log(i.id));
|
const briefIssues = issues.map(i => ({
|
||||||
|
id: i.id,
|
||||||
|
title: i.title,
|
||||||
|
status: i.status,
|
||||||
|
priority: i.priority,
|
||||||
|
tags: i.tags || [],
|
||||||
|
bound_solution_id: i.bound_solution_id
|
||||||
|
}));
|
||||||
|
console.log(JSON.stringify(briefIssues, null, 2));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,6 +1224,22 @@ async function queueAction(subAction: string | undefined, issueId: string | unde
|
|||||||
if (subAction === 'list' || subAction === 'history') {
|
if (subAction === 'list' || subAction === 'history') {
|
||||||
const index = readQueueIndex();
|
const index = readQueueIndex();
|
||||||
|
|
||||||
|
// Brief mode: minimal queue index info
|
||||||
|
if (options.brief) {
|
||||||
|
const briefIndex = {
|
||||||
|
active_queue_id: index.active_queue_id,
|
||||||
|
queues: index.queues.map(q => ({
|
||||||
|
id: q.id,
|
||||||
|
status: q.status,
|
||||||
|
issue_ids: q.issue_ids,
|
||||||
|
total_solutions: q.total_solutions,
|
||||||
|
completed_solutions: q.completed_solutions
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(briefIndex, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
console.log(JSON.stringify(index, null, 2));
|
console.log(JSON.stringify(index, null, 2));
|
||||||
return;
|
return;
|
||||||
@@ -1525,6 +1549,28 @@ async function queueAction(subAction: string | undefined, issueId: string | unde
|
|||||||
// Show current queue
|
// Show current queue
|
||||||
const queue = readActiveQueue();
|
const queue = readActiveQueue();
|
||||||
|
|
||||||
|
// Brief mode: minimal queue info (id, issue_ids, item summaries)
|
||||||
|
if (options.brief) {
|
||||||
|
const items = queue.solutions || queue.tasks || [];
|
||||||
|
const briefQueue = {
|
||||||
|
id: queue.id,
|
||||||
|
issue_ids: queue.issue_ids || [],
|
||||||
|
total: items.length,
|
||||||
|
pending: items.filter(i => i.status === 'pending').length,
|
||||||
|
executing: items.filter(i => i.status === 'executing').length,
|
||||||
|
completed: items.filter(i => i.status === 'completed').length,
|
||||||
|
items: items.map(i => ({
|
||||||
|
item_id: i.item_id,
|
||||||
|
issue_id: i.issue_id,
|
||||||
|
solution_id: i.solution_id,
|
||||||
|
status: i.status,
|
||||||
|
task_count: i.task_count
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(briefQueue, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
console.log(JSON.stringify(queue, null, 2));
|
console.log(JSON.stringify(queue, null, 2));
|
||||||
return;
|
return;
|
||||||
@@ -1960,7 +2006,7 @@ export async function issueCommand(
|
|||||||
console.log(chalk.bold('Options:'));
|
console.log(chalk.bold('Options:'));
|
||||||
console.log(chalk.gray(' --title <title> Issue/task title'));
|
console.log(chalk.gray(' --title <title> Issue/task title'));
|
||||||
console.log(chalk.gray(' --status <status> Filter by status (comma-separated)'));
|
console.log(chalk.gray(' --status <status> Filter by status (comma-separated)'));
|
||||||
console.log(chalk.gray(' --ids List only IDs (one per line)'));
|
console.log(chalk.gray(' --brief Brief JSON output (minimal fields)'));
|
||||||
console.log(chalk.gray(' --solution <path> Solution JSON file'));
|
console.log(chalk.gray(' --solution <path> Solution JSON file'));
|
||||||
console.log(chalk.gray(' --result <json> Execution result'));
|
console.log(chalk.gray(' --result <json> Execution result'));
|
||||||
console.log(chalk.gray(' --reason <text> Failure reason'));
|
console.log(chalk.gray(' --reason <text> Failure reason'));
|
||||||
|
|||||||
Reference in New Issue
Block a user