mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-25 19:48:33 +08:00
feat: standardize request_user_input schema across all codex skills and add config reminder
- Update all 68 .codex/skills files to use correct request_user_input schema (header, id, question, options with label/description) - Remove deprecated multiSelect, type, value, prompt fields - Add mandatory confirmation gates to planning-only skills - Add Codex config.toml reminder to ccw install CLI - Add Codex configuration section to README.md and README_CN.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: issue-discover
|
||||
description: Unified issue discovery and creation. Create issues from GitHub/text, discover issues via multi-perspective analysis, or prompt-driven iterative exploration. Triggers on "issue:new", "issue:discover", "issue:discover-by-prompt", "create issue", "discover issues", "find issues".
|
||||
allowed-tools: spawn_agent, wait, send_input, close_agent, AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep, mcp__ace-tool__search_context, mcp__exa__search
|
||||
allowed-tools: spawn_agent, wait, send_input, close_agent, request_user_input, Read, Write, Edit, Bash, Glob, Grep, mcp__ace-tool__search_context, mcp__exa__search
|
||||
---
|
||||
|
||||
# Issue Discover
|
||||
@@ -16,7 +16,7 @@ Unified issue discovery and creation skill covering three entry points: manual i
|
||||
│ → Action selection → Route to phase → Execute → Summary │
|
||||
└───────────────┬─────────────────────────────────────────────────┘
|
||||
│
|
||||
├─ ASK_USER: Select action
|
||||
├─ request_user_input: Select action
|
||||
│
|
||||
┌───────────┼───────────┬───────────┐
|
||||
↓ ↓ ↓ │
|
||||
@@ -50,7 +50,7 @@ Unified issue discovery and creation skill covering three entry points: manual i
|
||||
|
||||
## Key Design Principles
|
||||
|
||||
1. **Action-Driven Routing**: ASK_USER selects action, then load single phase
|
||||
1. **Action-Driven Routing**: request_user_input selects action, then load single phase
|
||||
2. **Progressive Phase Loading**: Only read the selected phase document
|
||||
3. **CLI-First Data Access**: All issue CRUD via `ccw issue` CLI commands
|
||||
4. **Auto Mode Support**: `-y` flag skips action selection with auto-detection
|
||||
@@ -101,7 +101,7 @@ Action Selection:
|
||||
│ ├─ Path pattern (src/**, *.ts) → Discover (Phase 2)
|
||||
│ ├─ Short text (< 80 chars) → Create New (Phase 1)
|
||||
│ └─ Long descriptive text (≥ 80 chars) → Discover by Prompt (Phase 3)
|
||||
└─ Otherwise → ASK_USER to select action
|
||||
└─ Otherwise → request_user_input to select action
|
||||
|
||||
Phase Execution (load one phase):
|
||||
├─ Phase 1: Create New → phases/01-issue-new.md
|
||||
@@ -168,33 +168,36 @@ function detectAction(input, flags) {
|
||||
}
|
||||
```
|
||||
|
||||
### Action Selection (ASK_USER)
|
||||
### Action Selection (request_user_input)
|
||||
|
||||
```javascript
|
||||
// When action cannot be auto-detected
|
||||
const answer = ASK_USER([{
|
||||
id: "action",
|
||||
type: "select",
|
||||
prompt: "What would you like to do?",
|
||||
options: [
|
||||
{
|
||||
label: "Create New Issue (Recommended)",
|
||||
description: "Create issue from GitHub URL, text description, or structured input"
|
||||
},
|
||||
{
|
||||
label: "Discover Issues",
|
||||
description: "Multi-perspective discovery: bug, security, test, quality, performance, etc."
|
||||
},
|
||||
{
|
||||
label: "Discover by Prompt",
|
||||
description: "Describe what to find — Gemini plans the exploration strategy iteratively"
|
||||
}
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
const answer = request_user_input({
|
||||
questions: [{
|
||||
header: "Action",
|
||||
id: "action",
|
||||
question: "What would you like to do?",
|
||||
options: [
|
||||
{
|
||||
label: "Create New Issue (Recommended)",
|
||||
description: "Create issue from GitHub URL, text description, or structured input"
|
||||
},
|
||||
{
|
||||
label: "Discover Issues",
|
||||
description: "Multi-perspective discovery: bug, security, test, quality, performance, etc."
|
||||
},
|
||||
{
|
||||
label: "Discover by Prompt",
|
||||
description: "Describe what to find — Gemini plans the exploration strategy iteratively"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
|
||||
// Route based on selection
|
||||
// answer.answers.action.answers[0] → selected label
|
||||
const actionMap = {
|
||||
"Create New Issue": "new",
|
||||
"Create New Issue (Recommended)": "new",
|
||||
"Discover Issues": "discover",
|
||||
"Discover by Prompt": "discover-by-prompt"
|
||||
};
|
||||
@@ -207,7 +210,7 @@ User Input (URL / text / path pattern / descriptive prompt)
|
||||
↓
|
||||
[Parse Flags + Auto-Detect Action]
|
||||
↓
|
||||
[Action Selection] ← ASK_USER (if needed)
|
||||
[Action Selection] ← request_user_input (if needed)
|
||||
↓
|
||||
[Read Selected Phase Document]
|
||||
↓
|
||||
@@ -305,7 +308,7 @@ close_agent({ id: agentId })
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No action detected | Show ASK_USER with all 3 options |
|
||||
| No action detected | Show request_user_input with all 3 options |
|
||||
| Invalid action type | Show available actions, re-prompt |
|
||||
| Phase execution fails | Report error, suggest manual intervention |
|
||||
| No files matched (discover) | Check target pattern, verify path exists |
|
||||
@@ -318,31 +321,35 @@ After successful phase execution, recommend next action:
|
||||
|
||||
```javascript
|
||||
// After Create New (issue created)
|
||||
ASK_USER([{
|
||||
id: "next_after_create",
|
||||
type: "select",
|
||||
prompt: "Issue created. What next?",
|
||||
options: [
|
||||
{ label: "Plan Solution", description: "Generate solution via issue-resolve" },
|
||||
{ label: "Create Another", description: "Create more issues" },
|
||||
{ label: "View Issues", description: "Review all issues" },
|
||||
{ label: "Done", description: "Exit workflow" }
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
request_user_input({
|
||||
questions: [{
|
||||
header: "Next Step",
|
||||
id: "next_after_create",
|
||||
question: "Issue created. What next?",
|
||||
options: [
|
||||
{ label: "Plan Solution (Recommended)", description: "Generate solution via issue-resolve" },
|
||||
{ label: "Create Another", description: "Create more issues" },
|
||||
{ label: "Done", description: "Exit workflow" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
// answer.answers.next_after_create.answers[0] → selected label
|
||||
|
||||
// After Discover / Discover by Prompt (discoveries generated)
|
||||
ASK_USER([{
|
||||
id: "next_after_discover",
|
||||
type: "select",
|
||||
prompt: `Discovery complete: ${findings.length} findings, ${executableFindings.length} executable. What next?`,
|
||||
options: [
|
||||
{ label: "Quick Plan & Execute (Recommended)", description: `Fix ${executableFindings.length} high-confidence findings directly` },
|
||||
{ label: "Export to Issues", description: "Convert discoveries to issues" },
|
||||
{ label: "Plan Solutions", description: "Plan solutions for exported issues via issue-resolve" },
|
||||
{ label: "Done", description: "Exit workflow" }
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
// If "Quick Plan & Execute" → Read phases/04-quick-execute.md, execute
|
||||
request_user_input({
|
||||
questions: [{
|
||||
header: "Next Step",
|
||||
id: "next_after_discover",
|
||||
question: `Discovery complete: ${findings.length} findings, ${executableFindings.length} executable. What next?`,
|
||||
options: [
|
||||
{ label: "Quick Plan & Execute (Recommended)", description: `Fix ${executableFindings.length} high-confidence findings directly` },
|
||||
{ label: "Export to Issues", description: "Convert discoveries to issues" },
|
||||
{ label: "Done", description: "Exit workflow" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
// answer.answers.next_after_discover.answers[0] → selected label
|
||||
// If "Quick Plan & Execute (Recommended)" → Read phases/04-quick-execute.md, execute
|
||||
```
|
||||
|
||||
## Related Skills & Commands
|
||||
|
||||
@@ -145,16 +145,23 @@ if (clarityScore >= 1 && clarityScore <= 2 && !issueData.affected_components?.le
|
||||
```javascript
|
||||
// ONLY ask questions if clarity is low
|
||||
if (clarityScore < 2 && (!issueData.context || issueData.context.length < 20)) {
|
||||
const answer = ASK_USER([{
|
||||
id: "clarify",
|
||||
type: "input",
|
||||
prompt: "Please describe the issue in more detail:",
|
||||
description: "Describe what, where, and expected behavior"
|
||||
}]); // BLOCKS (wait for user response)
|
||||
const answer = request_user_input({
|
||||
questions: [{
|
||||
header: "Clarify",
|
||||
id: "clarify",
|
||||
question: "Please describe the issue in more detail.",
|
||||
options: [
|
||||
{ label: "Provide Details", description: "Describe what, where, and expected behavior" },
|
||||
{ label: "Skip", description: "Create issue with current information" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
|
||||
if (answer.customText) {
|
||||
issueData.context = answer.customText;
|
||||
issueData.title = answer.customText.split(/[.\n]/)[0].substring(0, 60);
|
||||
const selection = answer.answers.clarify.answers[0];
|
||||
if (selection === "Provide Details") {
|
||||
// User provides details via follow-up
|
||||
issueData.context = selection;
|
||||
issueData.title = selection.split(/[.\n]/)[0].substring(0, 60);
|
||||
issueData.feedback = [{
|
||||
type: 'clarification',
|
||||
stage: 'new',
|
||||
@@ -228,7 +235,7 @@ Phase 2: Data Extraction (branched by clarity)
|
||||
│ Score 3 │ Score 1-2 │ Score 0 │
|
||||
│ GitHub │ Text + ACE │ Vague │
|
||||
├────────────┼─────────────────┼──────────────┤
|
||||
│ gh CLI │ Parse struct │ ASK_USER │
|
||||
│ gh CLI │ Parse struct │ request_user_input │
|
||||
│ → parse │ + quick hint │ (1 question) │
|
||||
│ │ (3 files max) │ → feedback │
|
||||
└────────────┴─────────────────┴──────────────┘
|
||||
|
||||
@@ -86,18 +86,20 @@ let selectedPerspectives = [];
|
||||
if (args.perspectives) {
|
||||
selectedPerspectives = args.perspectives.split(',').map(p => p.trim());
|
||||
} else {
|
||||
// Interactive selection via ASK_USER
|
||||
const response = ASK_USER([{
|
||||
id: "focus",
|
||||
type: "select",
|
||||
prompt: "Select primary discovery focus:",
|
||||
options: [
|
||||
{ label: "Bug + Test + Quality", description: "Quick scan: potential bugs, test gaps, code quality (Recommended)" },
|
||||
{ label: "Security + Performance", description: "System audit: security issues, performance bottlenecks" },
|
||||
{ label: "Maintainability + Best-practices", description: "Long-term health: coupling, tech debt, conventions" },
|
||||
{ label: "Full analysis", description: "All 8 perspectives (comprehensive, takes longer)" }
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
// Interactive selection via request_user_input
|
||||
const response = request_user_input({
|
||||
questions: [{
|
||||
header: "Focus",
|
||||
id: "focus",
|
||||
question: "Select primary discovery focus.",
|
||||
options: [
|
||||
{ label: "Bug + Test + Quality (Recommended)", description: "Quick scan: potential bugs, test gaps, code quality" },
|
||||
{ label: "Security + Performance", description: "System audit: security issues, performance bottlenecks" },
|
||||
{ label: "Full analysis", description: "All 8 perspectives (comprehensive, takes longer)" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
// response.answers.focus.answers[0] → selected label
|
||||
selectedPerspectives = parseSelectedPerspectives(response);
|
||||
}
|
||||
```
|
||||
@@ -271,20 +273,23 @@ await updateDiscoveryState(outputDir, {
|
||||
```javascript
|
||||
const hasHighPriority = issues.some(i => i.priority === 'critical' || i.priority === 'high');
|
||||
|
||||
await ASK_USER([{
|
||||
id: "next_step",
|
||||
type: "select",
|
||||
prompt: `Discovery complete: ${issues.length} issues generated, ${prioritizedFindings.length} total findings. What next?`,
|
||||
options: hasHighPriority ? [
|
||||
{ label: "Export to Issues (Recommended)", description: `${issues.length} high-priority issues found - export to tracker` },
|
||||
{ label: "Open Dashboard", description: "Review findings in ccw view before exporting" },
|
||||
{ label: "Skip", description: "Complete discovery without exporting" }
|
||||
] : [
|
||||
{ label: "Open Dashboard (Recommended)", description: "Review findings in ccw view to decide which to export" },
|
||||
{ label: "Export to Issues", description: `Export ${issues.length} issues to tracker` },
|
||||
{ label: "Skip", description: "Complete discovery without exporting" }
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
await request_user_input({
|
||||
questions: [{
|
||||
header: "Next Step",
|
||||
id: "next_step",
|
||||
question: `Discovery complete: ${issues.length} issues generated, ${prioritizedFindings.length} total findings. What next?`,
|
||||
options: hasHighPriority ? [
|
||||
{ label: "Export to Issues (Recommended)", description: `${issues.length} high-priority issues found - export to tracker` },
|
||||
{ label: "Open Dashboard", description: "Review findings in ccw view before exporting" },
|
||||
{ label: "Skip", description: "Complete discovery without exporting" }
|
||||
] : [
|
||||
{ label: "Open Dashboard (Recommended)", description: "Review findings in ccw view to decide which to export" },
|
||||
{ label: "Export to Issues", description: `Export ${issues.length} issues to tracker` },
|
||||
{ label: "Skip", description: "Complete discovery without exporting" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
// response.answers.next_step.answers[0] → selected label
|
||||
|
||||
if (response === "Export to Issues") {
|
||||
await appendJsonl(`${projectRoot}/.workflow/issues/issues.jsonl`, issues);
|
||||
|
||||
@@ -389,17 +389,19 @@ await updateDiscoveryState(outputDir, {
|
||||
});
|
||||
|
||||
// Prompt user for next action
|
||||
await ASK_USER([{
|
||||
id: "next_step",
|
||||
type: "select",
|
||||
prompt: `Discovery complete: ${issues.length} issues from ${cumulativeFindings.length} findings across ${iteration} iterations. What next?`,
|
||||
options: [
|
||||
{ label: "Export to Issues (Recommended)", description: `Export ${issues.length} issues for planning` },
|
||||
{ label: "Review Details", description: "View comparison analysis and iteration details" },
|
||||
{ label: "Run Deeper", description: "Continue with more iterations" },
|
||||
{ label: "Skip", description: "Complete without exporting" }
|
||||
]
|
||||
}]); // BLOCKS (wait for user response)
|
||||
await request_user_input({
|
||||
questions: [{
|
||||
header: "Next Step",
|
||||
id: "next_step",
|
||||
question: `Discovery complete: ${issues.length} issues from ${cumulativeFindings.length} findings across ${iteration} iterations. What next?`,
|
||||
options: [
|
||||
{ label: "Export to Issues (Recommended)", description: `Export ${issues.length} issues for planning` },
|
||||
{ label: "Review Details", description: "View comparison analysis and iteration details" },
|
||||
{ label: "Run Deeper", description: "Continue with more iterations" }
|
||||
]
|
||||
}]
|
||||
}); // BLOCKS (wait for user response)
|
||||
// answer.answers.next_step.answers[0] → selected label
|
||||
```
|
||||
|
||||
## Dimension Agent Prompt Template
|
||||
|
||||
@@ -44,7 +44,7 @@ executableFindings = allFindings.filter(f =>
|
||||
```
|
||||
|
||||
- 如果 0 个可执行 findings → 提示 "No executable findings (all below threshold)",建议用户走 "Export to Issues" 路径
|
||||
- 如果超过 10 个 findings → ASK_USER 确认是否全部执行或选择子集 (Auto mode: 全部执行)
|
||||
- 如果超过 10 个 findings → request_user_input 确认是否全部执行或选择子集 (Auto mode: 全部执行)
|
||||
|
||||
**同文件聚合**:
|
||||
|
||||
@@ -154,23 +154,26 @@ Quick Execute Summary:
|
||||
- File conflicts: {conflicts.length}
|
||||
```
|
||||
|
||||
ASK_USER:
|
||||
request_user_input:
|
||||
|
||||
```javascript
|
||||
ASK_USER([{
|
||||
id: "confirm_execute",
|
||||
type: "select",
|
||||
prompt: `${tasks.length} tasks ready. Start execution?`,
|
||||
options: [
|
||||
{ label: "Start Execution", description: "Execute all tasks" },
|
||||
{ label: "Adjust Filter", description: "Change confidence/priority threshold" },
|
||||
{ label: "Cancel", description: "Skip execution, return to post-phase options" }
|
||||
]
|
||||
}]);
|
||||
request_user_input({
|
||||
questions: [{
|
||||
header: "Confirm",
|
||||
id: "confirm_execute",
|
||||
question: `${tasks.length} tasks ready. Start execution?`,
|
||||
options: [
|
||||
{ label: "Start Execution (Recommended)", description: "Execute all tasks" },
|
||||
{ label: "Adjust Filter", description: "Change confidence/priority threshold" },
|
||||
{ label: "Cancel", description: "Skip execution, return to post-phase options" }
|
||||
]
|
||||
}]
|
||||
});
|
||||
// answer.answers.confirm_execute.answers[0] → selected label
|
||||
// Auto mode: Start Execution
|
||||
```
|
||||
|
||||
- "Adjust Filter" → 重新 ASK_USER 输入 confidence 和 priority 阈值,返回 Step 4.1
|
||||
- "Adjust Filter" → 重新 request_user_input 输入 confidence 和 priority 阈值,返回 Step 4.1
|
||||
- "Cancel" → 退出 Phase 4
|
||||
|
||||
### Step 4.5: Direct Inline Execution
|
||||
@@ -192,7 +195,7 @@ for each task in sortedTasks:
|
||||
6. Update .task/TASK-{id}.json _execution status
|
||||
7. If failed:
|
||||
- Auto mode: Skip & Continue
|
||||
- Interactive: ASK_USER → Retry / Skip / Abort
|
||||
- Interactive: request_user_input → Retry / Skip / Abort
|
||||
```
|
||||
|
||||
**可选 auto-commit**: 每个成功 task 后 `git add {files} && git commit -m "fix: {task.title}"`
|
||||
@@ -209,17 +212,19 @@ for each task in sortedTasks:
|
||||
// 计算未执行 findings
|
||||
const remainingFindings = allFindings.filter(f => !executedFindingIds.has(f.id))
|
||||
|
||||
ASK_USER([{
|
||||
id: "post_quick_execute",
|
||||
type: "select",
|
||||
prompt: `Quick Execute: ${completedCount}/${tasks.length} succeeded. ${remainingFindings.length} findings not executed.`,
|
||||
options: [
|
||||
{ label: "Retry Failed", description: `Re-execute ${failedCount} failed tasks` },
|
||||
{ label: "Export Remaining", description: `Export ${remainingFindings.length} remaining findings to issues` },
|
||||
{ label: "View Events", description: "Display execution-events.md" },
|
||||
{ label: "Done", description: "End workflow" }
|
||||
]
|
||||
}]);
|
||||
request_user_input({
|
||||
questions: [{
|
||||
header: "Post Execute",
|
||||
id: "post_quick_execute",
|
||||
question: `Quick Execute: ${completedCount}/${tasks.length} succeeded. ${remainingFindings.length} findings not executed.`,
|
||||
options: [
|
||||
{ label: "Done (Recommended)", description: "End workflow" },
|
||||
{ label: "Retry Failed", description: `Re-execute ${failedCount} failed tasks` },
|
||||
{ label: "Export Remaining", description: `Export ${remainingFindings.length} remaining findings to issues` }
|
||||
]
|
||||
}]
|
||||
});
|
||||
// answer.answers.post_quick_execute.answers[0] → selected label
|
||||
// Auto mode: Done
|
||||
```
|
||||
|
||||
@@ -231,11 +236,11 @@ ASK_USER([{
|
||||
|---------|---------|
|
||||
| 0 个可执行 findings | 提示 "No executable findings",建议 Export to Issues |
|
||||
| 只有 1 个 finding | 正常生成 1 个 TASK-001.json,简化确认对话 |
|
||||
| 超过 10 个 findings | ASK_USER 确认全部执行或选择子集 |
|
||||
| 超过 10 个 findings | request_user_input 确认全部执行或选择子集 |
|
||||
| finding 缺少 recommendation | criteria 退化为 "Review and fix {category} in {file}:{line}" |
|
||||
| finding 缺少 confidence | 默认 confidence=0.5,不满足过滤阈值 → 排除 |
|
||||
| discovery 输出不存在 | 报错 "No discoveries found. Run discover first." |
|
||||
| .task/ 目录已存在 | ASK_USER 追加 (TASK-{max+1}) 或覆盖 |
|
||||
| .task/ 目录已存在 | request_user_input 追加 (TASK-{max+1}) 或覆盖 |
|
||||
| 执行中文件被外部修改 | convergence verification 检测到差异,标记为 FAIL |
|
||||
| 所有 tasks 执行失败 | 建议 "Export to Issues → issue-resolve" 完整路径 |
|
||||
| finding 来自不同 perspective 但同文件 | 仍合并为一个 task,convergence.criteria 保留各自标准 |
|
||||
|
||||
Reference in New Issue
Block a user