| Variant | Command | Scope | Pre-checks |
|---|---|---|---|
| --------- | --------- | ------- | ------------ |
| Fast | /fe-review-fast | Staged diff only | None |
| Full | /fe-review | Staged diff + local checks | ESLint + bundle size |
| Branch | /fe-review-branch | Full branch vs base | ESLint + bundle size |
Execute: bash scripts/emit-review-gate.sh PENDING
写入初始状态到 ~/.pipeline-ai-workflow/frontend-code-review/{branch_name}/state.json:
{
"_meta": {
"created_at": "<ISO timestamp>",
"updated_at": "<ISO timestamp>",
"namespace": "frontend-code-review/{branch_name}"
},
"status": "running",
"data": {
"review_mode": "dual",
"aggregate_gate": {
"executed": false,
"gate": "PENDING"
},
"iteration": 0,
"codex_thread_id": null,
"secondary_status": "pending"
}
}
若状态文件已存在且 status = running,输出警告并询问是否恢复上次会话。
Fail-closed 语义:进程在 Step 4.5 前崩溃时,gate 保持 PENDING 阻断合并。
根据变体获取 diff:
| Variant | 命令 |
|---|---|
| --------- | ------ |
| Fast / Full | git diff --cached --stat && git diff --cached |
| Branch | git diff {base_ref}...HEAD --stat && git diff {base_ref}...HEAD |
分析 diff,输出结构化变更信息:
统计变更概况(所有变体):
分类变更类型(所有变体):
| 类型 | 标识规则 |
|---|---|
| ------ | --------- |
feat | 新增文件、新增函数/类/接口 |
fix | 修改错误处理逻辑、bug 相关变更 |
refactor | 重命名、移动文件、提取函数 |
perf | 性能优化相关变更 |
安全扫描(Full / Branch):
| 检查项 | 匹配模式 |
|---|---|
| -------- | --------- |
| 硬编码密钥 | password=, secret=, token=, api_key= |
| 私钥文件 | .pem, .key, id_rsa |
| 敏感配置 | 数据库连接串、Redis 地址 |
| 大文件 | 单文件变更 > 1000 行 |
输出两份变量:
DIFF_STAT(结构化摘要,供 Codex prompt 注入和安全聚合):
{
"summary": { "files_changed": 12, "insertions": 345, "deletions": 128, "risk_level": "medium" },
"file_categories": {
"source_code": ["src/components/Button.tsx"],
"tests": [],
"config": [],
"dependencies": []
},
"change_types": { "feat": { "files": ["..."], "description": "..." } },
"security_findings": [
{ "severity": "warning", "file": "src/api/client.ts", "line": 9, "finding": "..." }
]
}
RAW_DIFF(完整 git diff 原文,供 Step 3 副审使用):直接保存上方 diff 命令的完整文本输出,不做任何裁剪或结构化处理。
探测 lint / bundle 命令(读取 package.json):
package.json scripts 字段,按优先级匹配:lint → lint:fix → eslint → eslint srcsize → bundlesize → size-limit.bundlesizerc / .size-limit.json / size-limit.config.jsdependencies 中匹配 react/vue/svelte/solid,存为 FRAMEWORK执行检查:
# ESLint(含 jsx-a11y plugin,如已安装)
{LINT_COMMAND}
# Bundle size(仅当配置文件存在时执行,否则静默跳过)
{BUNDLE_SIZE_COMMAND}
结果存为 LOCAL_CHECKS,注入 Step 3 Codex prompt。
Case A: First review(无 --continue)
单条消息并行启动两个 reviewer:
1. Codex MCP(主审,阻塞)
参考 references/retry-executor.md 执行重试包裹:
action_type: api_call,retry_policy: default(3 次,指数退避),timeout_seconds: 120on_failure: return_error(降级模式,不阻塞)调用 mcp__codex__codex,按变体选择 prompt 模板:
references/codex-prompt-fast.mdreferences/codex-prompt-full.mdreferences/codex-prompt-branch.md注入变量:
CHANGED_FILES ← DIFF_STAT.file_categoriesDIFF_STAT ← Step 1 summaryLOCAL_CHECKS ← Step 2 lint + bundle 结果(Full/Branch only)FRAMEWORK ← 从 package.json 检测security_findings 非空,追加到 prompt Focus Area保存返回的 threadId,更新状态文件:
{ "data": { "codex_thread_id": "<threadId>", "iteration": 1 } }
2. Reviewer Framework(副审,非阻塞后台)
参考 references/reviewer-framework.md 执行:
target_content: {RAW_DIFF}
review_dimensions: ["typescript", "async-error", "code-structure", "naming", "component-design", "dry-reuse", "state-management", "security", "imports", "comments", "accessibility", "hooks-correctness", "memory-leak", "null-safety", "css-quality", "async-race"]
severity_threshold: minor
output_format: json
Fallback 级联:
references/reviewer-framework.md 执行(默认)pr-review-toolkit:code-reviewer(framework 执行失败时)Case B: Loop review(有 --continue)
mcp__codex__codex-reply(threadId),使用 references/review-common.md § Re-review Prompt TemplateCodex 为阻塞主审,reviewer-framework 后台非阻塞运行:
| Secondary 状态 | 处理方式 |
|---|---|
| ---------------- | --------- |
| Codex 前完成 | 纳入 Step 4 聚合 |
| Codex 后、precommit 前完成 | 在 pre-precommit checkpoint 调和 |
| precommit 时仍在运行 | 以 Codex gate 为准;若迟到结果含 P0/P1 → 重开 fix→re-review loop |
| 失败/超时 | Codex 单审模式 + ⚠️ secondary unavailable 警告 |
来源:Codex + reviewer-framework + Step 1 安全发现。
详细聚合规则(severity 映射、去重算法、降级矩阵)见 references/review-common.md § Three-Source Aggregation。
[severity] file:line — description → fix [source: ...]file + canonical_issue_text(行号 ±5 容差),保留最高严重级别codex | framework | diff-analyzer | both | all输出示例:
| 文件:行 | 问题 | 修复建议 | 来源 |
|---|---|---|---|
| --------- | ------ | --------- | ------ |
src/components/UserCard.tsx:42 | dangerouslySetInnerHTML 接收未净化的 userInput | 使用 DOMPurify.sanitize() 净化后传入 | codex |
| 文件:行 | 问题 | 修复建议 | 来源 |
|---|---|---|---|
| --------- | ------ | --------- | ------ |
src/utils/list.tsx:18 | 大列表未虚拟化,500+ 条目时将卡顿 | 使用 react-window | framework |
src/api/client.ts:9 | API key 暴露在客户端 bundle | 移至服务端环境变量 | diff-analyzer |
| 文件:行 | 问题 | 修复建议 | 来源 |
|---|---|---|---|
| --------- | ------ | --------- | ------ |
src/styles/modal.css:7 | magic z-index: 9999 | 使用 CSS 变量 --z-modal | both |
| 文件:行 | 问题 | 修复建议 | 来源 |
|---|---|---|---|
| --------- | ------ | --------- | ------ |
src/components/Button.tsx:3 | prop 类型可从 string 收窄为 ButtonVariant | 更新类型定义 | codex |
Execute: bash scripts/emit-review-gate.sh READY or bash scripts/emit-review-gate.sh BLOCKED
更新状态文件 ~/.pipeline-ai-workflow/frontend-code-review/{branch_name}/state.json:
{
"data": {
"aggregate_gate": {
"executed": true,
"gate": "READY | BLOCKED",
"source": "codex+framework | codex-only | framework-only",
"findings_count": { "P0": 0, "P1": 0, "P2": 2, "Nit": 1 }
},
"iteration": 1
}
}
输出 sentinel:
✅ Ready — READY(无 P0/P1)⛔ Blocked — BLOCKED(有 P0/P1)⚠️ BLOCKED → fix → re-review → ... → ✅ READY ⚠️
BLOCKED → 修复 P0/P1 → /fe-review-fast --continue → 重复直到 READY。
READY + P2/Nit → 批量修复 → 1 次 Codex --continue 验证 → 评估(见 references/review-common.md § P2/Nit Post-Ready Sweep)。
Loop 终止规则见 references/review-common.md § Loop Termination Rules。
precommit 前调和待定副审结果:
| 条件 | 处理方式 |
|---|---|
| ------ | --------- |
| reviewer-framework 完成 + 有 P0/P1 | 重新 emit BLOCKED → fix → re-review |
| reviewer-framework 完成 + 无 P0/P1 | 联合聚合 → 继续 precommit |
| reviewer-framework 仍在运行 | 以 Codex gate 为准;迟到 P0/P1 → 重开 loop |
references/review-common.mdreferences/retry-executor.mdreferences/reviewer-framework.mdreferences/codex-prompt-fast.mdreferences/codex-prompt-full.mdreferences/codex-prompt-branch.md共 3 个版本