Files
hangshuo652 1b89743d77 评审真实性增强:前端硬规则+人工启动方案+文档-实现三级校验
- 前端存在性硬规则:detectFrontend 源码级判定,web形态无真实前端/不可访问 → 实现完整度封顶50%(CLI/插件豁免)
- verify 多态:build_status 支持 done/failed/done_no_ui,前端按钮新增「无前端」
- 人工启动方案:评审环境自动启动失败 → awaiting_browse 暂停,评委手动启动后填 service_url 走 /verify-browse 恢复(SSRF 信任评委确认地址)
- Gitea 稳定性:clone 自动重试×3(525抖动)+ 每队独立 token 回退(全局账号失效兜底)
- A 阶段报告备份:feature_inventory.__stageA_report 防 B 阶段维度重复累积/A维度丢失
- tryTest 依赖预装:Python 项目自动 pip install(测试不再因缺依赖误判失败)
- 运行验证压缩静态维度:前端缺失+测试失败 → 静态纸面维度封顶50%(防原型拿高分)
- 文档-实现三级校验:claim-consistency 注入运行时证据(构建/测试/前端),识别「代码有但跑不起来」的虚报(逸飞冲天 61%→25%)
- 赛事文档:中期20%+最终80%(AI=人工总分)、评审表/评审规则/赛事说明/07设计同步
- 清空 review_snapshots 测试污染数据,保留当前正式分(零号158/逸飞冲天126)
- 测试 446 全通过(后端435+前端11)
2026-09-01 08:44:56 +08:00

275 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI-Review 评审系统
## 目录
```
ai-review/
├── server/ # 后端 Express + TypeScript + better-sqlite3
├── web/ # 前端 React + TypeScript + Vite
├── config/ # teams.json14 支参赛队伍结构化数据,含 gittea 凭据与选题)
├── docs/ # 文档(评审标准模板、user-stories.md 用户故事)
├── docs/design/ # 设计书(01-系统 / 02-API / 03-后台 / 04-前端)
└── AGENTS.md # 本文件
```
## 启动方式
```bash
# 后端(端口 3002
cd server
npx tsc # 必须先编译(不能直接跑 ts
node dist/index.js
# 前端(端口 14001
cd web
npx vite --host 0.0.0.0 --port 14001
# 后端测试(vitest,在 server/ 下运行)
cd server && npm test
```
## 关键配置
| 项 | 值 | 位置 |
|---|---|---|
| 后端端口 | 3002 | `server/src/config.ts` |
| 前端端口 | 14001 | `web/vite.config.ts` |
| 登录密码 | `620f4c96` | `server/.env` |
| DeepSeek API | `api.deepseek.com` | `server/src/services/review.service.ts` |
| MAX_CONCURRENT | 3 | `review.service.ts` |
| DB 文件 | `server/data/ai-review.db` | `server/src/db.ts` |
## 核心架构
### 评审管线(3 阶段)
```
Phase 1: 概览(1 次 AI 调用)
Phase 2: N 子 Agent 并行评审(按标准维度数,concurrency=3
Phase 3: 确定性校准(computeCalibration) + 硬规则引擎
```
### 核心文件
| 文件 | 职责 |
|------|------|
| `review.service.ts` (~1500行) | 评审引擎:clone→tryBuild→tryBrowse→AI→校准(computeCalibration)→硬规则→出分 |
| `standards.ts` | `parseDimensions` 解析标准 MD 为维度列表 |
| `l2-topics.ts` | L2考核选题元数据(11命题题+自选题,`config/l2-topics.json`):难度赋分 cap、功能完整性拆分、验收要点注入 |
| `l2-participants.ts` | L2受验者注册表(`config/l2-participants.json`):员工编号↔Gitea账号↔仓库映射,自动生成拉取 URL;拉取认证走全局评审账号只读协作者权限 |
| `code-inventory.ts` | 全量符号索引(评审真实性改进 2026-08-26):对所有文本文件提取 path/lines/symbols,注入实现类维度让 AI 看见 100% 文件清单(接口:`extractSignatures` + `renderInventoryText`,无 coreFiles 精读包——精读由 `filterFilesForDim` 维度过滤承担,2026-08-27 文档对齐) |
| `code-signals.ts` | 代码信号检测器:TODO 密度/空壳率/硬编码返回/死导入——确定性线索注入实现类维度 prompt,定位为线索而非判据 |
| `ai-log-audit.ts` | AI 日志确定性审计:占位率 / git 一致率 / 覆盖广度;占位>50%→维度≤30%、git一致<30%→≤20% 封顶 |
| `measurement-audit.ts` | 测量协议检查(P2,2026-08-27):确定性检查 `data/measurement/` 齐备性(baseline/README/timing-log),注入效果类维度 prompt |
| `accept-runner.ts` | 验收命令执行器(P22026-08-27):解析 README `## 验收` 命令块并真实执行,注入实现类维度;测试环境 dry-run 不实跑 |
| `entries.ts` | 条目 CRUD + 触发评审 + PDF 导出 |
| `projects.ts` | 项目 CRUD + 汇总排名 |
| `db.ts` | SQLite 初始化 + migrationsALTER TABLE try/catch |
| `config.ts` | 端口/密码/DeepSeek key |
### 关键流程
```
cloneRepo → discoverFiles → countCodeStats → tryBuild → tryBrowse/tryStart
→ 概览(精简context) → N子Agent(content+fileBlock) → 校准(computeCalibration) → 硬规则
→ 总分(rawScore) → 迟交扣分 → finalScore → review_snapshots
```
## 关键事实(修改前必读)
### 编译与重启
- TS 改动后必须 `cd server && npx tsc`,不能只改 .ts 不编译
- `server/dist/` 编译输出和 `server/src/` 分离
- 启动:必须用 `node dist/index.js`(不能 `tsx watch`,那需要 dev 模式)
- 服务器崩溃后启动会自动恢复卡死的 entry(状态重置为 pending
### tryBuild
- 支持 7 种构建系统:npm/pom.xml/build.gradle/makefile/cargo/go/pyproject
- Python build 命令是 `python -m build --wheel --no-isolation`(不是 `pip install -e .`
- `buildRootMap[file] === undefined` 判断是否存在(不是 falsy,根目录文件 relDir=""
- `canBuild` 过滤 install 步骤:`!command.startsWith('npm install')``!command.startsWith('pip install')`
### tryBrowse
-`puppeteer-core` + 自动检测 Chrome/Edge 路径(不自带 Chromium
- `waitUntil: 'domcontentloaded'`(不是 `networkidle0`,对 API 服务太严格)
- `service_url` 提供时跳过 tryStart,直接 browse 该 URL
- **看门狗**:整体 45s 硬超时(BROWSE_WATCHDOG_MS),Chrome 启动/加载/关闭任一环节挂住也会被强制 kill 并降级为"跳过浏览器测试",不会卡死评审管线
- **评审期二次 SSRF 校验**`revalidateHost`):打开 URL 前重新 DNS 解析域名,若已变为内网地址(重绑定攻击)则拦截并跳过浏览器测试;仅 `config.ssrfDnsCheck` 开启时生效
### 维度评审(runSubAgent
- 评审依据优先级:**标准快照 `dim.content` 优先且唯一**;内置 `dimGuidelines` 仅当 content 为空时兜底(并标注"内置兜底,仅供参考")。不要两套规则同时注入,否则 AI 会困惑
- `dimGuidelines` 是硬编码指南(key:场景价值/架构设计/工具使用/实现完整/开发范式/Agent核心/规模/代码规范/演示与文档/AI使用日志/效果与数据等),分值小计可能≠maxScore,仅兜底用
- `DIM_FILE_FILTERS` 按维度过滤文件(如代码规范只给源码,演示文档只给 .md)
- `filterFilesForDim` 输出时给文档文件标注 `(文档/说明文件,非代码)`,防止 AI 把 README/CLAUDE.md 内容当作代码问题上报
- `fileBlock` 截断:普通维度 15000 字,构建维度 40000 字
- `DIM_FILE_FILTERS``'AI使用日志'` 正则需同时覆盖 `ai_log`/`ai_usage`/`usage_log`(如 `_AI_USAGE_LOG.md`),否则该文件被过滤、AI 判"未发现日志"2026-08-18 实测修复)
- `extraContext` 只对构建维度(实现完整度)附加构建步骤详情
- `projectContext` 包含服务状态行:`参赛者服务地址: xxx(可正常访问/无法访问)`
### 确定性证据(方案一 / 方案二,2026-08-07 新增)
- **方案一 `evidence-detect.ts`**:Agent核心能力 4 项硬门槛由代码模式匹配做**确定性判定**(LLM调用/工具选择策略/错误重试降级/状态持久化),AI 不再判门槛、只做 5 项评分要素。检测结果(文件:行号)注入 Agent核心维度 prompt,含 `allPassed` 结论
- **方案二 `test-runner.ts`**`tryTest` 在构建可用的前提下真跑测试。支持多框架输出解析——pytest/jest/go test -v/surefire(Maven)/Gradle tests completed/Cargo test result;覆盖率解析含 pytest-cov/jest/istanbul/go cover/jacoco。go test 自动加 `-v -cover`。**软证据**——成功才注入真实通过率/覆盖率到"效果与数据"维度;环境失败/工具缺失一律**中性不扣分**(不证明项目差)
- **tryTest 与构建完全解耦**2026-08-13):无条件跑测试,不依赖 `buildResult.canBuild`。构建失败 ≠ 测试不可跑(cobol-java 的 build-backend 写错打不了包,但 pytest 能真跑 33/42)。`runTest` 完整保留输出供解析——**汇总行在输出尾部,截断到 3000 字会丢 passed/coverage 汇总**(曾导致 testsPassed=0、覆盖率 null
- **维度独立原则**`review.service.ts` runSubAgent 严格规则):每个维度独立评分,其他维度的判定(如 Agent核心门槛是否通过、项目是否为 Agent 应用)**不构成扣分依据**——"效果与数据"评估测试覆盖/覆盖率/可复现性,即使非 Agent 项目,测试真实存在且通过就应据实给分
- **确定性测试证据强绑定**:tryTest 真跑成功时 `testEvidenceToPrompt` 注入"确定性证据,评分必须据此",AI 不得忽略或低估真实通过率/覆盖率(实测生效:calc 项目 Agent核心 0/25 但效果与数据 15/20 正常给分;cobol-java 效果与数据 0/20→6/20AI 引用"42个用例33通过"
- **Agent核心检测置信度**`buildAgentGateReport` 按命中数标注置信度——0/低(1)/中(2-3)/高(≥4);低置信度通过项注入提示"可能误匹配,可在评分要素中酌情下调,但不得推翻门槛判定"
- 阈值常量在 `evidence-detect.ts`MAX_HITS=5`test-runner.ts`TEST_TIMEOUT=180s
### 校准(Phase 3b,确定性)
- `computeCalibration``standard-utils.ts`)由代码计算,**不信任 LLM 的 delta 数值**
- LLM 只输出跨维度语义矛盾的方向(over/under),代码定调幅:L1 矛盾±2、L2 σ异常(偏离>2σ)±4、L3 最不稳定维度(Agent核心/规模·功能点/效果与数据)高估×0.8
- 调幅常量在 `review-constants.ts`CAL_ANOMALY_STDDEV=2.0 / CAL_L2_LIMIT=4 / CAL_L1_LIMIT=2 / CAL_UNSTABLE_WEIGHT=0.8
- 每个实际改动写入 `calibrationExplanation`(格式:`校准执行:\n- 维度: 旧分→新分(L1/L2/L3`),可审计
- 老的 `applyCalibration`(LLM-delta)已删除,不要引用
### 代码健康度(countCodeStats
- 返回 CodeStatsfileCount/totalLines/effectiveLines/blankLines/commentLines/duplicateRatio/dirDepth/tinyFiles
- `duplicateRatio` 用 MD5 哈希文件内容检测
- `dirDepth.avg` 追踪目录嵌套深度
- 结果注入 `projectContext` 供 AI 参考
### 硬规则(Phase 3c,校准后执行)
- 构建失败→实现完整度≤4/12,效果与数据≤3/10
- pytest 失败→效果与数据≤5/10
- 重复代码>50%→代码规范≤3/5
- 无根目录 README→演示与文档≤2/5
- 日志写入 calibrationExplanation
### 评分
- 校准 delta 用 `Math.round()` 取整(避免 52.400000000000006
- 总分 = `Math.round(每个维度分数)` 累加
- `finalScore` = `totalScore - 迟交扣分`,上限 `max_score_cap`
- 迟交判定(2026-08-15 增强):`resolveSubmitTime` 解析提交时间——优先 git 最后 commit 时间;commit 缺失或早于条目创建时间(空仓库/提前 clone 旧代码/无 .git)→ 用条目创建时间兜底避免逃逸;两者都无效才用评审时刻。然后 `computeLateDays` 对比 `project.deadline`
### 评审可信度(2026-08-19
- **排名用多次聚合**`aggregateScores`/`aggregateEntryScores`standard-utils.ts)——最近 N 次(默认3)`review_snapshots.score` 中位数;N=2 平均、N=1 单次。聚合前提=各快照 `standard_snapshot` 一致。`<3 次标"初评(未达聚合样本)"`,排名区分正式/初评
- **快照分数列**`review_snapshots.score` 存含迟交扣分的 final_score(写快照时一并存,不解析 ai_report——它只有 totalScore)。历史快照 backfill 从 totalScore best-effort
- **可验证能力三档**`classifyVerifiability`,效果/提效类维度,校准之前判档):A=基准证据(`entries.benchmark_json` status=done);B=测试通过或覆盖率非 null;C=数据缺位→封顶 maxScore*0.3 + note"数据缺位(未证明),非无效"。**构建成功≠效果可验证**。C 档 note 渲染到前端维度表 + PDF。**纯增益维度严格制(2026-08-26**`提效幅度/效果对比/效率提升` 类维度(isPureGainDim)测试通过**不构成**提效证据——无基线对比数据一律 C 档封顶(实测案例:六边形战队提效幅度无量化数据 raw=6,修复后同类场景 C≤3)。**定性设计维度豁免(2026-08-26**`提效设计合理性/XX清晰度`isQualitativeDesignDim)考察设计思路而非量化结果,不参与 C 档封顶——避免测试环境因素跨队伍不公平(净码特攻案例)
- **基准证据按 entry 落库**`entries.benchmark_json`,非 env 变量——MAX_CONCURRENT=3 并发会串数据)
- **确定性 L1**`detectStructuralContradictions`):仅证据性矛盾触发(有测试/基准证据但效果≈0 → under;效果高分+实现全低 → over)。**效果维度 under 一律丢弃**computeCalibration 内过滤)——效果维度只降不升,诚实由三档封顶负责。禁止"实现高分+无数据"当 under
- **overall 中性边界**`neutralizeTestEvidence`):测试 summary 含"中性"→ 标 `[中性证据]`;不含("未检测到测试框架配置"=真缺测试)→ 真实弱点。synthesizeOverall prompt 禁止把 `[中性证据]` 列为不足
- **视频 URL 弱证据**`detectDemoVideo` 扫根目录 README + 根级 docs/*.md 的视频链接,source='url'(外部链接未核验)vs 'file'(强证据优先)
- **维度级聚合**:详情/PDF 维度表用 `averageDimensions` 跨快照聚合(entries.ts GET /:entryId 返回 dimsAgg),展示"历次分差"
- **决赛圈基准框架**`benchmark.ts` `runBenchmark(dir, seeds, detect)`,检出率与基线分开呈现。seed 库赛前生成不公开(Goodhart 已知上限)
- **人机标定**`docs/design/06-人机标定方案.md`——绝对准确未验证前,分数用于排名(相对序)可信,绝对解读需标定偏差基线
### parseDimensions
- 正则在 `standards.ts`,修复后支持空内容(`content: ""`
-`## 维度名(分数)` 解析,必须紧跟 `\n## ` 或字符串结束
- 过滤分区/说明性标题:`评审维度``合格判定``成果物清单``第X部分:` 等不进入维度列表
- group 推断:`## [Q2] xxx`(显式)或 `## 2-A. xxx` / `## 2-Axxx`(题目追加维度前缀)→ group=Q2;其余 common
- 验证:标准模板解析结果应固定为——赛道一 12维/150、赛道二 8维/100、L2考核 7维/100(全 common);人才测评已整合进 L2考核(2026-08-23),不再单独验证
### entries 表
- `UNIQUE(project_id, repo_url)` 约束
- `service_url TEXT DEFAULT ''`migration 添加)
- `feature_inventory TEXT DEFAULT ''`2026-08-27migration 添加):全量功能发现轮(Map-Reduce)结果 JSON 数组,供详情页展示与跨快照复用;重评时覆盖
- `ai_report.dimensions[n].checks`:实现类维度子 Agent 返回的定向追踪核对表(feature/entry/depth/evidence/reason),由 `parseDimResponse` 解析透传(2026-08-27 修正),前端维度表展示,缺失回退现状不崩
- `build_status TEXT DEFAULT ''`2026-08-18migration 添加):赛道二/L2考核单阶段人工构建确认,''=未确认(自动构建) / done / failed;赛道一 B 阶段不存此列,走 /verify 请求体
- `standard_snapshot` 存标准快照(评审时标准被修改也不影响已评审结果)
- `review_snapshots` 存每次评审历史
- L2考核专属字段:`selected_topic`(选题 01~11/self,决定 max_score_cap 与难度赋分)、`self_registration`(自选题登记 JSON:登记编号+功能清单快照)
- force-review(测试端点)需 `ADMIN_TEST_TOKEN=true` **且** `NODE_ENV=test` 双条件才开启;生产 `node dist/index.js` 即使 flag 泄漏也打不开
- **赛道必选(2026-08-13**:创建/编辑项目必须传 track(赛道一/赛道二/L2考核),缺省返回 400 `赛道为必选项`;前端下拉首项"请选择赛道(必选)"create() 校验 `if (!track) setError('请选择赛道')`。注意:有赛道会自动导入对应默认标准(`projects.ts` POST 里 `loadDefaultStandard`)——创建项目的测试用例必须带合法 track,否则建出的项目无赛道且后续标准解析行为不同。**e2e 陷阱**:依赖"自定义标准快照"的用例(如 `hardcode-fixes.spec.ts` 3.1/3.2)在带 track 创建项目后,自动标准会抢占 `resolveStandard` 匹配,导致条目快照不是测试上传的标准——需先调用 `apiClearStandards(request, token, pid)` 清掉自动标准再上传自定义标准
### 本地评审样本
- `server/data/clone/_real_cobol_java/`:真实仓库(cobol-java-v3COBOL→Java 测试生成工具)的本地副本,作真实评审冒烟对象
- 用它跑过 6 次真实 DeepSeek 评审:30(旧校准)→52(确定性门槛)→58→67(效果与数据 0→6,tryTest 解耦构建后)→55(第 5 次评审,校准 anomalies 触发的自然波动)。数据在 `data/e2e-usertest.db` 的 review_snapshots(该项目 track=赛道一,12 维标准)
- **注意:评审结束会删除 clone 目录**(`executeReview` 末尾 `fs.rmSync(dir)`),只留 review_snapshots;若需现场调试 clone 内容,评审前复制一份出来
### 管线诊断日志(`[pipe:entryId]`
- `pipeLog(entryId, phase, msg, durMs?)` 只写服务端 console(不进 progress_log,不污染前端)
- 覆盖阶段:START / CLONE / ANALYZE(含 canBuild·untested/ GATES / TESTcommand·pass/fail·coverage·summary**这是"证据静默丢失"类问题的 debug 入口**/ BROWSEserviceUrl·pageLoaded/ OVERVIEW / SUBAGENT12 个 DIM 各带耗时)/ **OVERALL**(整体评价合成,pos/hl/wk,失败打印 failed/ DONEscore·penalty·final·总耗时)/ **FAIL**`runReview` catch 兜底,任何阶段抛错都会有 `[pipe:xxx] FAIL <msg> [耗时ms]`,不会再静默卡 status=failed
- 实测 cobol 第 5 次评审:ANALYZE 24stryBuild 跑 python 构建超时)、TEST 10s`python -m pytest` 33/42 pass、coverage null)、DIM 每维度 4.6~24.7s、全程 114s
### 整体评价合成(方案A2026-08-19
- `synthesizeOverall`review.service.ts):校准+硬规则之后,+1 次 LLM 调用(约 15-30s),把 overview+维度得分评语+确定性证据合成**点评式**整体评价,写入 `ai_report.overall`JSONhighlights[{point,review}]/weaknesses[{point,review}]/verdict
- **项目总览(overview)负责中立描述,overall 只做点评**:每条亮点/不足都带判断(价值/影响/严重度),不重复定位
- 输入全是真实证据,prompt 显式"禁止编造";失败非致命(overall=null,不影响评分)
- 兼容旧格式(字符串数组 → point,review 空)
- 落点:赛道一 B 尾(executeReviewB)与赛道二单阶段尾(executeReview)各一次;A 阶段不合成
- 展示:前端条目详情"整体评价"段(亮点点评绿/不足点评红/总评,ProjectView.tsx+ PDF 报告块(pdf.service.ts
- 纯函数 `parseOverallResponse` 负责 JSON 解析/代码块剥离/裁剪(overall.test.ts 单测 7 用例)
## 已知坑
1. **Chrome 崩溃导致服务器卡死(已缓解)** — tryBrowse 有整体 45s 看门狗(BROWSE_WATCHDOG_MS),挂住会强制 kill Chrome 并降级"跳过浏览器测试",但仍建议留意 browse 期间系统资源占用
2. **多人提交排队** — MAX_CONCURRENT=3,第 4 个 entry 起入队列排队等空位(`queue[]` + `processQueue`
3. **AI 从 docs 编造代码问题(已缓解)** — fileBlock 中文档文件已标注 `(文档/说明文件,非代码)`,但 AI 仍可能把标准模板内容误当代码问题,若再出现可在 prompt 强化
4. **tryBrowse SSRF 风险(已缓解)** — service_url 保存时校验 + 评审期 `revalidateHost` 二次 DNS 解析(重绑定拦截,仅 `config.ssrfDnsCheck` 开启时生效),仍建议沙箱
5. **review.service.ts 1060 行** — 单文件过大,改动前必须理解整个 pipeline
6. **difficulty 字段已移除** — 不要搜或引用 difficulty(前端已改为"赛道"下拉)
7. **本地 file:// 仓库 URL 格式** — 必须用 `file://D:/...`(两斜杠);`file:///D:/...`(三斜杠)会被 `path.resolve` 解析成 `D:\D:\...` 导致白名单拒绝(2026-08-07 实测)
8. **测试数据会污染"真实数据"判断** — 库里大量 `选手X/小明作品/k4-entry` 是 e2e 造的假条目;判断真实评审数据要看 `repo_url`(真实 https/本地副本)而非条目名
## 测试
```bash
# 后端单元测试(vitest
cd server && npm test
# 特定测试文件
cd server && npm test -- src/__tests__/api.test.ts
# 用户故事驱动验收(docs/user-stories.md,纯函数级,不调 AI20 用例)
cd server && npm test -- src/__tests__/user-stories.test.ts
# E2E(需前后端都启动)
# web/e2e 目录有 Playwright 测试
## vitest 超时陷阱(2026-08-27 实测)
- **vitest 默认测试超时 5000ms**,而触发完整评审(`/start` → A 阶段)的用例因功能发现轮(Map-Reducemock 环境 12 块串行 ×400ms)拖到 ~5s,**会撞默认 5s 超时**。凡 `waitA_done`/等待 A 阶段完成的用例必须显式加超时(`}, 30000)` 或更大),否则偶发 `Test timed out in 5000ms`
- 现象:单跑通过、全量偶发失败,报错是 vitest 超时而非断言失败
## E2E 运行陷阱(2026-08-14 实测)
- **整套 full-e2e 需 15+ 分钟**,单个 describe 单独跑更快(评审标准 7、条目管理 10、批量/详情/汇总/异常/UI 27、完整流程 1 = 45 个测试)。整套跑超时是正常现象,不是 bug
- **孤儿 tsx server 会卡死所有 DB 请求**:多次中断 e2e 会残留多组 `tsx src/index.ts` 进程同时打开 `data/ai-review.db`better-sqlite3 WAL 锁冲突导致 login/beforeAll 全部挂起 90s。症状:health 慢、login 超时、beforeAll timeout。排查:`Get-CimInstance Win32_Process -Filter "Name='node.exe'" | where CommandLine -like "*tsx*src/index.ts*"`,全杀后重跑
- **`apiClearStandards` 的 BASE 必须带 `/api`**`http://localhost:3002/api`),漏掉会打到 `/projects/:id/standards`(无路由)返回 404 HTML`list.json()``SyntaxError: Unexpected token '<'`
- **补 track 后项目头部和表格赛道列都会渲染 `<span class="badge">赛道一</span>`**,原 `.badge` 选择器断言会多命中——用 `.entry-table .badge` 限定,且状态文案是中文(`待评审` 而非 `pending`,见 `ProjectView.tsx` statusBadge
```
## 数据库操作
```bash
# 手动查 SQLite
cd server && node -e "const D=require('better-sqlite3');const d=new D('data/ai-review.db');console.log(d.prepare('SELECT name FROM sqlite_master WHERE type=\"table\"').all())"
```
## 评审标准格式
```markdown
## 维度名(满分X分)
内容描述...
## 下一个维度(满分Y分)
内容描述...
```
标准 MD 必须至少有一个 `## 维度名(分数)` 格式的标题。
### 内置标准模板(由项目管理员上传)
**赛道一(Agent开发实战赛):** 场景价值15、开发范式与架构设计25、工具使用10、实现完整度15、规模·功能点·技术难度10、演示与文档5、AI使用日志10、效果评估与数据10
**赛道二(IDE+开发范式创新赛):** 场景价值、开发范式、工具使用、实现完整度、规模·功能点、演示与文档、AI使用日志、效果评估与数据(总分100)
**L2考核(AI人才育成认证,7维/100):** 功能完整性30、设计文档10、测试用例与测试结果10、AI协作过程记录15、技术选型与范式运用15、代码质量+README 10、业务场景理解与需求分析10。选题难度赋分:★★+0/★★★+5/★★★★+10,封顶选题 cap100/105/110)。合格线≥60 且 功能完整性≥15(地板线)。
当前维度 guideline 只覆盖标准维度名(如"场景价值与合理性"),赛道一变体名(如"开发范式与架构设计")需扩展匹配关键词。L2考核 7 维标准自带分档锚点与交叉验证规则,content 优先不触发内置兜底。