From 738ab6889856d0776e8fa8febe804b0db7683b3e Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 5 Jul 2026 21:01:55 +0800 Subject: [PATCH] docs(review): add comprehensive project review 2026-07-05 --- ...2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md | 668 ++++++++++++++++++ 1 file changed, 668 insertions(+) create mode 100644 reports/REVIEW_REPORT_2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md diff --git a/reports/REVIEW_REPORT_2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md b/reports/REVIEW_REPORT_2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md new file mode 100644 index 0000000..1355472 --- /dev/null +++ b/reports/REVIEW_REPORT_2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md @@ -0,0 +1,668 @@ +# 2026-07-05 项目全面 Review 报告(真实复核版) + +> 生成时间:2026-07-05T20:59:15+08:00 +> 审查对象:`/home/long/project/gaokao-volunteer-system` +> 当前 HEAD:`4059f144c49398aec2fcc3040e639e1312061086` +> 审查方式:真实读取代码/CI/脚本/现有报告 + 本地门禁执行 + 静态扫描;未把历史报告当作当前事实。 +> 重要边界:本报告是代码库与本地门禁 review,不等同于线上真实支付、真实域名、真实用户流量验收。 +> 复验更新:已在报告初稿后补装前端依赖并复跑 `pnpm typecheck/lint/test/build`,结果已回写到 §1.2 / M0。 + +--- + +## 0. 总结结论 + +**结论:REQUEST_CHANGES / 不能宣称生产级完成。** + +本轮 review 发现的当前有效问题: + +| 严重级别 | 数量 | 摘要 | +|---|---:|---| +| HIGH | 4 | Admin 导航断链、React Admin mock 登录未接真实 JWT、前端 API client 未注入 Authorization、本地 Python 总门禁 mypy 失败 | +| MEDIUM | 4 | Chromatic token 未配置会阻断 CI、LHCI 启动/端口口径仍有漂移风险、dev-verify 100-case smoke 非阻塞导致主链路回归可能被降级为 warning、前端依赖缺失曾阻断本地 fresh gate(已补装并复验通过) | +| LOW | 2 | 文档中仍大量保留 mock/sandbox 历史语境,旧截图报告目录仍在仓库中易误导;部分静态扫描命中需后续清理白名单 | + +已确认的正向事实: + +- `main / origin / gitea / tksea` 在上一轮已同步到 `4059f14`,本轮 review 起点工作区为 `## main`。 +- `apps/web/src/types/api-generated.d.ts` 与 `apps/web/src/schemas/api-generated.ts` 当前 `any_count=0`。 +- `/health` dev readiness 改动已进入 HEAD,`settings_valid` 在 dev 环境允许占位密钥,但 prod fail-closed 仍由配置加载策略覆盖。 + +--- + +## 1. Gate 结果(当前真实输出) + +### 1.1 Python / 后端总门禁 + +命令来源:`/tmp/gaokao-review-gates-20260705.log`,由本轮执行: + +```bash +bash scripts/dev-verify.sh +``` + +结果:**FAIL**。关键输出: + +```text +admin/routes/sprint3_api.py:292: error: Incompatible types in assignment (expression has type "str", variable has type "Literal['pending', 'in_progress', 'approved', 'rejected', 'changes_requested']") [assignment] +data/cli_compat_share.py:43: error: Item "None" of "_ArgumentGroup | None" has no attribute "_group_actions" [union-attr] +data/cli_compat_share.py:44: error: Item "Action" of "Action | Any" has no attribute "add_parser" [union-attr] +data/share/poster.py:123: error: Argument "candidate_name" to "PosterPayload" has incompatible type "str | None"; expected "str" [arg-type] +data/share/poster.py:273: error: Incompatible return value type (got "FreeTypeFont", expected "ImageFont") [return-value] +data/share/poster.py:274: error: Incompatible return value type (got "FreeTypeFont | ImageFont", expected "ImageFont") [return-value] +data/share/poster.py:319: error: Incompatible return value type (got "float", expected "int") [return-value] +data/share/poster.py:324: error: Incompatible return value type (got "float", expected "int") [return-value] +data/share/poster.py:329: error: Library stubs not installed for "qrcode" [import-untyped] +Found 9 errors in 3 files (checked 268 source files) +DEV_VERIFY_EXIT=1 +``` + +影响: + +- 这不是单测功能失败,而是类型门禁失败;按项目质量标准不能用“pytest 局部通过”覆盖。 +- 失败集中在 poster / report 相关类型与缺失 third-party stubs,说明分享海报链路仍存在类型质量债。 + +### 1.2 前端本地门禁 + +第一轮执行结果:**BLOCKED**,原因是本地缺少 `node_modules` / `turbo`,未进入真实业务门禁。随后已补执行: + +```bash +pnpm install --frozen-lockfile +pnpm typecheck +pnpm lint +pnpm test +pnpm build +``` + +复验结果:**PASS**。fresh evidence 来自 `/tmp/gaokao-frontend-gates-20260705.log`: + +```text +=== FRONTEND FRESH GATES START === +--- pnpm install --- +root node_modules exists +apps/web/node_modules exists +--- web typecheck --- +--- web lint --- +--- web test --- +--- web build --- + Tasks: 2 successful, 2 total + Tasks: 1 successful, 1 total +@gaokao/web:build: TOTAL │ 1.36 MB │ 393.60 KB │ ✅ +@gaokao/web:build: ✅ T-B-25 验证通过 +=== FRONTEND FRESH GATES END === +``` + +更新判断:前端本地 typecheck/lint/test/build 当前已有 fresh gate 证据;原 H5 从 HIGH blocker 降级为 MEDIUM 环境/可复现性问题。仍需注意:这不自动证明 Playwright e2e、Chromatic、LHCI 或真实浏览器视觉验收已全部闭环。 + +--- + +## 2. HIGH Findings + +### H1 · 后台导航 `/admin/review` 真实断链 + +**证据:** + +`apps/web/src/layouts/AdminLayout.tsx` 注册了 `/admin/review`: + + - L12: `const adminNavItems = [` + - L13: ` { to: '/admin', labelKey: 'admin.nav.dashboard', icon: Home },` + - L14: ` { to: '/admin/orders', labelKey: 'admin.nav.orders', icon: FileText },` + - L15: ` { to: '/admin/cases', labelKey: 'admin.nav.cases', icon: Users },` + - L16: ` { to: '/admin/share-links', labelKey: 'admin.nav.shareLinks', icon: Link2 },` + - L17: ` { to: '/admin/score-lines', labelKey: 'admin.nav.scoreLines', icon: Database },` + - L18: ` { to: '/admin/rank-estimator', labelKey: 'admin.nav.rankEstimator', icon: TrendingUp },` + - L19: ` { to: '/admin/majors', labelKey: 'admin.nav.majors', icon: BarChart3 },` + - L20: ` { to: '/admin/schools', labelKey: 'admin.nav.schools', icon: School },` + - L21: ` { to: '/admin/review', labelKey: 'admin.nav.review', icon: ShieldCheck },` + - L22: ` { to: '/admin/posters', labelKey: 'admin.nav.posters', icon: BarChart3 },` + - L23: `] as const;` + +`apps/web/src/router.tsx` 的 `/admin` 子路由没有 `review`: + + - L64: ` { path: '/admin/login', element: },` + - L65: ` { path: '/403', element: },` + - L66: ` {` + - L67: ` path: '/admin',` + - L68: ` element: (` + - L69: ` ` + - L70: ` ` + - L71: ` ` + - L72: ` ),` + - L73: ` children: [` + - L74: ` { index: true, element: },` + - L75: ` { path: 'orders', element: },` + - L76: ` { path: 'orders/:orderId', element: },` + - L77: ` { path: 'cases', element: },` + - L78: ` { path: 'cases/:caseId', element: },` + - L79: ` { path: 'share-links', element: },` + - L80: ` { path: 'share-links/:code', element: },` + - L81: ` { path: 'posters', element: },` + - L82: ` { path: 'score-lines', element: },` + - L83: ` { path: 'rank-estimator', element: },` + - L84: ` { path: 'majors', element: },` + - L85: ` { path: 'schools', element: },` + - L86: ` { path: 'error', element: },` + - L87: ` { path: '*', element: },` + - L88: ` ],` + +静态路由对照结果: + +```text +nav=['/admin', '/admin/orders', '/admin/cases', '/admin/share-links', '/admin/score-lines', '/admin/rank-estimator', '/admin/majors', '/admin/schools', '/admin/review', '/admin/posters'] +admin_routes=['/admin/*', '/admin/cases', '/admin/cases/:caseId', '/admin/error', '/admin/majors', '/admin/orders', '/admin/orders/:orderId', '/admin/posters', '/admin/rank-estimator', '/admin/schools', '/admin/score-lines', '/admin/share-links', '/admin/share-links/:code'] +missing=['/admin/review'] +``` + +**影响:** 后台用户点击“复核 / Review”会进入 NotFound,属于真实用户路径断裂。 +**建议修复:** 新增 `/admin/review` 子路由并接入已有 Review 页面或移除导航项;新增 e2e 遍历所有 admin nav links,断言不落入 NotFound。 + +--- + +### H2 · React Admin 登录仍是前端 mock,未接 `/api/auth/login` + +**证据:** + +`apps/web/src/pages/admin/LoginPage.tsx` 只校验固定验证码 `123456`,直接写 user store: + + - L53: ` const onSubmit = async (values: LoginFormValues): Promise => {` + - L54: ` setSubmitError(null);` + - L55: ` await new Promise((resolve) => window.setTimeout(resolve, 80));` + - L56: `` + - L57: ` if (values.code !== '123456') {` + - L58: ` setSubmitError(intl.formatMessage({ id: 'admin.login.mockCodeError' }));` + - L59: ` return;` + - L60: ` }` + - L61: `` + - L62: ` setUser({` + - L63: ` id: `admin-${values.phone.slice(-4)}`,` + - L64: ` name: intl.formatMessage({ id: 'admin.login.mockAdminName' }, { suffix: values.phone.slice(-4) }),` + - L65: ` phone: values.phone,` + - L66: ` role: 'admin',` + - L67: ` });` + - L68: ` toast.success(intl.formatMessage({ id: 'admin.login.toastSuccess' }), {` + - L69: ` description: intl.formatMessage({ id: 'admin.login.toastSuccessDescription' }),` + - L70: ` });` + - L71: ` void navigate(from, { replace: true });` + - L72: ` };` + - L102: `

` + - L103: ` ` + - L104: `

` + - L105: `

` + - L106: ` ` + - L107: `

` + - L132: `
` + - L133: `