Add coverage prettification and sorting functionality

- Introduced `prettify.css` for syntax highlighting in coverage reports.
- Added `prettify.js` to handle code formatting and highlighting.
- Included `sort-arrow-sprite.png` for sort indicators in the coverage table.
- Implemented `sorter.js` to enable sorting and filtering of coverage summary tables.
- Added a search box for filtering table rows based on user input.
This commit is contained in:
catlog22
2026-02-07 22:21:05 +08:00
parent 6073627ff2
commit ece02ab32a
40 changed files with 2828 additions and 728 deletions

View File

@@ -459,7 +459,7 @@ Display current understanding and exploration findings to the user.
- Open questions or areas needing clarification
- Available action options
**User Feedback Options** (AskUserQuestion - single select):
**User Feedback Options** (ASK_USER - single select):
| Option | Purpose | Next Action |
|--------|---------|------------|
@@ -543,7 +543,7 @@ close_agent({ id: deepeningAgent })
When user indicates a different focus is needed, spawn new agent with adjusted perspective.
**Direction Adjustment Process**:
1. Ask user for adjusted focus area (through AskUserQuestion)
1. Ask user for adjusted focus area (via ASK_USER)
2. Spawn new agent with different dimension/perspective
3. Compare new insights with prior analysis
4. Identify what was missed and why
@@ -592,10 +592,11 @@ When user has specific questions, address them directly.
```javascript
// Capture user questions first
const userQuestions = await AskUserQuestion({
question: "What specific questions do you have?",
const userQuestions = ASK_USER([{
id: "user_questions", type: "input",
prompt: "What specific questions do you have?",
options: [/* predefined + custom */]
})
}]) // BLOCKS (wait for user response)
// Send questions to active agent
send_input({
@@ -759,7 +760,7 @@ Append conclusions section and finalize the understanding document.
Offer user follow-up actions based on analysis results.
**Available Options** (AskUserQuestion - multi-select):
**Available Options** (ASK_USER - multi-select):
| Option | Purpose | Action |
|--------|---------|--------|

View File

@@ -182,14 +182,11 @@ ${synthesis.top_ideas.map((idea, i) =>
})
}
const selection = AskUser({
questions: [{
question: "Which idea should be developed?",
header: "Idea",
multiSelect: false,
options: ideaOptions
}]
})
const selection = ASK_USER([{
id: "idea", type: "select",
prompt: "Which idea should be developed?",
options: ideaOptions
}]) // BLOCKS (wait for user response)
// Parse selection
if (selection.idea === "Primary Recommendation") {
@@ -292,17 +289,14 @@ Write(`${sessionFolder}/cycle-task.md`, `# Generated Task\n\n**Generated**: ${ge
let shouldLaunch = isAutoMode
if (!isAutoMode) {
const confirmation = AskUser({
questions: [{
question: "Launch parallel-dev-cycle with this task?",
header: "Launch",
multiSelect: false,
options: [
{ label: "Yes, launch cycle (Recommended)", description: "Start parallel-dev-cycle with enriched task" },
{ label: "No, just save task", description: "Save formatted task for manual use" }
]
}]
})
const confirmation = ASK_USER([{
id: "launch", type: "select",
prompt: "Launch parallel-dev-cycle with this task?",
options: [
{ label: "Yes, launch cycle (Recommended)", description: "Start parallel-dev-cycle with enriched task" },
{ label: "No, just save task", description: "Save formatted task for manual use" }
]
}]) // BLOCKS (wait for user response)
shouldLaunch = confirmation.launch.includes("Yes")
}

View File

@@ -412,20 +412,17 @@ async function showMenuAndGetChoice(state) {
const pendingCount = ss?.pending_tasks?.length || 0
const completedCount = ss?.completed_tasks?.length || 0
const response = await AskUserQuestion({
questions: [{
question: `Select next action (completed: ${completedCount}, pending: ${pendingCount}):`,
header: "Action",
multiSelect: false,
options: [
{ label: "develop", description: `Continue development (${pendingCount} pending)` },
{ label: "debug", description: "Start debugging / diagnosis" },
{ label: "validate", description: "Run tests and validation" },
{ label: "complete", description: "Complete loop and generate summary" },
{ label: "exit", description: "Exit and save progress" }
]
}]
})
const response = await ASK_USER([{
id: "Action", type: "select",
prompt: `Select next action (completed: ${completedCount}, pending: ${pendingCount}):`,
options: [
{ label: "develop", description: `Continue development (${pendingCount} pending)` },
{ label: "debug", description: "Start debugging / diagnosis" },
{ label: "validate", description: "Run tests and validation" },
{ label: "complete", description: "Complete loop and generate summary" },
{ label: "exit", description: "Exit and save progress" }
]
}]) // BLOCKS (wait for user response)
return response["Action"]
}

View File

@@ -274,20 +274,17 @@ async function displayMenuAndGetChoice(actionResult) {
console.log('\n' + menuMatch[1])
}
const response = await AskUserQuestion({
questions: [{
question: "Select next action:",
header: "Action",
multiSelect: false,
options: [
{ label: "develop", description: "Continue development" },
{ label: "debug", description: "Start debugging" },
{ label: "validate", description: "Run validation" },
{ label: "complete", description: "Complete loop" },
{ label: "exit", description: "Exit and save" }
]
}]
})
const response = await ASK_USER([{
id: "Action", type: "select",
prompt: "Select next action:",
options: [
{ label: "develop", description: "Continue development" },
{ label: "debug", description: "Start debugging" },
{ label: "validate", description: "Run validation" },
{ label: "complete", description: "Complete loop" },
{ label: "exit", description: "Exit and save" }
]
}]) // BLOCKS (wait for user response)
return { action: response["Action"] }
}

View File

@@ -44,7 +44,7 @@ Phase 2: Drift Discovery (Subagent)
Phase 3: Confirmation
├─ Validate manifest schema
├─ Display cleanup summary by category
├─ AskUser: Select categories and risk level
├─ ASK_USER: Select categories and risk level
└─ Dry-run exit if --dry-run
Phase 4: Execution
@@ -241,29 +241,26 @@ Manifest: ${sessionFolder}/cleanup-manifest.json
}
// User confirmation
const selection = AskUser({
questions: [
{
question: "Which categories to clean?",
header: "Categories",
multiSelect: true,
options: [
{ label: "Sessions", description: `${manifest.summary.by_category.stale_sessions} stale sessions` },
{ label: "Documents", description: `${manifest.summary.by_category.drifted_documents} drifted docs` },
{ label: "Dead Code", description: `${manifest.summary.by_category.dead_code} unused files` }
]
},
{
question: "Risk level?",
header: "Risk",
options: [
{ label: "Low only", description: "Safest (Recommended)" },
{ label: "Low + Medium", description: "Includes likely unused" },
{ label: "All", description: "Aggressive" }
]
}
]
})
const selection = ASK_USER([
{
id: "categories", type: "multi-select",
prompt: "Which categories to clean?",
options: [
{ label: "Sessions", description: `${manifest.summary.by_category.stale_sessions} stale sessions` },
{ label: "Documents", description: `${manifest.summary.by_category.drifted_documents} drifted docs` },
{ label: "Dead Code", description: `${manifest.summary.by_category.dead_code} unused files` }
]
},
{
id: "risk", type: "select",
prompt: "Risk level?",
options: [
{ label: "Low only", description: "Safest (Recommended)" },
{ label: "Low + Medium", description: "Includes likely unused" },
{ label: "All", description: "Aggressive" }
]
}
]) // BLOCKS (wait for user response)
```
---

View File

@@ -16,7 +16,7 @@ Unified issue discovery and creation skill covering three entry points: manual i
│ → Action selection → Route to phase → Execute → Summary │
└───────────────┬─────────────────────────────────────────────────┘
├─ AskUserQuestion: Select action
├─ ASK_USER: Select action
┌───────────┼───────────┬───────────┐
↓ ↓ ↓ │
@@ -38,7 +38,7 @@ Unified issue discovery and creation skill covering three entry points: manual i
## Key Design Principles
1. **Action-Driven Routing**: AskUserQuestion selects action, then load single phase
1. **Action-Driven Routing**: ASK_USER 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
@@ -89,7 +89,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 → AskUserQuestion to select action
└─ Otherwise → ASK_USER to select action
Phase Execution (load one phase):
├─ Phase 1: Create New → phases/01-issue-new.md
@@ -155,31 +155,29 @@ function detectAction(input, flags) {
}
```
### Action Selection (AskUserQuestion)
### Action Selection (ASK_USER)
```javascript
// When action cannot be auto-detected
const answer = AskUserQuestion({
questions: [{
question: "What would you like to do?",
header: "Action",
multiSelect: false,
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"
}
]
}]
});
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)
// Route based on selection
const actionMap = {
@@ -196,7 +194,7 @@ User Input (URL / text / path pattern / descriptive prompt)
[Parse Flags + Auto-Detect Action]
[Action Selection] ← AskUserQuestion (if needed)
[Action Selection] ← ASK_USER (if needed)
[Read Selected Phase Document]
@@ -294,7 +292,7 @@ close_agent({ id: agentId })
| Error | Resolution |
|-------|------------|
| No action detected | Show AskUserQuestion with all 3 options |
| No action detected | Show ASK_USER 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 |
@@ -307,33 +305,29 @@ After successful phase execution, recommend next action:
```javascript
// After Create New (issue created)
AskUserQuestion({
questions: [{
question: "Issue created. What next?",
header: "Next",
multiSelect: false,
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" }
]
}]
});
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)
// After Discover / Discover by Prompt (discoveries generated)
AskUserQuestion({
questions: [{
question: "Discovery complete. What next?",
header: "Next",
multiSelect: false,
options: [
{ 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" }
]
}]
});
ASK_USER([{
id: "next_after_discover",
type: "select",
prompt: "Discovery complete. What next?",
options: [
{ 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)
```
## Related Skills & Commands

View File

@@ -145,16 +145,12 @@ 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 = AskUserQuestion({
questions: [{
question: 'Please describe the issue in more detail:',
header: 'Clarify',
multiSelect: false,
options: [
{ label: 'Provide details', description: 'Describe what, where, and expected behavior' }
]
}]
});
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)
if (answer.customText) {
issueData.context = answer.customText;
@@ -176,19 +172,9 @@ if (clarityScore < 2 && (!issueData.context || issueData.context.length < 20)) {
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');
// Yes → Create issue on GitHub and link it
// No → Store as local issue without GitHub sync
publishToGitHub = CONFIRM("Would you like to publish this issue to GitHub?"); // BLOCKS (wait for user response)
}
```
@@ -242,14 +228,14 @@ Phase 2: Data Extraction (branched by clarity)
│ Score 3 │ Score 1-2 │ Score 0 │
│ GitHub │ Text + ACE │ Vague │
├────────────┼─────────────────┼──────────────┤
│ gh CLI │ Parse struct │ AskQuestion
│ gh CLI │ Parse struct │ ASK_USER
│ → parse │ + quick hint │ (1 question) │
│ │ (3 files max) │ → feedback │
└────────────┴─────────────────┴──────────────┘
Phase 3: GitHub Publishing Decision (non-GitHub only)
├─ Source = github: Skip (already from GitHub)
└─ Source ≠ github: AskUserQuestion
└─ Source ≠ github: CONFIRM
├─ Yes → publishToGitHub = true
└─ No → publishToGitHub = false

View File

@@ -86,20 +86,18 @@ let selectedPerspectives = [];
if (args.perspectives) {
selectedPerspectives = args.perspectives.split(',').map(p => p.trim());
} else {
// Interactive selection via AskUserQuestion
const response = AskUserQuestion({
questions: [{
question: "Select primary discovery focus:",
header: "Focus",
multiSelect: false,
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)" }
]
}]
});
// 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)
selectedPerspectives = parseSelectedPerspectives(response);
}
```
@@ -273,22 +271,20 @@ await updateDiscoveryState(outputDir, {
```javascript
const hasHighPriority = issues.some(i => i.priority === 'critical' || i.priority === 'high');
await AskUserQuestion({
questions: [{
question: `Discovery complete: ${issues.length} issues generated, ${prioritizedFindings.length} total findings. What next?`,
header: "Next Step",
multiSelect: false,
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" }
]
}]
});
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)
if (response === "Export to Issues") {
await appendJsonl('.workflow/issues/issues.jsonl', issues);

View File

@@ -389,19 +389,17 @@ await updateDiscoveryState(outputDir, {
});
// Prompt user for next action
await AskUserQuestion({
questions: [{
question: `Discovery complete: ${issues.length} issues from ${cumulativeFindings.length} findings across ${iteration} iterations. What next?`,
header: "Next Step",
multiSelect: false,
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" }
]
}]
});
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)
```
## Dimension Agent Prompt Template

View File

@@ -16,7 +16,7 @@ Unified issue resolution pipeline that orchestrates solution creation from multi
│ → Source selection → Route to phase → Execute → Summary │
└───────────────┬─────────────────────────────────────────────────┘
├─ AskUserQuestion: Select issue source
├─ ASK_USER: Select issue source
┌───────────┼───────────┬───────────┬───────────┐
↓ ↓ ↓ ↓ │
@@ -36,7 +36,7 @@ Unified issue resolution pipeline that orchestrates solution creation from multi
## Key Design Principles
1. **Source-Driven Routing**: AskUserQuestion selects workflow, then load single phase
1. **Source-Driven Routing**: ASK_USER selects workflow, then load single phase
2. **Progressive Phase Loading**: Only read the selected phase document
3. **CLI-First Data Access**: All issue/solution CRUD via `ccw issue` CLI commands
4. **Auto Mode Support**: `-y` flag skips source selection (defaults to Explore & Plan)
@@ -142,7 +142,7 @@ Source Selection:
│ ├─ SESSION="..." → From Brainstorm
│ ├─ File/folder path → Convert from Artifact
│ └─ No input or --all-pending → Explore & Plan (all pending)
└─ Otherwise → AskUserQuestion to select source
└─ Otherwise → ASK_USER to select source
Phase Execution (load one phase):
├─ Phase 1: Explore & Plan → phases/01-issue-plan.md
@@ -210,35 +210,33 @@ function detectSource(input, flags) {
}
```
### Source Selection (AskUserQuestion)
### Source Selection (ASK_USER)
```javascript
// When source cannot be auto-detected
const answer = AskUserQuestion({
questions: [{
question: "How would you like to create/manage issue solutions?",
header: "Source",
multiSelect: false,
options: [
{
label: "Explore & Plan (Recommended)",
description: "AI explores codebase and generates solutions for issues"
},
{
label: "Convert from Artifact",
description: "Convert existing lite-plan, workflow session, or markdown to solution"
},
{
label: "From Brainstorm",
description: "Convert brainstorm session ideas into issue with solution"
},
{
label: "Form Execution Queue",
description: "Order bound solutions into execution queue for /issue:execute"
}
]
}]
});
const answer = ASK_USER([{
id: "source",
type: "select",
prompt: "How would you like to create/manage issue solutions?",
options: [
{
label: "Explore & Plan (Recommended)",
description: "AI explores codebase and generates solutions for issues"
},
{
label: "Convert from Artifact",
description: "Convert existing lite-plan, workflow session, or markdown to solution"
},
{
label: "From Brainstorm",
description: "Convert brainstorm session ideas into issue with solution"
},
{
label: "Form Execution Queue",
description: "Order bound solutions into execution queue for /issue:execute"
}
]
}]); // BLOCKS (wait for user response)
// Route based on selection
const sourceMap = {
@@ -256,7 +254,7 @@ User Input (issue IDs / artifact path / session ID / flags)
[Parse Flags + Auto-Detect Source]
[Source Selection] ← AskUserQuestion (if needed)
[Source Selection] ← ASK_USER (if needed)
[Read Selected Phase Document]
@@ -305,7 +303,7 @@ Phase-specific sub-tasks are attached when the phase executes (see individual ph
| Error | Resolution |
|-------|------------|
| No source detected | Show AskUserQuestion with all 4 options |
| No source detected | Show ASK_USER with all 4 options |
| Invalid source type | Show available sources, re-prompt |
| Phase execution fails | Report error, suggest manual intervention |
| No pending issues (plan) | Suggest creating issues first |
@@ -317,19 +315,17 @@ After successful phase execution, recommend next action:
```javascript
// After Plan/Convert/Brainstorm (solutions created)
AskUserQuestion({
questions: [{
question: "Solutions created. What next?",
header: "Next",
multiSelect: false,
options: [
{ label: "Form Queue", description: "Order solutions for execution (/issue:queue)" },
{ label: "Plan More Issues", description: "Continue creating solutions" },
{ label: "View Issues", description: "Review issue details" },
{ label: "Done", description: "Exit workflow" }
]
}]
});
ASK_USER([{
id: "next_action",
type: "select",
prompt: "Solutions created. What next?",
options: [
{ label: "Form Queue", description: "Order solutions for execution (/issue:queue)" },
{ label: "Plan More Issues", description: "Continue creating solutions" },
{ label: "View Issues", description: "Review issue details" },
{ label: "Done", description: "Exit workflow" }
]
}]); // BLOCKS (wait for user response)
// After Queue (queue formed)
// → Suggest /issue:execute directly

View File

@@ -249,14 +249,12 @@ for (const pending of pendingSelections) {
description: sol.description || sol.approach || 'No description'
}));
const answer = AskUserQuestion({
questions: [{
question: `Issue ${pending.issue_id}: which solution to bind?`,
header: pending.issue_id,
options: options,
multiSelect: false
}]
});
const answer = ASK_USER([{
id: pending.issue_id,
type: "select",
prompt: `Issue ${pending.issue_id}: which solution to bind?`,
options: options
}]); // BLOCKS (wait for user response)
const selected = answer[Object.keys(answer)[0]];
if (!selected || selected === 'Other') continue;

View File

@@ -582,19 +582,9 @@ ${solution.tasks.map(t => `- ${t.id}: ${t.title} [${t.action}]`).join('\n')}
// Confirm if not auto mode
if (!flags.yes && !flags.y) {
const confirm = AskUserQuestion({
questions: [{
question: `Create solution for issue ${issueId} with ${solution.tasks.length} tasks?`,
header: 'Confirm',
multiSelect: false,
options: [
{ label: 'Yes, create solution', description: 'Create and bind solution' },
{ label: 'Cancel', description: 'Abort without changes' }
]
}]
});
const confirmed = CONFIRM(`Create solution for issue ${issueId} with ${solution.tasks.length} tasks?`); // BLOCKS (wait for user response)
if (!confirm.answers?.['Confirm']?.includes('Yes')) {
if (!confirmed) {
console.log('Cancelled.');
return;
}

View File

@@ -251,15 +251,13 @@ agentIds.forEach((agentId, i) => {
```javascript
if (allClarifications.length > 0) {
for (const clarification of allClarifications) {
// Present to user via AskUserQuestion
const answer = AskUserQuestion({
questions: [{
question: `[${clarification.queue_id}] ${clarification.question}`,
header: clarification.conflict_id,
options: clarification.options,
multiSelect: false
}]
});
// Present to user via ASK_USER
const answer = ASK_USER([{
id: clarification.conflict_id,
type: "select",
prompt: `[${clarification.queue_id}] ${clarification.question}`,
options: clarification.options
}]); // BLOCKS (wait for user response)
// Re-spawn agent with user decision (original agent already closed)
// Create new agent with previous context + resolution
@@ -345,22 +343,20 @@ ccw issue queue list --brief
**Decision:**
- If `active_queue_id` is null → `ccw issue queue switch <new-queue-id>` (activate new queue)
- If active queue exists → Use **AskUserQuestion** to prompt user
- If active queue exists → Use **ASK_USER** to prompt user
**AskUserQuestion:**
**ASK_USER:**
```javascript
AskUserQuestion({
questions: [{
question: "Active queue exists. How would you like to proceed?",
header: "Queue Action",
options: [
{ label: "Merge into existing queue", description: "Add new items to active queue, delete new queue" },
{ label: "Use new queue", description: "Switch to new queue, keep existing in history" },
{ label: "Cancel", description: "Delete new queue, keep existing active" }
],
multiSelect: false
}]
})
ASK_USER([{
id: "queue_action",
type: "select",
prompt: "Active queue exists. How would you like to proceed?",
options: [
{ label: "Merge into existing queue", description: "Add new items to active queue, delete new queue" },
{ label: "Use new queue", description: "Switch to new queue, keep existing in history" },
{ label: "Cancel", description: "Delete new queue, keep existing active" }
]
}]); // BLOCKS (wait for user response)
```
**Action Commands:**

View File

@@ -2,7 +2,7 @@
Seven-phase workflow: **Context collection****Topic analysis****Role selection****Role questions****Conflict resolution****Final check****Generate specification**
All user interactions use AskUserQuestion tool (max 4 questions per call, multi-round).
All user interactions use ASK_USER / CONFIRM pseudo-code (implemented via AskUserQuestion tool) (max 4 questions per call, multi-round).
**Input**: `"GOAL: [objective] SCOPE: [boundaries] CONTEXT: [background]" [--count N]`
**Output**: `.workflow/active/WFS-{topic}/.brainstorming/guidance-specification.md`
@@ -18,7 +18,7 @@ All user interactions use AskUserQuestion tool (max 4 questions per call, multi-
### Phase Summary
| Phase | Goal | AskUserQuestion | Storage |
| Phase | Goal | ASK_USER | Storage |
|-------|------|-----------------|---------|
| 0 | Context collection | - | context-package.json |
| 1 | Topic analysis | 2-4 questions | intent_context |
@@ -28,35 +28,30 @@ All user interactions use AskUserQuestion tool (max 4 questions per call, multi-
| 4.5 | Final check | progressive rounds | additional_decisions |
| 5 | Generate spec | - | guidance-specification.md |
### AskUserQuestion Pattern
### ASK_USER Pattern
```javascript
// Single-select (Phase 1, 3, 4)
AskUserQuestion({
questions: [
{
question: "{问题文本}",
header: "{短标签}", // max 12 chars
multiSelect: false,
options: [
{ label: "{选项}", description: "{说明和影响}" },
{ label: "{选项}", description: "{说明和影响}" },
{ label: "{选项}", description: "{说明和影响}" }
]
}
// ... max 4 questions per call
]
})
ASK_USER([
{
id: "{短标签}", // max 12 chars
type: "select",
prompt: "{问题文本}",
options: [
{ label: "{选项}", description: "{说明和影响}" },
{ label: "{选项}", description: "{说明和影响}" },
{ label: "{选项}", description: "{说明和影响}" }
]
}
// ... max 4 questions per call
]) // BLOCKS (wait for user response)
// Multi-select (Phase 2)
AskUserQuestion({
questions: [{
question: "请选择 {count} 个角色",
header: "角色选择",
multiSelect: true,
options: [/* max 4 options per call */]
}]
})
ASK_USER([{
id: "角色选择", type: "multi-select",
prompt: "请选择 {count} 个角色",
options: [/* max 4 options per call */]
}]) // BLOCKS (wait for user response)
```
### Multi-Round Execution
@@ -65,7 +60,7 @@ AskUserQuestion({
const BATCH_SIZE = 4;
for (let i = 0; i < allQuestions.length; i += BATCH_SIZE) {
const batch = allQuestions.slice(i, i + BATCH_SIZE);
AskUserQuestion({ questions: batch });
ASK_USER(batch); // BLOCKS (wait for user response)
// Store responses before next round
}
```
@@ -143,34 +138,30 @@ if (contextResult.timed_out) {
1. Load Phase 0 context (tech_stack, modules, conflict_risk)
2. Deep topic analysis (entities, challenges, constraints, metrics)
3. Generate 2-4 context-aware probing questions
4. AskUserQuestion → Store to `session.intent_context`
4. ASK_USER → Store to `session.intent_context`
**Example**:
```javascript
AskUserQuestion({
questions: [
{
question: "实时协作平台的主要技术挑战?",
header: "核心挑战",
multiSelect: false,
options: [
{ label: "实时数据同步", description: "100+用户同时在线,状态同步复杂度高" },
{ label: "可扩展性架构", description: "用户规模增长时的系统扩展能力" },
{ label: "冲突解决机制", description: "多用户同时编辑的冲突处理策略" }
]
},
{
question: "MVP阶段最关注的指标",
header: "优先级",
multiSelect: false,
options: [
{ label: "功能完整性", description: "实现所有核心功能" },
{ label: "用户体验", description: "流畅的交互体验和响应速度" },
{ label: "系统稳定性", description: "高可用性和数据一致性" }
]
}
]
})
ASK_USER([
{
id: "核心挑战", type: "select",
prompt: "实时协作平台的主要技术挑战?",
options: [
{ label: "实时数据同步", description: "100+用户同时在线,状态同步复杂度高" },
{ label: "可扩展性架构", description: "用户规模增长时的系统扩展能力" },
{ label: "冲突解决机制", description: "多用户同时编辑的冲突处理策略" }
]
},
{
id: "优先级", type: "select",
prompt: "MVP阶段最关注的指标",
options: [
{ label: "功能完整性", description: "实现所有核心功能" },
{ label: "用户体验", description: "流畅的交互体验和响应速度" },
{ label: "系统稳定性", description: "高可用性和数据一致性" }
]
}
]) // BLOCKS (wait for user response)
```
**⚠️ CRITICAL**: Questions MUST reference topic keywords. Generic "Project type?" violates dynamic generation.
@@ -183,24 +174,21 @@ AskUserQuestion({
**Steps**:
1. Analyze Phase 1 keywords → Recommend count+2 roles with rationale
2. AskUserQuestion (multiSelect=true) → Store to `session.selected_roles`
2. ASK_USER (type=multi-select) → Store to `session.selected_roles`
3. If count+2 > 4, split into multiple rounds
**Example**:
```javascript
AskUserQuestion({
questions: [{
question: "请选择 3 个角色参与头脑风暴分析",
header: "角色选择",
multiSelect: true,
options: [
{ label: "system-architect", description: "实时同步架构设计和技术选型" },
{ label: "ui-designer", description: "协作界面用户体验和状态展示" },
{ label: "product-manager", description: "功能优先级和MVP范围决策" },
{ label: "data-architect", description: "数据同步模型和存储方案设计" }
]
}]
})
ASK_USER([{
id: "角色选择", type: "multi-select",
prompt: "请选择 3 个角色参与头脑风暴分析",
options: [
{ label: "system-architect", description: "实时同步架构设计和技术选型" },
{ label: "ui-designer", description: "协作界面用户体验和状态展示" },
{ label: "product-manager", description: "功能优先级和MVP范围决策" },
{ label: "data-architect", description: "数据同步模型和存储方案设计" }
]
}]) // BLOCKS (wait for user response)
```
**⚠️ CRITICAL**: User MUST interact. NEVER auto-select without confirmation.
@@ -213,36 +201,32 @@ AskUserQuestion({
1. FOR each selected role:
- Map Phase 1 challenges to role domain
- Generate 3-4 questions (implementation depth, trade-offs, edge cases)
- AskUserQuestion per role → Store to `session.role_decisions[role]`
- ASK_USER per role → Store to `session.role_decisions[role]`
2. Process roles sequentially (one at a time for clarity)
3. If role needs > 4 questions, split into multiple rounds
**Example** (system-architect):
```javascript
AskUserQuestion({
questions: [
{
question: "100+ 用户实时状态同步方案?",
header: "状态同步",
multiSelect: false,
options: [
{ label: "Event Sourcing", description: "完整事件历史,支持回溯,存储成本高" },
{ label: "集中式状态管理", description: "实现简单,单点瓶颈风险" },
{ label: "CRDT", description: "去中心化,自动合并,学习曲线陡" }
]
},
{
question: "两个用户同时编辑冲突如何解决?",
header: "冲突解决",
multiSelect: false,
options: [
{ label: "自动合并", description: "用户无感知,可能产生意外结果" },
{ label: "手动解决", description: "用户控制,增加交互复杂度" },
{ label: "版本控制", description: "保留历史,需要分支管理" }
]
}
]
})
ASK_USER([
{
id: "状态同步", type: "select",
prompt: "100+ 用户实时状态同步方案?",
options: [
{ label: "Event Sourcing", description: "完整事件历史,支持回溯,存储成本高" },
{ label: "集中式状态管理", description: "实现简单,单点瓶颈风险" },
{ label: "CRDT", description: "去中心化,自动合并,学习曲线陡" }
]
},
{
id: "冲突解决", type: "select",
prompt: "两个用户同时编辑冲突如何解决?",
options: [
{ label: "自动合并", description: "用户无感知,可能产生意外结果" },
{ label: "手动解决", description: "用户控制,增加交互复杂度" },
{ label: "版本控制", description: "保留历史,需要分支管理" }
]
}
]) // BLOCKS (wait for user response)
```
### Phase 4: Conflict Resolution
@@ -255,23 +239,20 @@ AskUserQuestion({
- Missing integration (e.g., "Optimistic updates" but no conflict handling)
- Implicit dependencies (e.g., "Live cursors" but no auth defined)
2. Generate clarification questions referencing SPECIFIC Phase 3 choices
3. AskUserQuestion (max 4 per call, multi-round) → Store to `session.cross_role_decisions`
3. ASK_USER (max 4 per call, multi-round) → Store to `session.cross_role_decisions`
4. If NO conflicts: Skip Phase 4 (inform user: "未检测到跨角色冲突跳过Phase 4")
**Example**:
```javascript
AskUserQuestion({
questions: [{
question: "CRDT 与 UI 回滚期望冲突,如何解决?\n背景system-architect选择CRDTui-designer期望回滚UI",
header: "架构冲突",
multiSelect: false,
options: [
{ label: "采用 CRDT", description: "保持去中心化调整UI期望" },
{ label: "显示合并界面", description: "增加用户交互,展示冲突详情" },
{ label: "切换到 OT", description: "支持回滚,增加服务器复杂度" }
]
}]
})
ASK_USER([{
id: "架构冲突", type: "select",
prompt: "CRDT 与 UI 回滚期望冲突,如何解决?\n背景system-architect选择CRDTui-designer期望回滚UI",
options: [
{ label: "采用 CRDT", description: "保持去中心化调整UI期望" },
{ label: "显示合并界面", description: "增加用户交互,展示冲突详情" },
{ label: "切换到 OT", description: "支持回滚,增加服务器复杂度" }
]
}]) // BLOCKS (wait for user response)
```
### Phase 4.5: Final Clarification
@@ -281,22 +262,13 @@ AskUserQuestion({
**Steps**:
1. Ask initial check:
```javascript
AskUserQuestion({
questions: [{
question: "在生成最终规范之前,是否有前面未澄清的重点需要补充?",
header: "补充确认",
multiSelect: false,
options: [
{ label: "无需补充", description: "前面的讨论已经足够完整" },
{ label: "需要补充", description: "还有重要内容需要澄清" }
]
}]
})
CONFIRM("在生成最终规范之前,是否有前面未澄清的重点需要补充?") // BLOCKS (wait for user response)
// Returns: "无需补充" (前面的讨论已经足够完整) | "需要补充" (还有重要内容需要澄清)
```
2. If "需要补充":
- Analyze user's additional points
- Generate progressive questions (not role-bound, interconnected)
- AskUserQuestion (max 4 per round) → Store to `session.additional_decisions`
- ASK_USER (max 4 per round) → Store to `session.additional_decisions`
- Repeat until user confirms completion
3. If "无需补充": Proceed to Phase 5

View File

@@ -231,17 +231,14 @@ for (let i = 0; i < questions.length; i += BATCH_SIZE) {
console.log(`\n[Round ${currentRound}/${totalRounds}] ${config.title} 上下文询问\n`);
AskUserQuestion({
questions: batch.map(q => ({
question: q.question,
header: q.category.substring(0, 12),
multiSelect: false,
options: q.options.map(opt => ({
label: opt.label,
description: opt.description
}))
ASK_USER(batch.map(q => ({
id: q.category.substring(0, 12), type: "select",
prompt: q.question,
options: q.options.map(opt => ({
label: opt.label,
description: opt.description
}))
});
}))); // BLOCKS (wait for user response)
// Store responses before next round
for (const answer of responses) {

View File

@@ -4,11 +4,11 @@ Six-phase workflow to eliminate ambiguities and enhance conceptual depth in role
**Phase 1-2**: Session detection → File discovery → Path preparation
**Phase 3A**: Cross-role analysis agent → Generate recommendations
**Phase 4**: User selects enhancements → User answers clarifications (via AskUserQuestion)
**Phase 4**: User selects enhancements → User answers clarifications (via ASK_USER)
**Phase 5**: Parallel update agents (one per role)
**Phase 6**: Context package update → Metadata update → Completion report
All user interactions use AskUserQuestion tool (max 4 questions per call, multi-round).
All user interactions use ASK_USER / CONFIRM pseudo-code (implemented via AskUserQuestion tool) (max 4 questions per call, multi-round).
**Document Flow**:
- Input: `[role]/analysis*.md`, `guidance-specification.md`, session metadata
@@ -25,41 +25,35 @@ All user interactions use AskUserQuestion tool (max 4 questions per call, multi-
| 1 | Session detection | Main flow | session_id, brainstorm_dir |
| 2 | File discovery | Main flow | role_analysis_paths |
| 3A | Cross-role analysis | spawn_agent | enhancement_recommendations |
| 4 | User interaction | Main flow + AskUserQuestion | update_plan |
| 4 | User interaction | Main flow + ASK_USER | update_plan |
| 5 | Document updates | spawn_agent[] (parallel) | Updated analysis*.md |
| 6 | Finalization | Main flow | context-package.json, report |
### AskUserQuestion Pattern
### ASK_USER Pattern
```javascript
// Enhancement selection (multi-select)
AskUserQuestion({
questions: [{
question: "请选择要应用的改进建议",
header: "改进选择",
multiSelect: true,
options: [
{ label: "EP-001: API Contract", description: "添加详细的请求/响应 schema 定义" },
{ label: "EP-002: User Intent", description: "明确用户需求优先级和验收标准" }
]
}]
})
ASK_USER([{
id: "改进选择", type: "multi-select",
prompt: "请选择要应用的改进建议",
options: [
{ label: "EP-001: API Contract", description: "添加详细的请求/响应 schema 定义" },
{ label: "EP-002: User Intent", description: "明确用户需求优先级和验收标准" }
]
}]) // BLOCKS (wait for user response)
// Clarification questions (single-select, multi-round)
AskUserQuestion({
questions: [
{
question: "MVP 阶段的核心目标是什么?",
header: "用户意图",
multiSelect: false,
options: [
{ label: "快速验证", description: "最小功能集,快速上线获取反馈" },
{ label: "技术壁垒", description: "完善架构,为长期发展打基础" },
{ label: "功能完整", description: "覆盖所有规划功能,延迟上线" }
]
}
]
})
ASK_USER([
{
id: "用户意图", type: "select",
prompt: "MVP 阶段的核心目标是什么?",
options: [
{ label: "快速验证", description: "最小功能集,快速上线获取反馈" },
{ label: "技术壁垒", description: "完善架构,为长期发展打基础" },
{ label: "功能完整", description: "覆盖所有规划功能,延迟上线" }
]
}
]) // BLOCKS (wait for user response)
```
---
@@ -150,7 +144,7 @@ close_agent({ id: analysisAgentId });
### Phase 4: User Interaction
**All interactions via AskUserQuestion (Chinese questions)**
**All interactions via ASK_USER (Chinese questions)**
#### Step 1: Enhancement Selection
@@ -163,17 +157,14 @@ const selectedEnhancements = [];
for (let i = 0; i < enhancements.length; i += BATCH_SIZE) {
const batch = enhancements.slice(i, i + BATCH_SIZE);
AskUserQuestion({
questions: [{
question: `请选择要应用的改进建议 (第${Math.floor(i/BATCH_SIZE)+1}轮)`,
header: "改进选择",
multiSelect: true,
options: batch.map(ep => ({
label: `${ep.id}: ${ep.title}`,
description: `影响: ${ep.affected_roles.join(', ')} | ${ep.enhancement}`
}))
}]
})
ASK_USER([{
id: "改进选择", type: "multi-select",
prompt: `请选择要应用的改进建议 (第${Math.floor(i/BATCH_SIZE)+1}轮)`,
options: batch.map(ep => ({
label: `${ep.id}: ${ep.title}`,
description: `影响: ${ep.affected_roles.join(', ')} | ${ep.enhancement}`
}))
}]) // BLOCKS (wait for user response)
// Store selections before next round
selectedEnhancements.push(...user_selections);
@@ -197,17 +188,14 @@ for (let i = 0; i < clarifications.length; i += BATCH_SIZE) {
const currentRound = Math.floor(i / BATCH_SIZE) + 1;
const totalRounds = Math.ceil(clarifications.length / BATCH_SIZE);
AskUserQuestion({
questions: batch.map(q => ({
question: q.question,
header: q.category.substring(0, 12),
multiSelect: false,
options: q.options.map(opt => ({
label: opt.label,
description: opt.description
}))
ASK_USER(batch.map(q => ({
id: q.category.substring(0, 12), type: "select",
prompt: q.question,
options: q.options.map(opt => ({
label: opt.label,
description: opt.description
}))
})
}))) // BLOCKS (wait for user response)
// Store answers before next round
batch.forEach((q, idx) => {

View File

@@ -84,7 +84,7 @@ Phase 1: Discovery
└─ Decision:
├─ count=0 → ERROR: No active sessions
├─ count=1 → Auto-select session → Phase 2
└─ count>1 → AskUserQuestion (max 4 options) → Phase 2
└─ count>1 → ASK_USER (max 4 options) → Phase 2
Phase 2: Planning Document Validation
├─ Check IMPL_PLAN.md exists
@@ -117,7 +117,7 @@ Phase 4: Execution Strategy & Task Execution
Phase 5: Completion
├─ Update task statuses in JSON files
├─ Generate summaries
└─ AskUserQuestion: Choose next step
└─ ASK_USER: Choose next step
├─ "Enter Review" → workflow:review
└─ "Complete Session" → workflow:session:complete
@@ -270,23 +270,20 @@ if (autoYes) {
selectedSessionId = firstSession.id
// Continue to Phase 2
} else {
// Interactive mode: Use AskUserQuestion to present formatted options (max 4 options shown)
// Interactive mode: Use ASK_USER to present formatted options (max 4 options shown)
// If more than 4 sessions, show most recent 4 with "Other" option for manual input
const sessions = getActiveSessions() // sorted by last modified
const displaySessions = sessions.slice(0, 4)
AskUserQuestion({
questions: [{
question: "Multiple active sessions detected. Select one:",
header: "Session",
multiSelect: false,
options: displaySessions.map(s => ({
label: s.id,
description: `${s.project} | ${s.progress}`
}))
// Note: User can select "Other" to manually enter session ID
}]
})
ASK_USER([{
id: "session", type: "select",
prompt: "Multiple active sessions detected. Select one:",
options: displaySessions.map(s => ({
label: s.id,
description: `${s.project} | ${s.progress}`
}))
// Note: User can select "Other" to manually enter session ID
}]) // BLOCKS (wait for user response)
}
```
@@ -415,23 +412,20 @@ if (autoYes) {
// Execute: workflow:session:complete --yes
} else {
// Interactive mode: Ask user
AskUserQuestion({
questions: [{
question: "All tasks completed. What would you like to do next?",
header: "Next Step",
multiSelect: false,
options: [
{
label: "Enter Review",
description: "Run specialized review (security/architecture/quality/action-items)"
},
{
label: "Complete Session",
description: "Archive session and update manifest"
}
]
}]
})
ASK_USER([{
id: "next_step", type: "select",
prompt: "All tasks completed. What would you like to do next?",
options: [
{
label: "Enter Review",
description: "Run specialized review (security/architecture/quality/action-items)"
},
{
label: "Complete Session",
description: "Archive session and update manifest"
}
]
}]) // BLOCKS (wait for user response)
}
```

View File

@@ -38,20 +38,22 @@ When `--yes` or `-y`: Auto-approve plan, skip clarifications, use default execut
## Usage
```
Skill(skill="workflow-lite-plan-execute", args="<task description>")
Skill(skill="workflow-lite-plan-execute", args="[FLAGS] \"<task description>\"")
```bash
$workflow-lite-plan-execute <task description>
$workflow-lite-plan-execute [FLAGS] "<task description>"
# Flags
-y, --yes Skip all confirmations (auto mode)
-e, --explore Force exploration phase
# Examples
Skill(skill="workflow-lite-plan-execute", args="\"Implement JWT authentication\"")
Skill(skill="workflow-lite-plan-execute", args="-y \"Add user profile page\"")
Skill(skill="workflow-lite-plan-execute", args="-e \"Refactor payment module\"")
$workflow-lite-plan-execute "Implement JWT authentication"
$workflow-lite-plan-execute -y "Add user profile page"
$workflow-lite-plan-execute -e "Refactor payment module"
```
> **Implementation sketch**: 编排器内部使用 `Skill(skill="workflow-lite-plan-execute", args="...")` 接口调用,此为伪代码示意,非命令行语法。
## Subagent API Reference
### spawn_agent

View File

@@ -69,7 +69,7 @@ Phase 2: Clarification (optional, multi-round)
├─ Aggregate clarification_needs from all exploration angles
├─ Deduplicate similar questions
└─ Decision:
├─ Has clarifications → AskUserQuestion (max 4 questions per round, multiple rounds allowed)
├─ Has clarifications → ASK_USER (max 4 questions per round, multiple rounds allowed)
└─ No clarifications → Skip to Phase 3
Phase 3: Planning (NO CODE EXECUTION - planning only)
@@ -79,7 +79,7 @@ Phase 3: Planning (NO CODE EXECUTION - planning only)
Phase 4: Confirmation & Selection
├─ Display plan summary (tasks, complexity, estimated time)
└─ AskUserQuestion:
└─ ASK_USER:
├─ Confirm: Allow / Modify / Cancel
├─ Execution: Agent / Codex / Auto
└─ Review: Gemini / Agent / Skip
@@ -457,7 +457,7 @@ This log will be fully consumed by planning phase, then refined for execution.
**Skip if**: No exploration or `clarification_needs` is empty across all explorations
**⚠️ CRITICAL**: AskUserQuestion tool limits max 4 questions per call. **MUST execute multiple rounds** to exhaust all clarification needs - do NOT stop at round 1.
**⚠️ CRITICAL**: ASK_USER tool limits max 4 questions per call. **MUST execute multiple rounds** to exhaust all clarification needs - do NOT stop at round 1.
**Aggregate clarification needs from all exploration angles**:
```javascript
@@ -506,17 +506,16 @@ if (autoYes) {
console.log(`### Clarification Round ${currentRound}/${totalRounds}`)
AskUserQuestion({
questions: batch.map(need => ({
question: `[${need.source_angle}] ${need.question}\n\nContext: ${need.context}`,
header: need.source_angle.substring(0, 12),
multiSelect: false,
options: need.options.map((opt, index) => ({
label: need.recommended === index ? `${opt}` : opt,
description: need.recommended === index ? `Recommended` : `Use ${opt}`
}))
}))
})
ASK_USER(batch.map(need => ({
id: `clarify-${need.source_angle}`,
type: "select",
prompt: `[${need.source_angle}] ${need.question}\n\nContext: ${need.context}`,
options: need.options.map((opt, index) => ({
label: need.recommended === index ? `${opt}` : opt,
description: need.recommended === index ? `Recommended` : `Use ${opt}`
})),
default: need.recommended
}))) // BLOCKS (wait for user response)
// Store batch responses in clarificationContext before next round
}
@@ -978,41 +977,42 @@ if (autoYes) {
} else {
// Interactive mode: Ask user
// Note: Execution "Other" option allows specifying CLI tools from ~/.claude/cli-tools.json
userSelection = AskUserQuestion({
questions: [
{
question: `Confirm plan? (${plan.tasks.length} tasks, ${plan.complexity})`,
header: "Confirm",
multiSelect: false,
options: [
{ label: "Allow", description: "Proceed as-is" },
{ label: "Modify", description: "Adjust before execution" },
{ label: "Cancel", description: "Abort workflow" }
]
},
{
question: "Execution method:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent", description: "@code-developer agent" },
{ label: "Codex", description: "codex CLI tool" },
{ label: "Auto", description: `Auto: ${plan.complexity === 'Low' ? 'Agent' : 'Codex'}` }
]
},
{
question: "Code review after execution?",
header: "Review",
multiSelect: false,
options: [
{ label: "Gemini Review", description: "Gemini CLI review" },
{ label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" },
{ label: "Agent Review", description: "@code-reviewer agent" },
{ label: "Skip", description: "No review" }
]
}
]
})
userSelection = ASK_USER([
{
id: "confirm",
type: "select",
prompt: `Confirm plan? (${plan.tasks.length} tasks, ${plan.complexity})`,
options: [
{ label: "Allow", description: "Proceed as-is" },
{ label: "Modify", description: "Adjust before execution" },
{ label: "Cancel", description: "Abort workflow" }
],
default: "Allow"
},
{
id: "execution",
type: "select",
prompt: "Execution method:",
options: [
{ label: "Agent", description: "@code-developer agent" },
{ label: "Codex", description: "codex CLI tool" },
{ label: "Auto", description: `Auto: ${plan.complexity === 'Low' ? 'Agent' : 'Codex'}` }
],
default: "Auto"
},
{
id: "review",
type: "select",
prompt: "Code review after execution?",
options: [
{ label: "Gemini Review", description: "Gemini CLI review" },
{ label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" },
{ label: "Agent Review", description: "@code-reviewer agent" },
{ label: "Skip", description: "No review" }
],
default: "Skip"
}
]) // BLOCKS (wait for user response)
}
```

View File

@@ -41,8 +41,8 @@ Flexible task execution phase supporting three input modes: in-memory plan (from
**Behavior**:
- Store prompt as `originalUserInput`
- Create simple execution plan from prompt
- AskUserQuestion: Select execution method (Agent/Codex/Auto)
- AskUserQuestion: Select code review tool (Skip/Gemini/Agent/Other)
- ASK_USER: Select execution method (Agent/Codex/Auto)
- ASK_USER: Select code review tool (Skip/Gemini/Agent/Other)
- Proceed to execution with `originalUserInput` included
**User Interaction**:
@@ -64,31 +64,31 @@ if (autoYes) {
}
} else {
// Interactive mode: Ask user
userSelection = AskUserQuestion({
questions: [
{
question: "Select execution method:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent", description: "@code-developer agent" },
{ label: "Codex", description: "codex CLI tool" },
{ label: "Auto", description: "Auto-select based on complexity" }
]
},
{
question: "Enable code review after execution?",
header: "Code Review",
multiSelect: false,
options: [
{ label: "Skip", description: "No review" },
{ label: "Gemini Review", description: "Gemini CLI tool" },
{ label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" },
{ label: "Agent Review", description: "Current agent review" }
]
}
]
})
userSelection = ASK_USER([
{
id: "execution",
type: "select",
prompt: "Select execution method:",
options: [
{ label: "Agent", description: "@code-developer agent" },
{ label: "Codex", description: "codex CLI tool" },
{ label: "Auto", description: "Auto-select based on complexity" }
],
default: "Auto"
},
{
id: "review",
type: "select",
prompt: "Enable code review after execution?",
options: [
{ label: "Skip", description: "No review" },
{ label: "Gemini Review", description: "Gemini CLI tool" },
{ label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" },
{ label: "Agent Review", description: "Current agent review" }
],
default: "Skip"
}
]) // BLOCKS (wait for user response)
}
```
@@ -136,8 +136,8 @@ If `isPlanJson === false`:
**Step 3: User Interaction**
- AskUserQuestion: Select execution method (Agent/Codex/Auto)
- AskUserQuestion: Select code review tool
- ASK_USER: Select execution method (Agent/Codex/Auto)
- ASK_USER: Select code review tool
- Proceed to execution with full context
## Execution Process

View File

@@ -362,27 +362,25 @@ if (autoYes) {
console.log(`[--yes] Auto-continuing to Phase 4: Execution`)
// Read phases/04-execution.md and execute Phase 4
} else {
AskUserQuestion({
questions: [{
question: "Planning complete. What would you like to do next?",
header: "Next Action",
multiSelect: false,
options: [
{
label: "Verify Plan Quality (Recommended)",
description: "Run quality verification to catch issues before execution."
},
{
label: "Start Execution",
description: "Begin implementing tasks immediately (Phase 4)."
},
{
label: "Review Status Only",
description: "View task breakdown and session status without taking further action."
}
]
}]
});
ASK_USER([{
id: "phase3-next-action",
type: "select",
prompt: "Planning complete. What would you like to do next?",
options: [
{
label: "Verify Plan Quality (Recommended)",
description: "Run quality verification to catch issues before execution."
},
{
label: "Start Execution",
description: "Begin implementing tasks immediately (Phase 4)."
},
{
label: "Review Status Only",
description: "View task breakdown and session status without taking further action."
}
]
}]) // BLOCKS (wait for user response)
}
// Execute based on user choice

View File

@@ -49,7 +49,7 @@ Step 3: Inline Conflict Resolution (conditional)
│ └─ Gemini/Qwen CLI analysis → conflict strategies
├─ 3.4 Iterative user clarification (send_input loop, max 10 rounds)
│ ├─ Display conflict + strategy ONE BY ONE
│ ├─ AskUserQuestion for user selection
│ ├─ ASK_USER for user selection
│ └─ send_input → agent re-analysis → confirm uniqueness
├─ 3.5 Generate conflict-resolution.json
└─ 3.6 Close conflict agent
@@ -419,11 +419,10 @@ FOR each conflict:
selectedStrategy = conflict.strategies[conflict.recommended || 0]
clarified = true // Skip clarification loop
} else {
AskUserQuestion({
questions: [{
question: formatStrategiesForDisplay(conflict.strategies),
header: "策略选择",
multiSelect: false,
ASK_USER([{
id: `conflict-${conflict.id}-strategy`,
type: "select",
prompt: formatStrategiesForDisplay(conflict.strategies),
options: [
...conflict.strategies.map((s, i) => ({
label: `${s.name}${i === conflict.recommended ? ' (推荐)' : ''}`,
@@ -431,8 +430,7 @@ FOR each conflict:
})),
{ label: "自定义修改", description: `建议: ${conflict.modification_suggestions?.slice(0,2).join('; ')}` }
]
}]
})
}]) // BLOCKS (wait for user response)
// 3. Handle selection
if (userChoice === "自定义修改") {
@@ -446,12 +444,12 @@ FOR each conflict:
// 4. Clarification (if needed) - using send_input for agent re-analysis
if (!autoYes && selectedStrategy.clarification_needed?.length > 0) {
for (batch of chunk(selectedStrategy.clarification_needed, 4)) {
AskUserQuestion({
questions: batch.map((q, i) => ({
question: q, header: `澄清${i+1}`, multiSelect: false,
options: [{ label: "详细说明", description: "提供答案" }]
}))
})
ASK_USER(batch.map((q, i) => ({
id: `clarify-${conflict.id}-${i+1}`,
type: "select",
prompt: q,
options: [{ label: "详细说明", description: "提供答案" }]
}))) // BLOCKS (wait for user response)
userClarifications.push(...collectAnswers(batch))
}
@@ -498,7 +496,7 @@ selectedStrategies = resolvedConflicts.map(r => ({
```
**Key Points**:
- AskUserQuestion: max 4 questions/call, batch if more
- ASK_USER: max 4 questions/call, batch if more
- Strategy options: 2-4 strategies + "自定义修改"
- Clarification loop via send_input: max 10 rounds, agent determines uniqueness_confirmed
- Agent stays active throughout interaction (no close_agent until Step 3.6)

View File

@@ -92,57 +92,53 @@ if (autoYes) {
**User Questions** (skipped if autoYes):
```javascript
if (!autoYes) AskUserQuestion({
questions: [
{
question: "Do you have supplementary materials or guidelines to include?",
header: "Materials",
multiSelect: false,
options: [
{ label: "No additional materials", description: "Use existing context only" },
{ label: "Provide file paths", description: "I'll specify paths to include" },
{ label: "Provide inline content", description: "I'll paste content directly" }
]
},
{
question: "Select execution method for generated tasks:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent (Recommended)", description: "Claude agent executes tasks directly" },
{ label: "Hybrid", description: "Agent orchestrates, calls CLI for complex steps" },
{ label: "CLI Only", description: "All execution via CLI tools (codex/gemini/qwen)" }
]
},
{
question: "If using CLI, which tool do you prefer?",
header: "CLI Tool",
multiSelect: false,
options: [
{ label: "Codex (Recommended)", description: "Best for implementation tasks" },
{ label: "Gemini", description: "Best for analysis and large context" },
{ label: "Qwen", description: "Alternative analysis tool" },
{ label: "Auto", description: "Let agent decide per-task" }
]
}
]
})
if (!autoYes) ASK_USER([
{
id: "materials",
type: "select",
prompt: "Do you have supplementary materials or guidelines to include?",
options: [
{ label: "No additional materials", description: "Use existing context only" },
{ label: "Provide file paths", description: "I'll specify paths to include" },
{ label: "Provide inline content", description: "I'll paste content directly" }
]
},
{
id: "execution-method",
type: "select",
prompt: "Select execution method for generated tasks:",
options: [
{ label: "Agent (Recommended)", description: "Claude agent executes tasks directly" },
{ label: "Hybrid", description: "Agent orchestrates, calls CLI for complex steps" },
{ label: "CLI Only", description: "All execution via CLI tools (codex/gemini/qwen)" }
]
},
{
id: "cli-tool",
type: "select",
prompt: "If using CLI, which tool do you prefer?",
options: [
{ label: "Codex (Recommended)", description: "Best for implementation tasks" },
{ label: "Gemini", description: "Best for analysis and large context" },
{ label: "Qwen", description: "Alternative analysis tool" },
{ label: "Auto", description: "Let agent decide per-task" }
]
}
]) // BLOCKS (wait for user response)
```
**Handle Materials Response** (skipped if autoYes):
```javascript
if (!autoYes && userConfig.materials === "Provide file paths") {
// Follow-up question for file paths
const pathsResponse = AskUserQuestion({
questions: [{
question: "Enter file paths to include (comma-separated or one per line):",
header: "Paths",
multiSelect: false,
options: [
{ label: "Enter paths", description: "Provide paths in text input" }
]
}]
})
const pathsResponse = ASK_USER([{
id: "material-paths",
type: "input",
prompt: "Enter file paths to include (comma-separated or one per line):",
options: [
{ label: "Enter paths", description: "Provide paths in text input" }
]
}]) // BLOCKS (wait for user response)
userConfig.supplementaryPaths = parseUserPaths(pathsResponse)
}
```

View File

@@ -51,7 +51,7 @@ Step 3: Task Execution Loop
Step 4: Completion
├─ Synchronize all statuses
├─ Generate summaries
└─ AskUserQuestion: Review or Complete Session
└─ ASK_USER: Review or Complete Session
```
## Step 1: TodoWrite Generation
@@ -284,23 +284,21 @@ if (autoYes) {
// Execute: workflow:session:complete --yes
} else {
// Interactive mode: Ask user
AskUserQuestion({
questions: [{
question: "All tasks completed. What would you like to do next?",
header: "Next Step",
multiSelect: false,
options: [
{
label: "Enter Review",
description: "Run specialized review (security/architecture/quality/action-items)"
},
{
label: "Complete Session",
description: "Archive session and update manifest"
}
]
}]
})
ASK_USER([{
id: "completion-next-step",
type: "select",
prompt: "All tasks completed. What would you like to do next?",
options: [
{
label: "Enter Review",
description: "Run specialized review (security/architecture/quality/action-items)"
},
{
label: "Complete Session",
description: "Archive session and update manifest"
}
]
}]) // BLOCKS (wait for user response)
}
```

View File

@@ -81,12 +81,14 @@ Phase 2: Agent Execution (Document Generation)
**User Questions**:
```javascript
AskUserQuestion({
questions: [
if (AUTO_YES) {
// --yes/-y: skip user questions, use defaults
userConfig = { materials: "No additional materials", execution: "Agent (Recommended)", cliTool: "Auto" }
} else {
ASK_USER([
{
question: "Do you have supplementary materials or guidelines to include?",
header: "Materials",
multiSelect: false,
id: "Materials", type: "select",
prompt: "Do you have supplementary materials or guidelines to include?",
options: [
{ label: "No additional materials", description: "Use existing context only" },
{ label: "Provide file paths", description: "I'll specify paths to include" },
@@ -94,9 +96,8 @@ AskUserQuestion({
]
},
{
question: "Select execution method for generated TDD tasks:",
header: "Execution",
multiSelect: false,
id: "Execution", type: "select",
prompt: "Select execution method for generated TDD tasks:",
options: [
{ label: "Agent (Recommended)", description: "Agent executes Red-Green-Refactor cycles directly" },
{ label: "Hybrid", description: "Agent orchestrates, calls CLI for complex steps (Red/Green phases)" },
@@ -104,9 +105,8 @@ AskUserQuestion({
]
},
{
question: "If using CLI, which tool do you prefer?",
header: "CLI Tool",
multiSelect: false,
id: "CLI Tool", type: "select",
prompt: "If using CLI, which tool do you prefer?",
options: [
{ label: "Codex (Recommended)", description: "Best for TDD Red-Green-Refactor cycles" },
{ label: "Gemini", description: "Best for analysis and large context" },
@@ -114,24 +114,21 @@ AskUserQuestion({
{ label: "Auto", description: "Let agent decide per-task" }
]
}
]
})
]) // BLOCKS (wait for user response)
}
```
**Handle Materials Response**:
```javascript
if (userConfig.materials === "Provide file paths") {
// Follow-up question for file paths
const pathsResponse = AskUserQuestion({
questions: [{
question: "Enter file paths to include (comma-separated or one per line):",
header: "Paths",
multiSelect: false,
options: [
{ label: "Enter paths", description: "Provide paths in text input" }
]
}]
})
const pathsResponse = ASK_USER([{
id: "Paths", type: "input",
prompt: "Enter file paths to include (comma-separated or one per line):",
options: [
{ label: "Enter paths", description: "Provide paths in text input" }
]
}]) // BLOCKS (wait for user response)
userConfig.supplementaryPaths = parseUserPaths(pathsResponse)
}
```
@@ -244,7 +241,7 @@ const userConfig = {
// User configuration from Phase 0
"user_config": {
// From Phase 0 AskUserQuestion
// From Phase 0 ASK_USER
}
}
```