31 KiB
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。/healthdev readiness 改动已进入 HEAD,settings_valid在 dev 环境允许占位密钥,但 prod fail-closed 仍由配置加载策略覆盖。
1. Gate 结果(当前真实输出)
1.1 Python / 后端总门禁
命令来源:/tmp/gaokao-review-gates-20260705.log,由本轮执行:
bash scripts/dev-verify.sh
结果:FAIL。关键输出:
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,未进入真实业务门禁。随后已补执行:
pnpm install --frozen-lockfile
pnpm typecheck
pnpm lint
pnpm test
pnpm build
复验结果:PASS。fresh evidence 来自 /tmp/gaokao-frontend-gates-20260705.log:
=== 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: <AdminLoginPage /> }, - L65:
{ path: '/403', element: <ForbiddenPage /> }, - L66:
{ - L67:
path: '/admin', - L68:
element: ( - L69:
<RequireAuth> - L70:
<AdminLayout /> - L71:
</RequireAuth> - L72:
), - L73:
children: [ - L74:
{ index: true, element: <AdminDashboardPage /> }, - L75:
{ path: 'orders', element: <AdminOrdersPage /> }, - L76:
{ path: 'orders/:orderId', element: <AdminOrderDetailPage /> }, - L77:
{ path: 'cases', element: <AdminCasesPage /> }, - L78:
{ path: 'cases/:caseId', element: <AdminCaseDetailPage /> }, - L79:
{ path: 'share-links', element: <AdminShareLinksPage /> }, - L80:
{ path: 'share-links/:code', element: <AdminShareLinkDetailPage /> }, - L81:
{ path: 'posters', element: <AdminPostersPage /> }, - L82:
{ path: 'score-lines', element: <AdminScoreLinesPage /> }, - L83:
{ path: 'rank-estimator', element: <AdminRankEstimatorPage /> }, - L84:
{ path: 'majors', element: <AdminMajorsPage /> }, - L85:
{ path: 'schools', element: <AdminSchoolsPage /> }, - L86:
{ path: 'error', element: <AdminErrorPage /> }, - L87:
{ path: '*', element: <NotFoundPage /> }, - L88:
],
静态路由对照结果:
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<void> => { - 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:
<h2 className="text-2xl font-bold text-slate-950 dark:text-white"> - L103:
<FormattedMessage id="admin.login.title" /> - L104:
</h2> - L105:
<p className="text-sm text-slate-500 dark:text-slate-400"> - L106:
<FormattedMessage id="admin.login.mockHint" /> - L107:
</p> - L132:
<div className="relative mt-2"> - L133:
<LockKeyhole className="pointer-events-none absolute left-4 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" aria-hidden="true" /> - L134:
<input - L135:
id="admin-code" - L136:
type="text" - L137:
inputMode="numeric" - L138:
autoComplete="one-time-code" - L139:
placeholder="123456" - L140:
className="min-h-12 w-full rounded-2xl border border-slate-200 bg-white px-11 text-sm text-slate-950 shadow-sm transition placeholder:text-slate-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-slate-700 dark:bg-slate-950 dark:text-white"
后端真实登录端点存在:admin/routes/auth.py 声明 POST /api/auth/login : 用户名 + 密码 → JWT,但 React 登录页没有调用该端点。
影响: 真实后端环境会出现“前端显示已登录,但后续 admin API 请求没有 JWT,返回 401/403”的集成失败。
建议修复: 登录页改为调用 /api/auth/login;保存 JWT 到明确策略(优先内存/session,避免长期 localStorage);失败态显示真实错误;补 LoginPage 集成测试和 admin e2e 登录主链路。
H3 · apiClient 没有统一注入 Authorization: Bearer,Admin API 契约未闭环
证据:
apps/web/src/lib/api-client.ts 只设置 Content-Type / Accept 和调用方传入 headers,没有从 auth/user store 注入 Bearer:
- L101:
const init: RequestInit = { - L102:
method, - L103:
headers: { - L104:
'Content-Type': 'application/json', - L105:
Accept: 'application/json', - L106:
...headers, - L107:
}, - L108:
signal, - L109:
}; - L110: ``
- L111:
if (body !== undefined) { - L112:
init.body = JSON.stringify(body); - L113:
} - L114: ``
- L115:
if (isWriteMethod(method)) { - L116:
await waitUntilOnline(signal); - L117:
} - L118: ``
- L119:
const res = await fetch(${BASE_URL}${path}, init); - L120: ``
- L155:
export const apiClient = { - L156:
get: <T>(path: string, schema: ZodType<T, ZodTypeDef, unknown>, signal?: AbortSignal): Promise<T> => - L157:
request(path, schema, { method: 'GET', signal }), - L158:
post: <T, B = unknown>(path: string, body: B, schema: ZodType<T, ZodTypeDef, unknown>, signal?: AbortSignal): Promise<T> => - L159:
request(path, schema, { method: 'POST', body, signal }), - L160:
put: <T, B = unknown>(path: string, body: B, schema: ZodType<T, ZodTypeDef, unknown>, signal?: AbortSignal): Promise<T> => - L161:
request(path, schema, { method: 'PUT', body, signal }), - L162:
patch: <T, B = unknown>(path: string, body: B, schema: ZodType<T, ZodTypeDef, unknown>, signal?: AbortSignal): Promise<T> => - L163:
request(path, schema, { method: 'PATCH', body, signal }), - L164:
delete: <T>(path: string, schema: ZodType<T, ZodTypeDef, unknown>, signal?: AbortSignal): Promise<T> => - L165:
request(path, schema, { method: 'DELETE', signal }), - L166:
};
后端 admin/auth.py 依赖 Authorization: Bearer,还支持 URL query t= fallback:
- L115:
credentials: Optional[HTTPAuthorizationCredentials] = Depends(_BEARER_SCHEME), - L116:
settings: Settings = Depends(get_settings), - L117:
) -> AdminUser: - L118:
"""FastAPI 依赖:从 Authorization: Bearer *** JWT,返回 AdminUser。 - L119: ``
- L120:
缺失/无效/过期一律 401 (走业务错误码 E012xx 系列). - L121:
支持从 URL query 参数 ``t`` 获取 token(仅用于管理后台 Web 页面场景)。 - L122:
""" - L123:
raw_token: str | None = None - L124:
if credentials is not None and credentials.scheme.lower() == "bearer": - L125:
raw_token = credentials.credentials - L126:
# fallback: URL query 参数 t(管理后台 Web 登录页跳转场景) - L127:
if raw_token is None: - L128:
query_token = request.query_params.get("t") - L129:
if query_token: - L130:
raw_token = query_token - L131:
if raw_token is None: - L132:
raise BusinessError( - L133:
AUTH_TOKEN_INVALID, detail={"reason": "missing bearer token"}
影响: 即使 H2 修复了登录,如果 apiClient 不统一注入 token,后台订单/案例/分享等受保护 API 仍会失败;若继续依赖 URL ?t=,token 容易进入浏览器历史、日志或 Referer。
建议修复: 建立 authStore / token provider,apiClient 统一注入 Authorization;逐步减少 URL token fallback 的使用范围,仅保留后台 Web 兼容场景并加安全注释和测试。
H4 · Python 总门禁 mypy 当前失败,不能宣称后端质量门禁通过
证据: scripts/dev-verify.sh 会运行 python -m mypy .:
- L87:
log "running pytest with coverage gate" - L88:
# Single source of truth threshold: matches scripts/check_coverage_gate.py - L89:
if [[ "${SKIP_PRE_EXISTING}" == "1" ]]; then - L90:
log "skip pre-existing failures: --skip-pre-existing" - L91:
for node in "${PRE_EXISTING_IGNORES[@]}"; do - L92:
PYTEST_IGNORE_ARGS+=("--deselect" "$node") - L93:
done - L94:
fi - L95:
python -m pytest admin/tests tests data \ - L96:
--ignore=.venv \ - L97:
--ignore=.worktrees \ - L98:
--cov=admin \ - L99:
--cov=data \ - L100:
--cov=skills \ - L101:
--cov-report=term-missing \ - L102:
--cov-report=xml \ - L103:
--cov-fail-under=80 \ - L104:
-q \ - L105:
"${PYTEST_IGNORE_ARGS[@]}" - L106: ``
- L107:
log "running core coverage verifier" - L108:
python scripts/check_coverage_gate.py coverage.xml - L109: ``
- L110:
log "running ruff" - L111:
python -m ruff check . --exclude .venv,.worktrees - L112: ``
- L113:
log "running mypy" - L114:
python -m mypy . - L115: ``
- L116:
log "crowd_db quality summary (防漂移监控)" - L117:
python -m data.crowd_db.quality_summary --human - L118: ``
- L119:
# P1-7/P1-8: 100-case smoke 作为独立验证步骤,失败不阻断核心门禁 - L120:
log "running 100-case smoke e2e (non-blocking)" - L121:
python scripts/score_range_fullchain_100_e2e.py --batch smoke || log "WARN: 100-case smoke e2e failed (non-blocking, see /tmp/score-range-fullchain-100-e2e.log)"
本轮执行结果显示 mypy 有 9 个错误,涉及 data/share/poster.py 等文件:
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
影响: 类型门禁失败会影响 poster/share 相关链路长期可维护性,也说明 CI clean env 可能无法稳定通过。
建议修复: 修 data/share/poster.py 返回类型;安装/声明 types-qrcode 或在 mypy 配置中有边界地忽略;修后复跑 bash scripts/dev-verify.sh。
3. MEDIUM Findings
M0 · 前端本地门禁曾因依赖缺失不可执行;已补装依赖并 fresh gate 通过,但应沉淀环境准备要求
证据: 首轮 /tmp/gaokao-review-gates-20260705.log 显示 apps/web/node_modules missing、turbo: not found;补执行 /tmp/gaokao-frontend-gates-20260705.log 后,前端 gate 结果为 PASS。
=== 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 ===
影响: 该问题当前不再是代码质量 blocker,但说明本地 review/交接流程需要先执行依赖安装,否则容易把“环境未准备”误报为“前端 gate 失败”。
建议修复: 在 review runbook / README 的前端 gate 前置条件中加入 pnpm install --frozen-lockfile,并在 CI/本地脚本中显式检查 turbo 可用后再运行 gate。
3. MEDIUM Findings
M1 · Chromatic job 无 token 条件保护,可能阻断 CI
证据: .github/workflows/web-ci.yml 直接使用 secret:
- L96:
chromatic: - L97:
runs-on: ubuntu-latest - L98:
needs: ci - L99:
timeout-minutes: 15 - L100:
if: github.event_name == 'push' || github.event_name == 'pull_request' - L101:
steps: - L102:
- uses: actions/checkout@v4 - L103:
with: - L104:
fetch-depth: 0 - L105: ``
影响: 未配置 CHROMATIC_TOKEN 时,push/PR 可能被 Chromatic 阻断;这与“外部 token 待配置”的状态口径不一致。
建议修复: 给 chromatic job 增加 secret 存在性条件或降级为非阻塞;在报告中明确 Chromatic 是否为 release blocker。
M2 · LHCI 配置与启动口径仍有漂移风险
证据: workflow 使用 treosh action + serverUrl: 8080,而 lighthouserc 注释仍写“vite preview 启动(8081)”:
.github/workflows/web-ci.yml:
- L106:
- name: Setup pnpm - L107:
uses: pnpm/action-setup@v4 - L108:
with: - L109:
version: 10 - L110: ``
- L111:
- name: Setup Node.js - L112:
uses: actions/setup-node@v4 - L113:
with: - L114:
node-version: '20' - L115:
cache: 'pnpm' - L116: ``
- L117:
- name: Install dependencies - L118:
run: pnpm install --frozen-lockfile - L119: ``
- L120:
- name: Build - L121:
run: pnpm --filter @gaokao/web build - L122: ``
- L123:
- name: Publish to Chromatic - L124:
uses: chromaui/action@v1 - L125:
with: - L126:
projectToken: ${{ secrets.CHROMATIC_TOKEN }} - L127:
workingDir: apps/web - L128:
buildScriptName: build - L129:
exitZeroOnChanges: true - L130: ``
- L131:
lighthouse: - L132:
# G3 闸门真实化:P/A/B/S 均 ≥ 90 - L133:
runs-on: ubuntu-latest - L134:
needs: ci - L135:
timeout-minutes: 15 - L136:
if: github.event_name == 'push' || github.event_name == 'pull_request' - L137:
steps: - L138:
- uses: actions/checkout@v4 - L139: ``
- L140:
- name: Setup pnpm - L141:
uses: pnpm/action-setup@v4 - L142: ``
- L143:
- name: Setup Node.js - L144:
uses: actions/setup-node@v4 - L145:
with: - L146:
node-version: '20' - L147:
cache: 'pnpm' - L148: ``
- L149:
- name: Install dependencies - L150:
run: pnpm install --frozen-lockfile - L151: ``
- L152:
- name: Build - L153:
run: pnpm --filter @gaokao/web build - L154: ``
- L155:
- name: Run Lighthouse CI (G3 闸门:P/A/B/S ≥ 90) - L156:
uses: treosh/lighthouse-ci-action@v12 - L157:
with: - L158:
configPath: ./apps/web/lighthouserc.cjs - L159:
uploadArtifacts: true - L160:
temporaryPublicStorage: true - L161:
runs: 3 - L162:
serverUrl: http://127.0.0.1:8080/ - L163:
# treosh action 自动启动 vite preview @ 8080 - L164:
url: | - L165:
http://127.0.0.1:8080/ - L166:
http://127.0.0.1:8080/data-query - L167:
http://127.0.0.1:8080/plans - L168:
http://127.0.0.1:8080/about
apps/web/lighthouserc.cjs:
- L14:
collect: { - L15:
// 静态服务器从 vite preview 启动(8081),见 CI workflow - L16:
url: [ - L17:
'http://127.0.0.1:8080/', - L18:
'http://127.0.0.1:8080/data-query', - L19:
'http://127.0.0.1:8080/plans', - L20:
'http://127.0.0.1:8080/about', - L21:
], - L22:
numberOfRuns: 3, // 取 P75(median) - L23:
settings: { - L24:
// P75 算分(默认 median = P50) - L25:
preset: 'desktop', - L26:
chromeFlags: '--no-sandbox --headless=new', - L27:
}, - L29:
assert: { - L30:
// G3 闸门:每类 ≥ 90 - L31:
assertions: { - L32:
'categories:performance': ['error', { minScore: 0.9 }], - L33:
'categories:accessibility': ['error', { minScore: 0.9 }], - L34:
'categories:best-practices': ['error', { minScore: 0.9 }], - L35:
'categories:seo': ['error', { minScore: 0.9 }], - L36:
}, - L37:
}, - L38:
upload: { - L39:
target: 'temporary-public-storage', // 公开 storage 30 天;后续接 LHCI server - L40:
},
影响: LHCI 可能在 CI 上因为服务启动机制/端口口径不一致而假失败或假通过。
建议修复: 在 LHCI 配置或 workflow 中显式指定 preview 启动命令、ready pattern、端口;修正文档注释;CI 上保留 artifact。
M3 · scripts/dev-verify.sh 将 100-case smoke 设为 non-blocking,主链路回归可能被 warning 化
证据:
- L87:
log "running pytest with coverage gate" - L88:
# Single source of truth threshold: matches scripts/check_coverage_gate.py - L89:
if [[ "${SKIP_PRE_EXISTING}" == "1" ]]; then - L90:
log "skip pre-existing failures: --skip-pre-existing" - L91:
for node in "${PRE_EXISTING_IGNORES[@]}"; do - L92:
PYTEST_IGNORE_ARGS+=("--deselect" "$node") - L93:
done - L94:
fi - L95:
python -m pytest admin/tests tests data \ - L96:
--ignore=.venv \ - L97:
--ignore=.worktrees \ - L98:
--cov=admin \ - L99:
--cov=data \ - L100:
--cov=skills \ - L101:
--cov-report=term-missing \ - L102:
--cov-report=xml \ - L103:
--cov-fail-under=80 \ - L104:
-q \ - L105:
"${PYTEST_IGNORE_ARGS[@]}" - L106: ``
- L107:
log "running core coverage verifier" - L108:
python scripts/check_coverage_gate.py coverage.xml - L109: ``
- L110:
log "running ruff" - L111:
python -m ruff check . --exclude .venv,.worktrees - L112: ``
- L113:
log "running mypy" - L114:
python -m mypy . - L115: ``
- L116:
log "crowd_db quality summary (防漂移监控)" - L117:
python -m data.crowd_db.quality_summary --human - L118: ``
- L119:
# P1-7/P1-8: 100-case smoke 作为独立验证步骤,失败不阻断核心门禁 - L120:
log "running 100-case smoke e2e (non-blocking)" - L121:
python scripts/score_range_fullchain_100_e2e.py --batch smoke || log "WARN: 100-case smoke e2e failed (non-blocking, see /tmp/score-range-fullchain-100-e2e.log)"
第 119-121 行说明 100-case smoke 失败不阻断核心门禁。
影响: 对当前高信任付费/志愿服务项目,100-case fullchain smoke 更接近业务真实回归;长期 non-blocking 可能掩盖主链路问题。
建议修复: 至少把 smoke 结果拆为 核心门禁 PASS/FAIL 与 业务主链路 PASS/FAIL 两个明确状态;在 release gate 中设置必过子集。
4. LOW / 文档真相风险
L1 · 历史 review 与当前 review 容易混用
仓库内存在多个历史 review:reports/REVIEW_REPORT_V10_FRONTEND_2026-07-05.md、REVIEW_REPORT_2026-07-02_SENIOR_DEVELOPER.md、STRICT_SYSTEM_REVIEW_* 等。历史报告仍有价值,但不应替代当前 HEAD + 当前门禁结果。
建议: 将本报告作为 2026-07-05 当前全面 review 真相入口;旧报告顶部应逐步加“历史快照”提示或 CURRENT REVIEW 指针。
L2 · 旧截图报告产物仍在仓库中,易被误当当前前端验收材料
reports/user_simulation_2026_06_20/ 仍包含旧截图和 captures.json。上一轮已避免把这些旧产物合并进新提交;本轮 review 继续建议把它们标注为历史材料,不作为 V10 当前验收证据。
5. 已验证不是问题 / 当前正向事实
apps/web/src/types/api-generated.d.ts与apps/web/src/schemas/api-generated.ts的any_count=0:
apps/web/src/types/api-generated.d.ts 0
apps/web/src/schemas/api-generated.ts 0
-
admin/routes/health.py当前 dev readiness 逻辑可解释:- L65:
def _check_settings_valid(settings: Settings) -> bool: - L66:
"""检查 prod fail-closed 通过 (JWT + admin password + payment)。 - L67: ``
- L68:
dev 环境允许占位密钥,仅 prod 环境强制安全密钥。 - L69:
""" - L70:
if settings.env == "dev": - L71:
# dev 环境允许占位密钥,不做 fail-closed - L72:
return True - L73:
secure, _ = is_jwt_secret_secure(settings) - L74:
return secure - L75: ``
- L76: ``
- L77:
@router.get("/health", summary="健康检查") - L78:
def health(settings: Settings = Depends(get_settings_dep)) -> JSONResponse: - L79:
"""公开端点。只返回 readiness, 不暴露环境/路径/版本细节。 - L80: ``
- L81:
返回结构: - L82:
- status: "ok" 或 "degraded"(任一 readiness 检查失败时降级) - L83:
- checks: {db_writable, disk_writable, settings_valid} 子对象 - L84: ``
- L85:
readiness 语义(2026-06-27 P1-4 修复): - L86:
- 所有 checks 通过 → status="ok", HTTP 200 - L87:
- 任一 check 失败 → status="degraded", HTTP 503 - L88:
- K8s/systemd readiness probe 应判 HTTP status,不只判 status 字段 - L89:
""" - L90:
checks = { - L91:
"db_writable": _check_db_writable(settings), - L92:
"disk_writable": _check_disk_writable(settings), - L93:
"settings_valid": _check_settings_valid(settings), - L94:
} - L95:
all_ok = all(checks.values()) - L96:
return JSONResponse( - L97:
status_code=200 if all_ok else 503, - L98:
content={ - L99:
"status": "ok" if all_ok else "degraded", - L100:
"checks": checks, - L101:
},
- L65:
-
静态扫描未发现 Python 裸
except:。
6. 建议整改优先级
P0 / 立即阻断生产完成声明
- 修复 H1
/admin/review断链并补全 admin nav e2e。 - 修复 H2/H3:React Admin 真实登录 + JWT 注入 + auth 状态测试。
- 修复 H4:mypy 9 errors,复跑
scripts/dev-verify.sh到 green。 - 前端依赖已补装并复跑 typecheck/lint/test/build;后续仍需补 Playwright e2e / LHCI / Chromatic fresh evidence。
P1 / CI 与验收口径收敛
- Chromatic token 缺失时不阻断或明确设为必配 release gate。
- LHCI preview 启动和端口口径统一。
- 100-case smoke 的 release gate 语义升级,不再只作为 warning。
P2 / 文档与证据治理
- 给历史 review 报告加当前真相入口。
- 标注旧截图/旧 user simulation 产物为历史材料。
7. 本轮命令与证据索引
## main
4059f144c49398aec2fcc3040e639e1312061086
4059f14 (HEAD -> main, tksea/main, origin/main, gitea/main) fix(health): allow dev placeholder readiness
da99dec docs: add systemic frontend review findings
5d52e07 docs: update frontend review status after e2e fixes
本轮主要证据:
- 本地 gate 日志:
/tmp/gaokao-review-gates-20260705.log - 当前报告:
reports/REVIEW_REPORT_2026-07-05_COMPREHENSIVE_PROJECT_REVIEW.md - 核查文件:
apps/web/src/layouts/AdminLayout.tsxapps/web/src/router.tsxapps/web/src/pages/admin/LoginPage.tsxapps/web/src/lib/api-client.ts.github/workflows/web-ci.ymlapps/web/lighthouserc.cjsscripts/dev-verify.shadmin/routes/health.pyadmin/auth.py
8. 最终判断
不能宣称项目整体生产级完成。
可以宣称:
- 本轮已完成一次当前 HEAD 的多维真实 review。
- 已发现并固化当前有效问题到今日 review 报告。
- 当前最大阻断不是“未知”,而是明确集中在:后台真实鉴权闭环、admin nav 路由完整性、Python 类型门禁、Playwright/LHCI/Chromatic 与真实视觉验收 fresh evidence、CI 外部服务口径。
仍不能宣称:
- 前端 V10 全部门禁(含 Playwright e2e / LHCI / Chromatic / 真实视觉验收)当前全部通过。
- Admin 真实 JWT 登录已接通。
- CI/LHCI/Chromatic 生产级验收闭环。
- 线上真实支付/真实域名/真实用户流量验收完成。