From 292cfec96d8a308b172505cee38954d1269afb75 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 5 Jun 2026 01:56:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E6=95=B4=E7=90=86=20Code=20Review?= =?UTF-8?q?=20=E5=80=99=E9=81=B8=E5=88=86=E9=A1=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/messages/en.json | 170 ++++++++++++ apps/web/messages/zh-TW.json | 170 ++++++++++++ .../web/src/app/[locale]/code-review/page.tsx | 255 +++++++++--------- .../security-mirror-progress-guard.py | 26 +- 4 files changed, 480 insertions(+), 141 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 233dde611..76bbb50dc 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -83,6 +83,176 @@ "zhTW": "繁體中文", "en": "繁中" }, + "codeReview": { + "header": { + "eyebrow": "AWOOOI 程式碼審查", + "title": "AI 程式碼審查控制面", + "subtitle": "Hermes、OpenClaw、Elephant Alpha 與 NemoTron 只做審查、分級與候選整理;修正、推版與主機操作仍留在人工閘門後面。", + "evidenceLink": "查看 AwoooP 執行紀錄" + }, + "handoff": { + "eyebrow": "Code Review → Codex", + "title": "審查後 Coding 工作橋接", + "subtitle": "審查結論先變成可追溯的 Codex 工作草稿;真正修改、推版、主機操作與來源切換仍留在人工閘門後面。", + "lanes": { + "draftable": { + "title": "可交給 Codex 起草", + "metric": "4 類", + "detail": "前端體驗、測試補洞、文件同步、低風險重構。", + "guard": "只建立草稿修正與驗證清單。" + }, + "approvalRequired": { + "title": "需人工批准後接手", + "metric": "3 類", + "detail": "高風險程式路徑、部署流程、跨專案設定。", + "guard": "先有人控範圍、回滾條件與證據。" + }, + "blocked": { + "title": "禁止自動轉工作", + "metric": "5 條", + "detail": "Kali 主機變更、掃描、正式推版、主要來源切換、執行期閘門。", + "guard": "維持 Gate 0 與獨立人工批准。" + } + } + }, + "candidateQueue": { + "title": "Codex 工作候選分類", + "subtitle": "候選只代表可整理成任務草稿;人工批准前不自動改 code、不自動 merge、不自動部署。", + "columns": { + "id": "編號", + "track": "分類", + "finding": "可接線內容", + "handoff": "Codex 交付物", + "gate": "批准條件", + "state": "狀態" + }, + "items": { + "frontendExperience": { + "track": "前端體驗", + "finding": "版面密度、手機寬度、文字層級、水平溢出。", + "handoff": "起草 UI 修正、截圖證據與 production smoke 清單。", + "gate": "人工確認 scope" + }, + "testCoverage": { + "track": "測試補洞", + "finding": "IwoooS 邊界、禁用動作、進度口徑、i18n drift。", + "handoff": "補 guard、smoke test 或 fixture,不碰 runtime。", + "gate": "不得碰 runtime" + }, + "documentationSync": { + "track": "文件同步", + "finding": "LOGBOOK、總帳、部署證據、平行工作同步。", + "handoff": "整理已驗證事實與下一步,不寫未驗證結論。", + "gate": "證據已回讀" + }, + "lowRiskRefactor": { + "track": "低風險重構", + "finding": "只限重複 UI helper、型別命名、無行為變更的整理。", + "handoff": "提出小 patch、影響範圍與回退方式。", + "gate": "人工批准後才 coding" + }, + "runtimeBlocked": { + "track": "禁止轉派", + "finding": "Kali 更新、掃描、GitHub primary、正式部署、執行期閘門。", + "handoff": "維持只讀候選與人工閘門,不建立 Codex 任務。", + "gate": "獨立批准" + } + } + }, + "summaryCards": { + "source": { + "label": "來源", + "value": "gitea main", + "detail": "以只讀證據回看,不在前端暴露內網入口。" + }, + "trigger": { + "label": "觸發", + "value": "推送 / 手動", + "detail": "程式碼審查工作流。" + }, + "gate": { + "label": "閘門", + "value": "非阻擋 v1", + "detail": "危急與高風險優先顯示。" + }, + "report": { + "label": "報告", + "value": "Telegram + Actions", + "detail": "啟動卡片與完成卡片。" + } + }, + "approvalFlow": { + "title": "人工批准後才進入 Codex coding", + "steps": { + "candidate": { + "title": "候選", + "detail": "只讀審查結論。" + }, + "manualApproval": { + "title": "人工批准", + "detail": "確認 scope、風險與回退。" + }, + "codexTask": { + "title": "Codex 任務", + "detail": "只接被批准的工作項。" + }, + "patch": { + "title": "PR / patch", + "detail": "小範圍修改與證據。" + }, + "guards": { + "title": "Guard", + "detail": "測試、build、資安守門。" + }, + "deploy": { + "title": "Deploy", + "detail": "部署與 production 驗證。" + } + } + }, + "reviewFlow": { + "title": "審查流程", + "stages": { + "push": { + "label": "推送", + "state": "Gitea main" + }, + "start": { + "label": "啟動", + "state": "Telegram 卡片" + }, + "scan": { + "label": "掃描", + "state": "機密 / 毀滅性操作 / 差異檢查" + }, + "classify": { + "label": "分級", + "state": "危急 / 高 / 中 / 低" + }, + "report": { + "label": "回報", + "state": "Telegram 報告" + } + } + }, + "agents": { + "title": "Agent 分工", + "roles": { + "hermes": "變更摘要與規則脈絡", + "openclaw": "AI 程式碼審查編排", + "elephantAlpha": "風險分級與修復決策", + "nemotron": "高風險推理席位" + } + }, + "states": { + "candidate": "候選", + "blocked": "封鎖" + }, + "agentStates": { + "wired": "已接線", + "standby": "待命" + } + }, "demo": { "title": "AWOOOI 展示", "subtitle": "視覺驗收測試", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 233dde611..76bbb50dc 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -83,6 +83,176 @@ "zhTW": "繁體中文", "en": "繁中" }, + "codeReview": { + "header": { + "eyebrow": "AWOOOI 程式碼審查", + "title": "AI 程式碼審查控制面", + "subtitle": "Hermes、OpenClaw、Elephant Alpha 與 NemoTron 只做審查、分級與候選整理;修正、推版與主機操作仍留在人工閘門後面。", + "evidenceLink": "查看 AwoooP 執行紀錄" + }, + "handoff": { + "eyebrow": "Code Review → Codex", + "title": "審查後 Coding 工作橋接", + "subtitle": "審查結論先變成可追溯的 Codex 工作草稿;真正修改、推版、主機操作與來源切換仍留在人工閘門後面。", + "lanes": { + "draftable": { + "title": "可交給 Codex 起草", + "metric": "4 類", + "detail": "前端體驗、測試補洞、文件同步、低風險重構。", + "guard": "只建立草稿修正與驗證清單。" + }, + "approvalRequired": { + "title": "需人工批准後接手", + "metric": "3 類", + "detail": "高風險程式路徑、部署流程、跨專案設定。", + "guard": "先有人控範圍、回滾條件與證據。" + }, + "blocked": { + "title": "禁止自動轉工作", + "metric": "5 條", + "detail": "Kali 主機變更、掃描、正式推版、主要來源切換、執行期閘門。", + "guard": "維持 Gate 0 與獨立人工批准。" + } + } + }, + "candidateQueue": { + "title": "Codex 工作候選分類", + "subtitle": "候選只代表可整理成任務草稿;人工批准前不自動改 code、不自動 merge、不自動部署。", + "columns": { + "id": "編號", + "track": "分類", + "finding": "可接線內容", + "handoff": "Codex 交付物", + "gate": "批准條件", + "state": "狀態" + }, + "items": { + "frontendExperience": { + "track": "前端體驗", + "finding": "版面密度、手機寬度、文字層級、水平溢出。", + "handoff": "起草 UI 修正、截圖證據與 production smoke 清單。", + "gate": "人工確認 scope" + }, + "testCoverage": { + "track": "測試補洞", + "finding": "IwoooS 邊界、禁用動作、進度口徑、i18n drift。", + "handoff": "補 guard、smoke test 或 fixture,不碰 runtime。", + "gate": "不得碰 runtime" + }, + "documentationSync": { + "track": "文件同步", + "finding": "LOGBOOK、總帳、部署證據、平行工作同步。", + "handoff": "整理已驗證事實與下一步,不寫未驗證結論。", + "gate": "證據已回讀" + }, + "lowRiskRefactor": { + "track": "低風險重構", + "finding": "只限重複 UI helper、型別命名、無行為變更的整理。", + "handoff": "提出小 patch、影響範圍與回退方式。", + "gate": "人工批准後才 coding" + }, + "runtimeBlocked": { + "track": "禁止轉派", + "finding": "Kali 更新、掃描、GitHub primary、正式部署、執行期閘門。", + "handoff": "維持只讀候選與人工閘門,不建立 Codex 任務。", + "gate": "獨立批准" + } + } + }, + "summaryCards": { + "source": { + "label": "來源", + "value": "gitea main", + "detail": "以只讀證據回看,不在前端暴露內網入口。" + }, + "trigger": { + "label": "觸發", + "value": "推送 / 手動", + "detail": "程式碼審查工作流。" + }, + "gate": { + "label": "閘門", + "value": "非阻擋 v1", + "detail": "危急與高風險優先顯示。" + }, + "report": { + "label": "報告", + "value": "Telegram + Actions", + "detail": "啟動卡片與完成卡片。" + } + }, + "approvalFlow": { + "title": "人工批准後才進入 Codex coding", + "steps": { + "candidate": { + "title": "候選", + "detail": "只讀審查結論。" + }, + "manualApproval": { + "title": "人工批准", + "detail": "確認 scope、風險與回退。" + }, + "codexTask": { + "title": "Codex 任務", + "detail": "只接被批准的工作項。" + }, + "patch": { + "title": "PR / patch", + "detail": "小範圍修改與證據。" + }, + "guards": { + "title": "Guard", + "detail": "測試、build、資安守門。" + }, + "deploy": { + "title": "Deploy", + "detail": "部署與 production 驗證。" + } + } + }, + "reviewFlow": { + "title": "審查流程", + "stages": { + "push": { + "label": "推送", + "state": "Gitea main" + }, + "start": { + "label": "啟動", + "state": "Telegram 卡片" + }, + "scan": { + "label": "掃描", + "state": "機密 / 毀滅性操作 / 差異檢查" + }, + "classify": { + "label": "分級", + "state": "危急 / 高 / 中 / 低" + }, + "report": { + "label": "回報", + "state": "Telegram 報告" + } + } + }, + "agents": { + "title": "Agent 分工", + "roles": { + "hermes": "變更摘要與規則脈絡", + "openclaw": "AI 程式碼審查編排", + "elephantAlpha": "風險分級與修復決策", + "nemotron": "高風險推理席位" + } + }, + "states": { + "candidate": "候選", + "blocked": "封鎖" + }, + "agentStates": { + "wired": "已接線", + "standby": "待命" + } + }, "demo": { "title": "AWOOOI 展示", "subtitle": "視覺驗收測試", diff --git a/apps/web/src/app/[locale]/code-review/page.tsx b/apps/web/src/app/[locale]/code-review/page.tsx index f8ef6696e..369efbb00 100644 --- a/apps/web/src/app/[locale]/code-review/page.tsx +++ b/apps/web/src/app/[locale]/code-review/page.tsx @@ -13,97 +13,83 @@ import { FileCheck2, GitBranch, Gauge, + ListChecks, LockKeyhole, SearchCheck, ShieldCheck, + Workflow, } from 'lucide-react' +import { useTranslations } from 'next-intl' const agents = [ - { name: 'Hermes', role: '變更摘要與規則脈絡', state: 'wired' }, - { name: 'OpenClaw', role: 'AI 程式碼審查編排', state: 'wired' }, - { name: 'Elephant Alpha', role: '風險分級與修復決策', state: 'wired' }, - { name: 'NemoTron', role: '高風險推理席位', state: 'standby' }, + { name: 'Hermes', roleKey: 'hermes', state: 'wired' }, + { name: 'OpenClaw', roleKey: 'openclaw', state: 'wired' }, + { name: 'Elephant Alpha', roleKey: 'elephantAlpha', state: 'wired' }, + { name: 'NemoTron', roleKey: 'nemotron', state: 'standby' }, ] const stages = [ - { label: '推送', state: 'Gitea main' }, - { label: '啟動', state: 'Telegram 卡片' }, - { label: '掃描', state: '機密 / 毀滅性操作 / 差異檢查' }, - { label: '分級', state: '危急 / 高 / 中 / 低' }, - { label: '回報', state: 'Telegram 報告' }, + { key: 'push' }, + { key: 'start' }, + { key: 'scan' }, + { key: 'classify' }, + { key: 'report' }, ] -const agentStateLabel: Record = { - wired: '已接線', - standby: '待命', -} +const handoffFlags = [ + 'codex_handoff_mode=read_only_candidate', + 'codex_auto_coding_enabled=false', + 'runtime_execution_authorized=false', + 'production_deploy_authorized=false', +] const codexHandoffLanes = [ { + key: 'draftable', icon: Code2, - title: '可交給 Codex 起草', - metric: '4 類', - detail: '前端體驗、測試補洞、文件同步、低風險重構。', - guard: '只建立草稿修正與驗證清單。', className: 'border-emerald-500/30 bg-emerald-500/10 text-emerald-100', iconClassName: 'text-emerald-300', }, { + key: 'approvalRequired', icon: FileCheck2, - title: '需人工批准後接手', - metric: '3 類', - detail: '高風險程式路徑、部署流程、跨專案設定。', - guard: '先有人控範圍、回滾條件與證據。', className: 'border-amber-500/30 bg-amber-500/10 text-amber-100', iconClassName: 'text-amber-300', }, { + key: 'blocked', icon: LockKeyhole, - title: '禁止自動轉工作', - metric: '5 條', - detail: 'Kali 主機變更、掃描、正式推版、主要來源切換、執行期閘門。', - guard: '維持 Gate 0 與獨立人工批准。', className: 'border-rose-500/30 bg-rose-500/10 text-rose-100', iconClassName: 'text-rose-300', }, ] const codexCandidateWork = [ - { - id: 'CR-CX-01', - track: '前端體驗', - finding: '版面密度、手機寬度、文字層級', - handoff: 'Codex 起草 UI 修正與截圖證據', - gate: '人工確認 scope', - state: '候選', - }, - { - id: 'CR-CX-02', - track: '守門測試', - finding: 'IwoooS 邊界、禁用動作、進度口徑', - handoff: '補 guard / smoke test', - gate: '不得碰 runtime', - state: '候選', - }, - { - id: 'CR-CX-03', - track: '繁中紀錄', - finding: '部署證據、LOGBOOK、平行工作同步', - handoff: '整理已驗證事實', - gate: '不寫未驗證結論', - state: '候選', - }, - { - id: 'CR-CX-04', - track: '禁止轉派', - finding: 'Kali 更新、掃描、GitHub primary、正式部署', - handoff: '維持人工閘門', - gate: '獨立批准', - state: '封鎖', - }, + { id: 'CR-CX-01', key: 'frontendExperience', state: 'candidate' }, + { id: 'CR-CX-02', key: 'testCoverage', state: 'candidate' }, + { id: 'CR-CX-03', key: 'documentationSync', state: 'candidate' }, + { id: 'CR-CX-04', key: 'lowRiskRefactor', state: 'candidate' }, + { id: 'CR-BLOCK-01', key: 'runtimeBlocked', state: 'blocked' }, +] + +const approvalFlowSteps = [ + 'candidate', + 'manualApproval', + 'codexTask', + 'patch', + 'guards', + 'deploy', +] + +const summaryCards = [ + { key: 'source', icon: GitBranch, iconClassName: 'text-emerald-300' }, + { key: 'trigger', icon: Activity, iconClassName: 'text-sky-300' }, + { key: 'gate', icon: ShieldCheck, iconClassName: 'text-amber-300' }, + { key: 'report', icon: Gauge, iconClassName: 'text-lime-300' }, ] export default function CodeReviewPage({ params }: { params: { locale: string } }) { + const t = useTranslations('codeReview') const evidenceHref = `/${params.locale}/awooop/runs` return ( @@ -114,19 +100,17 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
- AWOOOI 程式碼審查 + {t('header.eyebrow')}
-

AI 程式碼審查控制面

-

- Hermes → OpenClaw → Elephant Alpha → NemoTron,只做審查與分級,不自動推版。 -

+

{t('header.title')}

+

{t('header.subtitle')}

- 查看 AwoooP 執行紀錄 + {t('header.evidenceLink')} @@ -141,26 +125,17 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
- Code Review → Codex + {t('handoff.eyebrow')}
-

審查後 Coding 工作橋接

-

- 審查結論先變成可追溯的 Codex 工作草稿;真正修改、推版、主機操作與來源切換仍留在人工閘門後面。 -

+

{t('handoff.title')}

+

{t('handoff.subtitle')}

-
- codex_handoff_mode=read_only_candidate -
-
- codex_auto_coding_enabled=false -
-
- runtime_execution_authorized=false -
-
- production_deploy_authorized=false -
+ {handoffFlags.map((flag) => ( +
+ {flag} +
+ ))}
@@ -169,16 +144,16 @@ export default function CodeReviewPage({ params }: { params: { locale: string } const Icon = lane.icon return (
- {lane.metric} + {t(`handoff.lanes.${lane.key}.metric` as never)}
-
{lane.title}
-

{lane.detail}

-
{lane.guard}
+
{t(`handoff.lanes.${lane.key}.title` as never)}
+

{t(`handoff.lanes.${lane.key}.detail` as never)}

+
{t(`handoff.lanes.${lane.key}.guard` as never)}
{index < codexHandoffLanes.length - 1 ? ( ) : null} @@ -194,34 +169,51 @@ export default function CodeReviewPage({ params }: { params: { locale: string } >
-
Codex 工作候選佇列
-
- 草稿、待批、封鎖分流;不是自動執行佇列。 +
+ + {t('candidateQueue.title')}
+
{t('candidateQueue.subtitle')}
action_buttons_allowed=false
+
+ {t('candidateQueue.columns.id')} + {t('candidateQueue.columns.track')} + {t('candidateQueue.columns.finding')} + {t('candidateQueue.columns.handoff')} + {t('candidateQueue.columns.gate')} + {t('candidateQueue.columns.state')} +
{codexCandidateWork.map((item) => (
{item.id} - {item.track} - {item.finding} - {item.handoff} - {item.gate} + + {t(`candidateQueue.items.${item.key}.track` as never)} + + + {t(`candidateQueue.items.${item.key}.finding` as never)} + + + {t(`candidateQueue.items.${item.key}.handoff` as never)} + + + {t(`candidateQueue.items.${item.key}.gate` as never)} + - {item.state} + {t(`states.${item.state}` as never)}
))} @@ -229,37 +221,34 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
-
-
- - 來源 -
-
gitea main
-
以只讀證據回看,不在前端暴露內網入口
+ {summaryCards.map((card) => { + const Icon = card.icon + return ( +
+
+ + {t(`summaryCards.${card.key}.label` as never)} +
+
{t(`summaryCards.${card.key}.value` as never)}
+
{t(`summaryCards.${card.key}.detail` as never)}
+
+ ) + })} +
+ +
+
+ + {t('approvalFlow.title')}
-
-
- - 觸發 -
-
推送 / 手動
-
程式碼審查工作流
-
-
-
- - 閘門 -
-
非阻擋 v1
-
危急 / 高風險優先顯示
-
-
-
- - 報告 -
-
Telegram + Actions
-
啟動卡片與完成卡片
+
+ {approvalFlowSteps.map((step, index) => ( +
+
{String(index + 1).padStart(2, '0')}
+
{t(`approvalFlow.steps.${step}.title` as never)}
+
{t(`approvalFlow.steps.${step}.detail` as never)}
+
+ ))}
@@ -267,17 +256,17 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
- 審查流程 + {t('reviewFlow.title')}
{stages.map((stage, index) => (
{String(index + 1).padStart(2, '0')} - {stage.label} - {stage.state} + {t(`reviewFlow.stages.${stage.key}.label` as never)} + {t(`reviewFlow.stages.${stage.key}.state` as never)}
))}
@@ -286,7 +275,7 @@ export default function CodeReviewPage({ params }: { params: { locale: string }
- Agent 分工 + {t('agents.title')}
{agents.map((agent) => ( @@ -295,9 +284,9 @@ export default function CodeReviewPage({ params }: { params: { locale: string } className="grid grid-cols-[8rem_1fr_4.5rem] items-center rounded border border-gray-800 bg-gray-950 px-3 py-2 text-sm" > {agent.name} - {agent.role} + {t(`agents.roles.${agent.roleKey}` as never)} - {agentStateLabel[agent.state] ?? agent.state} + {t(`agentStates.${agent.state}` as never)}
))} diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 87d875cb6..dacfa906c 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -8297,24 +8297,34 @@ def validate(root: Path) -> None: source_text, '', ) + code_review_surface_text = "\n".join( + [ + code_review_page, + "\n".join(collect_string_values(web_messages_zh.get("codeReview", {}))), + ] + ) for text in [ 'data-testid="code-review-codex-handoff-board"', 'data-testid="code-review-codex-candidate-work"', - "審查後 Coding 工作橋接", - "Codex 工作草稿", - "可交給 Codex 起草", - "需人工批准後接手", - "禁止自動轉工作", "codex_handoff_mode=read_only_candidate", "codex_auto_coding_enabled=false", "runtime_execution_authorized=false", "production_deploy_authorized=false", "action_buttons_allowed=false", "CR-CX-04", - "Kali 更新、掃描、GitHub primary、正式部署", - "維持人工閘門", ]: - assert_text_contains("code_review_page.codex_handoff_read_only", code_review_page, text) + assert_text_contains("code_review_page.codex_handoff_structure", code_review_page, text) + for text in [ + "審查後 Coding 工作橋接", + "Codex 工作草稿", + "可交給 Codex 起草", + "需人工批准後接手", + "禁止自動轉工作", + "前端體驗、測試補洞、文件同步、低風險重構", + "Kali 更新、掃描、GitHub primary、正式部署", + "維持只讀候選與人工閘門", + ]: + assert_text_contains("code_review_page.codex_handoff_read_only", code_review_surface_text, text) assert_text_contains("iwooos_page.surface_connection_board", iwooos_projection_page, "surfaceConnectionStatuses") assert_text_contains("iwooos_page.surface_connection_testid", iwooos_projection_page, 'data-testid="iwooos-surface-connection-board"') assert_text_contains("iwooos_page.surface_connection_embedded", iwooos_projection_page, "embeddedBridge")