orchestrate-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOrchestrate Review
编排审查流程
Multi-pass code review with parallel Task agents, finding aggregation, and iteration until clean.
通过并行Task agents执行多轮代码审查,汇总问题并迭代直至无问题。
Scope-Based Specialist Selection
基于范围的专家选择
Select conditional specialists based on the review scope:
- User request: Detect signals from content user refers to (files, directory, module)
- Workflow (Phase 9): Detect signals from changed files only
- Project audit: Detect signals from project structure as a whole
根据审查范围选择对应的专业审查人员:
- 用户请求:从用户提及的内容(文件、目录、模块)中检测信号
- 工作流(第9阶段):仅从变更文件中检测信号
- 项目审计:从整个项目结构中检测信号
Review Passes
审查轮次
Spawn parallel Task agents (model: ), one per pass:
general-purposesonnet启动并行的 Task agents(模型:),每个轮次对应一个agent:
general-purposesonnetCore (Always)
核心轮次(必选)
javascript
const corePasses = [
{ id: 'code-quality', role: 'code quality reviewer',
focus: ['Style and consistency', 'Best practices', 'Bugs and logic errors', 'Error handling', 'Maintainability', 'Duplication'] },
{ id: 'security', role: 'security reviewer',
focus: ['Auth/authz flaws', 'Input validation', 'Injection risks', 'Secrets exposure', 'Insecure defaults'] },
{ id: 'performance', role: 'performance reviewer',
focus: ['N+1 queries', 'Blocking operations', 'Hot path inefficiencies', 'Memory leaks'] },
{ id: 'test-coverage', role: 'test coverage reviewer',
focus: ['Missing tests', 'Edge case coverage', 'Test quality', 'Integration needs', 'Mock appropriateness'] }
];javascript
const corePasses = [
{ id: 'code-quality', role: 'code quality reviewer',
focus: ['Style and consistency', 'Best practices', 'Bugs and logic errors', 'Error handling', 'Maintainability', 'Duplication'] },
{ id: 'security', role: 'security reviewer',
focus: ['Auth/authz flaws', 'Input validation', 'Injection risks', 'Secrets exposure', 'Insecure defaults'] },
{ id: 'performance', role: 'performance reviewer',
focus: ['N+1 queries', 'Blocking operations', 'Hot path inefficiencies', 'Memory leaks'] },
{ id: 'test-coverage', role: 'test coverage reviewer',
focus: ['Missing tests', 'Edge case coverage', 'Test quality', 'Integration needs', 'Mock appropriateness'] }
];Conditional (Signal-Based)
条件轮次(基于信号)
javascript
if (signals.hasDb) passes.push({ id: 'database', role: 'database specialist',
focus: ['Query performance', 'Indexes/transactions', 'Migration safety', 'Data integrity'] });
if (signals.needsArchitecture) passes.push({ id: 'architecture', role: 'architecture reviewer',
focus: ['Module boundaries', 'Dependency direction', 'Cross-layer coupling', 'Pattern consistency'] });
if (signals.hasApi) passes.push({ id: 'api', role: 'api designer',
focus: ['REST conventions', 'Error/status consistency', 'Pagination/filters', 'Versioning'] });
if (signals.hasFrontend) passes.push({ id: 'frontend', role: 'frontend specialist',
focus: ['Component boundaries', 'State management', 'Accessibility', 'Render performance'] });
if (signals.hasBackend) passes.push({ id: 'backend', role: 'backend specialist',
focus: ['Service boundaries', 'Domain logic', 'Concurrency/idempotency', 'Background job safety'] });
if (signals.hasDevops) passes.push({ id: 'devops', role: 'devops reviewer',
focus: ['CI/CD safety', 'Secrets handling', 'Build/test pipelines', 'Deploy config'] });javascript
if (signals.hasDb) passes.push({ id: 'database', role: 'database specialist',
focus: ['Query performance', 'Indexes/transactions', 'Migration safety', 'Data integrity'] });
if (signals.needsArchitecture) passes.push({ id: 'architecture', role: 'architecture reviewer',
focus: ['Module boundaries', 'Dependency direction', 'Cross-layer coupling', 'Pattern consistency'] });
if (signals.hasApi) passes.push({ id: 'api', role: 'api designer',
focus: ['REST conventions', 'Error/status consistency', 'Pagination/filters', 'Versioning'] });
if (signals.hasFrontend) passes.push({ id: 'frontend', role: 'frontend specialist',
focus: ['Component boundaries', 'State management', 'Accessibility', 'Render performance'] });
if (signals.hasBackend) passes.push({ id: 'backend', role: 'backend specialist',
focus: ['Service boundaries', 'Domain logic', 'Concurrency/idempotency', 'Background job safety'] });
if (signals.hasDevops) passes.push({ id: 'devops', role: 'devops reviewer',
focus: ['CI/CD safety', 'Secrets handling', 'Build/test pipelines', 'Deploy config'] });Signal Detection
信号检测
javascript
const signals = {
hasDb: files.some(f => /(db|migrations?|schema|prisma|typeorm|sql)/i.test(f)),
hasApi: files.some(f => /(api|routes?|controllers?|handlers?)/i.test(f)),
hasFrontend: files.some(f => /\.(tsx|jsx|vue|svelte)$/.test(f)),
hasBackend: files.some(f => /(server|backend|services?|domain)/i.test(f)),
hasDevops: files.some(f => /(\.github\/workflows|Dockerfile|k8s|terraform)/i.test(f)),
needsArchitecture: files.length > 20 // 20+ files typically indicates cross-module changes
};javascript
const signals = {
hasDb: files.some(f => /(db|migrations?|schema|prisma|typeorm|sql)/i.test(f)),
hasApi: files.some(f => /(api|routes?|controllers?|handlers?)/i.test(f)),
hasFrontend: files.some(f => /\.(tsx|jsx|vue|svelte)$/.test(f)),
hasBackend: files.some(f => /(server|backend|services?|domain)/i.test(f)),
hasDevops: files.some(f => /(\.github\/workflows|Dockerfile|k8s|terraform)/i.test(f)),
needsArchitecture: files.length > 20 // 20+ files typically indicates cross-module changes
};Task Prompt Template
任务提示模板
You are a ${pass.role}. Review these changed files:
${files.join('\n')}
Focus: ${pass.focus.map(f => `- ${f}`).join('\n')}
Return JSON:
{
"pass": "${pass.id}",
"findings": [{
"file": "path.ts",
"line": 42,
"severity": "critical|high|medium|low",
"description": "Issue",
"suggestion": "Fix",
"confidence": "high|medium|low",
"falsePositive": false
}]
}
Example findings (diverse passes and severities):
// Security - high severity
{ "file": "src/auth/login.ts", "line": 89, "severity": "high",
"description": "Password comparison uses timing-vulnerable string equality",
"suggestion": "Use crypto.timingSafeEqual() instead of ===",
"confidence": "high", "falsePositive": false }
// Code quality - medium severity
{ "file": "src/utils/helpers.ts", "line": 45, "severity": "medium",
"description": "Duplicated validation logic exists in src/api/validators.ts:23",
"suggestion": "Extract to shared lib/validation.ts",
"confidence": "high", "falsePositive": false }
// Performance - low severity
{ "file": "src/config.ts", "line": 12, "severity": "low",
"description": "Magic number 3600 should be named constant",
"suggestion": "const CACHE_TTL_SECONDS = 3600;",
"confidence": "medium", "falsePositive": false }
// False positive example
{ "file": "src/crypto/hash.ts", "line": 78, "severity": "high",
"description": "Non-constant time comparison",
"suggestion": "N/A - intentional for non-secret data",
"confidence": "low", "falsePositive": true }
Report all issues with confidence >= medium. Empty findings array if clean.你是一名${pass.role}。请审查以下变更文件:
${files.join('\n')}
审查重点:${pass.focus.map(f => `- ${f}`).join('\n')}
返回JSON格式结果:
{
"pass": "${pass.id}",
"findings": [{
"file": "path.ts",
"line": 42,
"severity": "critical|high|medium|low",
"description": "Issue",
"suggestion": "Fix",
"confidence": "high|medium|low",
"falsePositive": false
}]
}
不同轮次和严重程度的问题示例:
// 安全 - 高严重程度
{ "file": "src/auth/login.ts", "line": 89, "severity": "high",
"description": "密码比较使用了存在时序漏洞的字符串相等判断",
"suggestion": "Use crypto.timingSafeEqual() instead of ===",
"confidence": "high", "falsePositive": false }
// 代码质量 - 中严重程度
{ "file": "src/utils/helpers.ts", "line": 45, "severity": "medium",
"description": "重复的验证逻辑存在于src/api/validators.ts:23",
"suggestion": "提取到共享的lib/validation.ts中",
"confidence": "high", "falsePositive": false }
// 性能 - 低严重程度
{ "file": "src/config.ts", "line": 12, "severity": "low",
"description": "魔法数字3600应定义为命名常量",
"suggestion": "const CACHE_TTL_SECONDS = 3600;",
"confidence": "medium", "falsePositive": false }
// 误报示例
{ "file": "src/crypto/hash.ts", "line": 78, "severity": "high",
"description": "非常量时间比较",
"suggestion": "不适用 - 针对非敏感数据的有意设计",
"confidence": "low", "falsePositive": true }
请报告所有置信度≥中等的问题。若无问题则返回空的findings数组。Aggregation
结果聚合
javascript
function aggregateFindings(results) {
const items = [];
for (const {pass, findings = []} of results) {
for (const f of findings) {
items.push({
id: `${pass}:${f.file}:${f.line}:${f.description}`,
pass, ...f,
status: f.falsePositive ? 'false-positive' : 'open'
});
}
}
// Deduplicate by id
const deduped = [...new Map(items.map(i => [i.id, i])).values()];
// Group by severity
const bySeverity = {critical: [], high: [], medium: [], low: []};
deduped.forEach(i => !i.falsePositive && bySeverity[i.severity || 'low'].push(i));
const totals = Object.fromEntries(Object.entries(bySeverity).map(([k, v]) => [k, v.length]));
return {
items: deduped,
bySeverity,
totals,
openCount: Object.values(totals).reduce((a, b) => a + b, 0)
};
}javascript
function aggregateFindings(results) {
const items = [];
for (const {pass, findings = []} of results) {
for (const f of findings) {
items.push({
id: `${pass}:${f.file}:${f.line}:${f.description}`,
pass, ...f,
status: f.falsePositive ? 'false-positive' : 'open'
});
}
}
// 根据id去重
const deduped = [...new Map(items.map(i => [i.id, i])).values()];
// 按严重程度分组
const bySeverity = {critical: [], high: [], medium: [], low: []};
deduped.forEach(i => !i.falsePositive && bySeverity[i.severity || 'low'].push(i));
const totals = Object.fromEntries(Object.entries(bySeverity).map(([k, v]) => [k, v.length]));
return {
items: deduped,
bySeverity,
totals,
openCount: Object.values(totals).reduce((a, b) => a + b, 0)
};
}Iteration Loop
迭代循环
Security Note: Fixes are applied by the orchestrator using standard Edit tool permissions. Critical/high severity findings should be reviewed before applying - do not blindly apply LLM-suggested fixes to security-sensitive code. The orchestrator validates each fix against the original issue.
javascript
// 5 iterations balances thoroughness vs cost; 1 stall (2 consecutive identical-hash iterations) indicates fixes aren't progressing
const MAX_ITERATIONS = 5, MAX_STALLS = 1;
let iteration = 1, stallCount = 0, lastHash = null;
while (iteration <= MAX_ITERATIONS) {
// 1. Spawn parallel Task agents
const results = await Promise.all(passes.map(pass => Task({
subagent_type: 'general-purpose',
model: 'sonnet',
prompt: /* see template above */
})));
// 2. Aggregate findings
const findings = aggregateFindings(results);
// 3. Check if done
if (findings.openCount === 0) {
workflowState.completePhase({ approved: true, iterations: iteration });
break;
}
// 4. Fix issues (severity order: critical → high → medium → low)
// Orchestrator reviews each suggestion before applying via Edit tool
for (const issue of [...findings.bySeverity.critical, ...findings.bySeverity.high,
...findings.bySeverity.medium, ...findings.bySeverity.low]) {
if (!issue.falsePositive) {
// Read file, locate issue.line, validate suggestion, apply via Edit tool
// For complex fixes, use simple-fixer agent pattern
}
}
// 5. Commit
exec(`git add . && git commit -m "fix: review feedback (iteration ${iteration})"`);
// 6. Post-iteration deslop
Task({ subagent_type: 'deslop:deslop-agent', model: 'sonnet' });
// 7. Stall detection
const hash = crypto.createHash('sha256')
.update(JSON.stringify(findings.items.filter(i => !i.falsePositive)))
.digest('hex');
stallCount = hash === lastHash ? stallCount + 1 : 0;
lastHash = hash;
// 8. Check limits
if (stallCount >= MAX_STALLS || iteration >= MAX_ITERATIONS) {
const reason = stallCount >= MAX_STALLS ? 'stall-detected' : 'iteration-limit';
console.log(`[BLOCKED] Review loop ended: ${reason}. Remaining: ${JSON.stringify(findings.totals)}`);
// Ask the user before advancing - do not silently proceed to delivery-validation
const question = `Review loop blocked (${reason}). Open issues remain. How should we proceed?`;
const response = AskUserQuestion({
questions: [{
question,
header: 'Review Blocked',
multiSelect: false,
options: [
{ label: 'Override and proceed', description: 'Advance to delivery-validation with unresolved issues (risky)' },
{ label: 'Abort workflow', description: 'Stop here; open issues must be fixed manually' }
]
}]
});
// AskUserQuestion returns { answers: { [questionText]: selectedLabel } }
const choice = response.answers?.[question] ?? response[question];
if (choice === 'Override and proceed') {
workflowState.completePhase({
approved: false, blocked: true, overridden: true,
reason, remaining: findings.totals
});
} else {
workflowState.failPhase(`Review blocked: ${reason}. ${JSON.stringify(findings.totals)} issues remain.`);
}
break;
}
iteration++;
}安全注意:修复操作由编排器使用标准Edit工具权限执行。在应用之前,应先审查严重程度为关键/高的问题修复建议——不要盲目应用LLM针对安全敏感代码提出的修复方案。编排器会根据原始问题验证每个修复方案。
javascript
// 5次迭代平衡了审查全面性与成本;1次停滞(连续2次迭代的哈希值相同)表示修复无进展
const MAX_ITERATIONS = 5, MAX_STALLS = 1;
let iteration = 1, stallCount = 0, lastHash = null;
while (iteration <= MAX_ITERATIONS) {
// 1. 启动并行Task agents
const results = await Promise.all(passes.map(pass => Task({
subagent_type: 'general-purpose',
model: 'sonnet',
prompt: /* 参见上方模板 */
})));
// 2. 聚合问题
const findings = aggregateFindings(results);
// 3. 检查是否完成
if (findings.openCount === 0) {
workflowState.completePhase({ approved: true, iterations: iteration });
break;
}
// 4. 修复问题(按严重程度顺序:关键 → 高 → 中 → 低)
// 编排器在通过Edit工具应用前会审查每个建议
for (const issue of [...findings.bySeverity.critical, ...findings.bySeverity.high,
...findings.bySeverity.medium, ...findings.bySeverity.low]) {
if (!issue.falsePositive) {
// 读取文件,定位问题行,验证建议,通过Edit工具应用
// 对于复杂修复,使用simple-fixer agent模式
}
}
// 5. 提交变更
exec(`git add . && git commit -m "fix: review feedback (iteration ${iteration})"`);
// 6. 迭代后清理
Task({ subagent_type: 'deslop:deslop-agent', model: 'sonnet' });
// 7. 停滞检测
const hash = crypto.createHash('sha256')
.update(JSON.stringify(findings.items.filter(i => !i.falsePositive)))
.digest('hex');
stallCount = hash === lastHash ? stallCount + 1 : 0;
lastHash = hash;
// 8. 检查限制
if (stallCount >= MAX_STALLS || iteration >= MAX_ITERATIONS) {
const reason = stallCount >= MAX_STALLS ? 'stall-detected' : 'iteration-limit';
console.log(`[受阻] 审查循环结束:${reason}。剩余问题:${JSON.stringify(findings.totals)}`);
// 推进前询问用户——不要直接进入交付验证阶段
const question = `审查循环受阻(${reason})。仍存在未解决问题。我们应如何处理?`;
const response = AskUserQuestion({
questions: [{
question,
header: '审查受阻',
multiSelect: false,
options: [
{ label: '强制推进', description: '带着未解决问题进入交付验证阶段(存在风险)' },
{ label: '终止工作流', description: '在此停止;未解决问题需手动修复' }
]
}]
});
// AskUserQuestion返回 { answers: { [questionText]: selectedLabel } }
const choice = response.answers?.[question] ?? response[question];
if (choice === '强制推进') {
workflowState.completePhase({
approved: false, blocked: true, overridden: true,
reason, remaining: findings.totals
});
} else {
workflowState.failPhase(`审查受阻:${reason}。仍存在${JSON.stringify(findings.totals)}个问题。`);
}
break;
}
iteration++;
}Review Queue
审查队列
Store state at :
{stateDir}/review-queue-{timestamp}.jsonjson
{
"status": "open|resolved|blocked",
"scope": { "type": "diff", "files": ["..."] },
"passes": ["code-quality", "security"],
"items": [],
"iteration": 0,
"stallCount": 0
}Delete when approved. Keep when blocked for orchestrator inspection.
将状态存储在:
{stateDir}/review-queue-{timestamp}.jsonjson
{
"status": "open|resolved|blocked",
"scope": { "type": "diff", "files": ["..."] },
"passes": ["code-quality", "security"],
"items": [],
"iteration": 0,
"stallCount": 0
}审核通过后删除该文件。受阻时保留以便编排器检查。
Cross-Platform Compatibility
跨平台兼容性
This skill uses which is Claude Code syntax. For other platforms:
Task({ subagent_type: ... })| Platform | Equivalent Syntax |
|---|---|
| Claude Code | |
| OpenCode | |
| Codex CLI | |
The aggregation and iteration logic remains the same across platforms - only the agent spawning syntax differs.
该技能使用的是Claude Code语法。对于其他平台:
Task({ subagent_type: ... })| 平台 | 等效语法 |
|---|---|
| Claude Code | |
| OpenCode | |
| Codex CLI | |
聚合和迭代逻辑在各平台保持一致——仅agent启动语法不同。