feat(tests): enhance test coverage with integration and utility tests

- Updated QueueCard tests to use getAllByText for better resilience against multiple occurrences.
- Modified useCodexLens tests to check for error existence instead of specific message.
- Added mock for ResizeObserver in test setup to support components using it.
- Introduced integration tests for appStore and hooks interactions, covering locale and theme flows.
- Created layout-utils tests to validate pane manipulation functions.
- Added queryKeys tests to ensure correct key generation for workspace queries.
- Implemented utils tests for class name merging and memory metadata parsing.
This commit is contained in:
catlog22
2026-02-17 13:06:13 +08:00
parent 8665ea73a4
commit d5c6f65599
25 changed files with 1437 additions and 2338 deletions

View File

@@ -61,6 +61,36 @@ User Input → Analyze Intent → Select Workflow → [Confirm] → Execute Chai
**vs ccw-coordinator**: External CLI execution with background tasks and hook callbacks.
## Auto Mode (`-y` / `--yes`)
当用户传入 `-y``--yes` 时,整个 CCW 链路进入自动模式:
```javascript
// Phase 0: 检测 -y 标志(在 Phase 1 之前执行)
const autoYes = /\b(-y|--yes)\b/.test($ARGUMENTS)
```
**自动模式行为**:
- **Phase 1.5**: 跳过需求澄清clarity_score < 2 也不询问,用已有信息推断)
- **Phase 3**: 跳过用户确认,直接执行命令链
- **Phase 5**: 错误处理自动选择 "Skip"(继续下一个命令)
- **Skill 传播**: `-y` 自动附加到链中每个 Skill 的 args
**传播机制**: 通过 `assembleCommand` 注入 `-y`
```javascript
function assembleCommand(step, previousResult) {
let args = step.args || '';
if (!args && previousResult?.session_id) {
args = `--session="${previousResult.session_id}"`;
}
// ★ 传播 -y 到下游 Skill
if (autoYes && !args.includes('-y') && !args.includes('--yes')) {
args = args ? `${args} -y` : '-y';
}
return { skill: step.cmd, args };
}
```
## 5-Phase Workflow
### Phase 1: Analyze Intent
@@ -114,6 +144,7 @@ function detectTaskType(text) {
```javascript
async function clarifyRequirements(analysis) {
if (analysis.clarity_score >= 2) return analysis;
if (autoYes) return analysis; // ★ 自动模式:跳过澄清,用已有信息推断
const questions = generateClarificationQuestions(analysis); // Goal, Scope, Constraints
const answers = await AskUserQuestion({ questions });
@@ -282,6 +313,8 @@ function buildCommandChain(workflow, analysis) {
```javascript
async function getUserConfirmation(chain) {
if (autoYes) return chain; // ★ 自动模式:跳过确认,直接执行
const response = await AskUserQuestion({
questions: [{
question: "Execute this command chain?",
@@ -411,6 +444,10 @@ function assembleCommand(step, previousResult) {
if (!args && previousResult?.session_id) {
args = `--session="${previousResult.session_id}"`;
}
// ★ 传播 -y 到下游 Skill
if (autoYes && !args.includes('-y') && !args.includes('--yes')) {
args = args ? `${args} -y` : '-y';
}
return { skill: step.cmd, args };
}
@@ -430,6 +467,8 @@ function updateTodoStatus(index, total, workflow, status) {
// Error handling: Retry/Skip/Abort
async function handleError(step, error, index) {
if (autoYes) return 'skip'; // ★ 自动模式:跳过失败命令,继续下一个
const response = await AskUserQuestion({
questions: [{
question: `${step.cmd} failed: ${error.message}`,
@@ -610,6 +649,10 @@ todos = [
# Auto-select workflow
/ccw "Add user authentication"
# Auto mode - skip all confirmations, propagate -y to all skills
/ccw -y "Add user authentication"
/ccw --yes "Fix memory leak in WebSocket handler"
# Complex requirement (triggers clarification)
/ccw "Optimize system performance"

View File

@@ -193,7 +193,8 @@ Final: planner 发送 all_planned → executor 完成剩余 EXEC-* → 结束
### 选择逻辑
```javascript
const autoYes = args.includes('--auto') || args.includes('-y')
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test(args)
const explicitExec = args.match(/--exec[=\s]+(agent|codex|gemini|auto)/i)?.[1]
let executionConfig
@@ -253,7 +254,7 @@ function resolveExecutor(taskCount) {
Skill(skill="team-planex", args="--exec=codex ISS-xxx")
Skill(skill="team-planex", args="--exec=agent --text '简单功能'")
# Auto 模式(跳过交互)
# Auto 模式(跳过交互-y 或 --yes
Skill(skill="team-planex", args="-y --text '添加日志'")
```

View File

@@ -1,6 +1,6 @@
# Command: monitor
> 消息总线轮询与协调循环。持续监控 worker 进度,路由消息,触发 GC 循环,执行质量门控。
> 阶段驱动的协调循环。按 pipeline 阶段顺序等待 worker 完成,路由消息,触发 GC 循环,执行质量门控。
## When to Use
@@ -16,7 +16,12 @@
### Delegation Mode
**Mode**: Directcoordinator 直接轮询和路由
**Mode**: Stage-driven按阶段顺序等待非轮询
### 设计原则
> **模型执行没有时间概念**。禁止空转 while 循环检查状态。
> 使用固定 sleep 间隔 + 最大轮询次数,避免无意义的 API 调用浪费。
### Decision Logic
@@ -24,59 +29,37 @@
// 消息路由表
const routingTable = {
// Scout 完成
'scan_ready': {
action: 'Mark SCOUT complete, unblock QASTRAT',
next: 'strategist'
},
'issues_found': {
action: 'Mark SCOUT complete with issues, unblock QASTRAT',
next: 'strategist'
},
'scan_ready': { action: 'Mark SCOUT complete, unblock QASTRAT' },
'issues_found': { action: 'Mark SCOUT complete with issues, unblock QASTRAT' },
// Strategist 完成
'strategy_ready': {
action: 'Mark QASTRAT complete, unblock QAGEN',
next: 'generator'
},
'strategy_ready': { action: 'Mark QASTRAT complete, unblock QAGEN' },
// Generator 完成
'tests_generated': {
action: 'Mark QAGEN complete, unblock QARUN',
next: 'executor'
},
'tests_revised': {
action: 'Mark QAGEN-fix complete, unblock QARUN-gc',
next: 'executor'
},
'tests_generated': { action: 'Mark QAGEN complete, unblock QARUN' },
'tests_revised': { action: 'Mark QAGEN-fix complete, unblock QARUN-gc' },
// Executor 完成
'tests_passed': {
action: 'Mark QARUN complete, check coverage, unblock next',
next: 'check_coverage'
},
'tests_failed': {
action: 'Evaluate failures, decide GC loop or continue',
next: 'gc_decision'
},
'tests_passed': { action: 'Mark QARUN complete, check coverage, unblock next', special: 'check_coverage' },
'tests_failed': { action: 'Evaluate failures, decide GC loop or continue', special: 'gc_decision' },
// Analyst 完成
'analysis_ready': {
action: 'Mark QAANA complete, evaluate quality gate',
next: 'quality_gate'
},
'quality_report': {
action: 'Quality report received, prepare final report',
next: 'finalize'
},
'analysis_ready': { action: 'Mark QAANA complete, evaluate quality gate', special: 'quality_gate' },
'quality_report': { action: 'Quality report received, prepare final report', special: 'finalize' },
// 错误
'error': {
action: 'Assess severity, retry or escalate',
next: 'error_handler'
}
'error': { action: 'Assess severity, retry or escalate', special: 'error_handler' }
}
```
### 等待策略常量
```javascript
const POLL_INTERVAL_SEC = 300 // 每次检查间隔 5 分钟(测试执行可能很慢)
const MAX_POLLS_PER_STAGE = 6 // 单阶段最多等待 6 次(~30 分钟)
const SLEEP_CMD = process.platform === 'win32'
? `timeout /t ${POLL_INTERVAL_SEC} /nobreak >nul 2>&1`
: `sleep ${POLL_INTERVAL_SEC}`
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoMode = /\b(-y|--yes)\b/.test(args)
```
## Execution Steps
### Step 1: Context Preparation
@@ -92,116 +75,176 @@ for (const layer of (strategy.layers || [])) {
let gcIteration = 0
const MAX_GC_ITERATIONS = 3
// 获取 pipeline 阶段列表(来自 dispatch 创建的任务链)
const allTasks = TaskList()
const pipelineTasks = allTasks
.filter(t => t.owner && t.owner !== 'coordinator')
.sort((a, b) => Number(a.id) - Number(b.id))
```
### Step 2: Execute Strategy
### Step 2: Stage-Driven Execution
> **核心改动**: 不再使用 while 轮询循环。按 pipeline 阶段顺序,逐阶段等待完成。
> 每个阶段sleep → 检查消息 → 确认任务状态 → 处理结果 → 下一阶段。
```javascript
let allComplete = false
// 按依赖顺序处理每个阶段
for (const stageTask of pipelineTasks) {
// --- 等待当前阶段完成 ---
let stageComplete = false
let pollCount = 0
while (!allComplete) {
// 1. Poll message bus
const messages = mcp__ccw-tools__team_msg({
operation: "list",
team: teamName,
last: 10
})
while (!stageComplete && pollCount < MAX_POLLS_PER_STAGE) {
// ★ 固定等待sleep 30s让 worker 有执行时间
Bash(SLEEP_CMD)
pollCount++
// 2. Route each unprocessed message
for (const msg of messages) {
const handler = routingTable[msg.type]
if (!handler) continue
// 1. 检查消息总线(主要信号源)
const messages = mcp__ccw-tools__team_msg({
operation: "list",
team: teamName,
last: 5
})
switch (handler.next) {
case 'check_coverage': {
// 读取执行结果
const coverage = msg.data?.coverage || 0
const targetLayer = msg.data?.layer || 'L1'
const target = coverageTargets[targetLayer] || 80
if (coverage >= target) {
// 覆盖率达标,继续流水线
// 解锁下一个任务QAANA 或下一层级)
} else {
// 转入 GC 决策
handler.next = 'gc_decision'
}
break
}
case 'gc_decision': {
const coverage = msg.data?.coverage || 0
const targetLayer = msg.data?.layer || 'L1'
if (gcIteration < MAX_GC_ITERATIONS) {
gcIteration++
// 触发 GC 循环
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "generator", type: "gc_loop_trigger",
summary: `[coordinator] GC循环 #${gcIteration}: 覆盖率 ${coverage}% 未达标,请修复`,
data: { iteration: gcIteration, layer: targetLayer, coverage }
})
// 创建 GC 修复任务(参见 dispatch.md createGCLoopTasks
// createGCLoopTasks(gcIteration, targetLayer, sessionFolder)
} else {
// 超过最大迭代次数,接受当前覆盖率
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] GC循环已达上限(${MAX_GC_ITERATIONS}),接受当前覆盖率 ${coverage}%`
})
// 继续流水线,解锁 QAANA
}
break
}
case 'quality_gate': {
const qualityScore = sharedMemory.quality_score || 0
let status = 'PASS'
if (qualityScore < 60) status = 'FAIL'
else if (qualityScore < 80) status = 'CONDITIONAL'
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 质量门控: ${status} (score: ${qualityScore})`
})
break
}
case 'error_handler': {
const fromRole = msg.from
const severity = msg.data?.severity || 'medium'
if (severity === 'critical') {
// 通知用户
SendMessage({
content: `## [coordinator] Critical Error from ${fromRole}\n\n${msg.summary}`,
summary: `[coordinator] Critical error: ${msg.summary}`
})
} else {
// 标记任务失败,尝试重试
}
break
}
// 2. 路由消息
for (const msg of messages) {
const handler = routingTable[msg.type]
if (!handler) continue
processMessage(msg, handler)
}
// 3. 确认任务状态(兜底)
const currentTask = TaskGet({ taskId: stageTask.id })
stageComplete = currentTask.status === 'completed' || currentTask.status === 'deleted'
}
// 3. Check TaskList for overall completion
const tasks = TaskList()
const pendingWorkerTasks = tasks.filter(t =>
t.owner !== 'coordinator' &&
t.status !== 'completed' &&
t.status !== 'deleted'
)
// --- 阶段超时处理 ---
if (!stageComplete) {
const elapsedMin = Math.round(pollCount * POLL_INTERVAL_SEC / 60)
allComplete = pendingWorkerTasks.length === 0
if (autoMode) {
// 自动模式:记录日志,自动跳过
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 超时 (${elapsedMin}min),自动跳过`
})
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue
}
// 4. 如果没有完成,等待片刻再轮询
if (!allComplete) {
// 短暂等待(在实际执行中 coordinator 会在 subagent 返回后继续)
// 交互模式:由用户决定
const decision = AskUserQuestion({
questions: [{
question: `阶段 "${stageTask.subject}" 已等待 ${elapsedMin} 分钟仍未完成。如何处理?`,
header: "Stage Wait",
multiSelect: false,
options: [
{ label: "继续等待", description: `再等 ${MAX_POLLS_PER_STAGE} 轮(~${Math.round(MAX_POLLS_PER_STAGE * POLL_INTERVAL_SEC / 60)}min` },
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" },
{ label: "终止流水线", description: "停止整个 QA 流程,汇报当前结果" }
]
}]
})
const answer = decision["Stage Wait"]
if (answer === "继续等待") {
// 重置计数器,继续等待当前阶段
pollCount = 0
// 重新进入当前阶段的等待循环(需要用 while 包裹,此处用 goto 语义)
continue // 注意:实际执行中需要将 for 改为可重入的逻辑
} else if (answer === "跳过此阶段") {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 用户选择跳过阶段 ${stageTask.subject}`
})
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue
} else {
// 终止流水线
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "shutdown",
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
})
break // 跳出 for 循环,进入 Step 3 汇报
}
}
}
```
### Step 2.1: Message Processing (processMessage)
```javascript
function processMessage(msg, handler) {
switch (handler.special) {
case 'check_coverage': {
const coverage = msg.data?.coverage || 0
const targetLayer = msg.data?.layer || 'L1'
const target = coverageTargets[targetLayer] || 80
if (coverage < target) {
handleGCDecision(coverage, targetLayer)
}
// 覆盖率达标则不做额外处理,流水线自然流转
break
}
case 'gc_decision': {
const coverage = msg.data?.coverage || 0
const targetLayer = msg.data?.layer || 'L1'
handleGCDecision(coverage, targetLayer)
break
}
case 'quality_gate': {
// 重新读取最新 shared memory
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const qualityScore = latestMemory.quality_score || 0
let status = 'PASS'
if (qualityScore < 60) status = 'FAIL'
else if (qualityScore < 80) status = 'CONDITIONAL'
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 质量门控: ${status} (score: ${qualityScore})`
})
break
}
case 'error_handler': {
const severity = msg.data?.severity || 'medium'
if (severity === 'critical') {
SendMessage({
content: `## [coordinator] Critical Error from ${msg.from}\n\n${msg.summary}`,
summary: `[coordinator] Critical error: ${msg.summary}`
})
}
break
}
}
}
function handleGCDecision(coverage, targetLayer) {
if (gcIteration < MAX_GC_ITERATIONS) {
gcIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "generator", type: "gc_loop_trigger",
summary: `[coordinator] GC循环 #${gcIteration}: 覆盖率 ${coverage}% 未达标,请修复`,
data: { iteration: gcIteration, layer: targetLayer, coverage }
})
// 创建 GC 修复任务(参见 dispatch.md createGCLoopTasks
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] GC循环已达上限(${MAX_GC_ITERATIONS}),接受当前覆盖率 ${coverage}%`
})
}
}
```
@@ -211,9 +254,11 @@ while (!allComplete) {
```javascript
// 汇总所有结果
const finalSharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const allFinalTasks = TaskList()
const workerTasks = allFinalTasks.filter(t => t.owner && t.owner !== 'coordinator')
const summary = {
total_tasks: TaskList().filter(t => t.owner !== 'coordinator').length,
completed_tasks: TaskList().filter(t => t.status === 'completed' && t.owner !== 'coordinator').length,
total_tasks: workerTasks.length,
completed_tasks: workerTasks.filter(t => t.status === 'completed').length,
gc_iterations: gcIteration,
quality_score: finalSharedMemory.quality_score,
coverage: finalSharedMemory.execution_results?.coverage
@@ -240,8 +285,9 @@ const summary = {
| Scenario | Resolution |
|----------|------------|
| Message bus unavailable | Fall back to TaskList polling only |
| Stage timeout (交互模式) | AskUserQuestion继续等待 / 跳过 / 终止流水线 |
| Stage timeout (自动模式 `-y`/`--yes`) | 自动跳过,记录日志,继续流水线 |
| Teammate unresponsive (2x no response) | Respawn teammate with same task |
| Deadlock detected (tasks blocked indefinitely) | Identify cycle, manually unblock |
| Quality gate FAIL | Report to user, suggest targeted re-run |
| Agent/CLI failure | Retry once, then fallback to inline execution |
| Timeout (>5 min) | Report partial results, notify coordinator |
| GC loop stuck >3 iterations | Accept current coverage, continue pipeline |

View File

@@ -78,8 +78,11 @@ function detectQAMode(args, desc) {
let qaMode = detectQAMode(args, taskDescription)
// 简单任务可跳过确认
if (!taskDescription || taskDescription.length < 10) {
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test(args)
// 简单任务可跳过确认auto 模式跳过)
if (!autoYes && (!taskDescription || taskDescription.length < 10)) {
const clarification = AskUserQuestion({
questions: [{
question: "请描述 QA 目标(哪些模块需要质量保障?关注哪些方面?)",
@@ -202,19 +205,21 @@ SendMessage({
summary: `[coordinator] QA report: ${report.quality_score}`
})
// 询问下一步
AskUserQuestion({
questions: [{
question: "QA 流程已完成。下一步:",
header: "Next",
multiSelect: false,
options: [
{ label: "新目标", description: "对新模块/需求执行QA" },
{ label: "深入分析", description: "对发现的问题进行更深入分析" },
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
]
}]
})
// 询问下一步auto 模式跳过,默认关闭团队)
if (!autoYes) {
AskUserQuestion({
questions: [{
question: "QA 流程已完成。下一步:",
header: "Next",
multiSelect: false,
options: [
{ label: "新目标", description: "对新模块/需求执行QA" },
{ label: "深入分析", description: "对发现的问题进行更深入分析" },
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
]
}]
})
}
```
## Error Handling

View File

@@ -49,7 +49,13 @@ function detectMode() {
Before dispatching, collect workflow preferences via AskUserQuestion:
```javascript
if (mode === 'plan') {
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test($ARGUMENTS)
if (autoYes) {
// 自动模式:跳过所有询问,使用默认值
workflowPreferences = { autoYes: true, forceExplore: false }
} else if (mode === 'plan') {
const prefResponse = AskUserQuestion({
questions: [
{
@@ -76,7 +82,7 @@ if (mode === 'plan') {
autoYes: prefResponse.autoMode === 'Auto',
forceExplore: prefResponse.exploration === 'Force explore'
}
} else {
} else if (mode !== 'plan') {
// Execute mode (standalone, not in-memory)
const prefResponse = AskUserQuestion({
questions: [

View File

@@ -52,40 +52,48 @@ Unified planning skill combining 4-phase planning workflow, plan quality verific
Before dispatching to phase execution, collect workflow preferences via AskUserQuestion:
```javascript
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否跳过所有确认步骤(自动模式)?",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test($ARGUMENTS)
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
}
// For replan mode, also collect interactive preference
if (mode === 'replan') {
const replanPref = AskUserQuestion({
if (autoYes) {
// 自动模式:跳过所有询问,使用默认值
workflowPreferences = { autoYes: true, interactive: false }
} else {
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否使用交互式澄清模式?",
header: "Replan Mode",
question: "是否跳过所有确认步骤(自动模式",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Standard (Recommended)", description: "使用安全默认值" },
{ label: "Interactive", description: "通过提问交互式澄清修改范围" }
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
workflowPreferences.interactive = replanPref.replanMode === 'Interactive'
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
}
// For replan mode, also collect interactive preference
if (mode === 'replan') {
const replanPref = AskUserQuestion({
questions: [
{
question: "是否使用交互式澄清模式?",
header: "Replan Mode",
multiSelect: false,
options: [
{ label: "Standard (Recommended)", description: "使用安全默认值" },
{ label: "Interactive", description: "通过提问交互式澄清修改范围" }
]
}
]
})
workflowPreferences.interactive = replanPref.replanMode === 'Interactive'
}
}
```

View File

@@ -52,22 +52,30 @@ Unified TDD workflow skill combining TDD planning (Red-Green-Refactor task chain
Before dispatching to phase execution, collect workflow preferences via AskUserQuestion:
```javascript
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否跳过所有确认步骤(自动模式)?",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test($ARGUMENTS)
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
if (autoYes) {
// 自动模式:跳过所有询问,使用默认值
workflowPreferences = { autoYes: true }
} else {
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否跳过所有确认步骤(自动模式)?",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
}
}
```

View File

@@ -68,22 +68,30 @@ Full pipeline and execute-only modes are triggered by skill name routing (see Mo
Before dispatching to phase execution, collect workflow preferences via AskUserQuestion:
```javascript
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否跳过所有确认步骤(自动模式)?",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test($ARGUMENTS)
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
if (autoYes) {
// 自动模式:跳过所有询问,使用默认值
workflowPreferences = { autoYes: true }
} else {
const prefResponse = AskUserQuestion({
questions: [
{
question: "是否跳过所有确认步骤(自动模式)?",
header: "Auto Mode",
multiSelect: false,
options: [
{ label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },
{ label: "Auto", description: "跳过所有确认,自动执行" }
]
}
]
})
workflowPreferences = {
autoYes: prefResponse.autoMode === 'Auto'
}
}
```