diff --git a/CHECKLIST.md b/CHECKLIST.md index 258ecb0..f4206ae 100644 --- a/CHECKLIST.md +++ b/CHECKLIST.md @@ -317,6 +317,7 @@ - 独立 review(herdr 里的 pi,模型 `strata/qwen3.8-flash-next-abliterated-iq3_s:high`)。第 1 轮 FAIL 两条,都在我那条提交里:`schemas.py` 被我从 498 顶到 534 行,破了「单文件 ≤500 行」;同一提交净增 3 条多行 docstring(114→117)。修在 `6df713d`:自报家族(`CacheLayerStatus`/`MemoryStatus`/`RuntimeStatus`/三个 state 别名/`SenseStatus`/`SystemStatus`)搬进 `backend/src/ely_eye/status_schemas.py`(它只需要 `schemas.py` 的 `TrainingAdapterKind`,反向不依赖),schemas.py 回到 469;三条 docstring 各压成一行,全仓多行 docstring 回到 114,与父提交同数。 - 第 2 轮 FAIL 三条:① **翻页其实没被测到**——E2E 等的是「行数变化」,而搜索列表与浏览列表共用 `.atom-row`,那一刻的 13 行里有一条是搜索命中;把 `nextPage()` 里的 `setCursor`+`loadBrowse` 删掉、或把翻页改成追加而不是替换,E2E 都还 PASS。改成 `data-testid="browse-list"` + 每行 `data-atom`,断言第一页正好 12 行、下一页零重叠、末页 = `total−12`、Prev 复原;两个变异现在各自红:`Next page did not swap the page: the pager is not paging` 与 `the next page repeated 12 of 12 atoms from the first page` ② CHECKLIST 写 `App.tsx`「130 行的壳」,`wc -l` 是 131 ③ CHECKLIST 引的拒绝挂载原文被 smoke 的 `.slice(0,120)` 砍掉了后半句 `; set ELY_EYE_MODEL_DIR to the model snapshot`,改成 slice 200 并照原文记。 - 同一轮实测为真:263 passed;ruff 干净;全仓 mypy 24 错/6 文件(净新增 0);go build/vet/test+gofmt 干净;`npm run build`+`eslint .` 干净;`ui_smoke.sh` PASS(4.0s);`mcp_write_smoke.sh` PASS(3.2s);30 条路由与 `HTTP_SURFACE` 一致;senses 单一真相(`api.py:52/:105` 与 `maintenance.py:238` 都只渲染 `sense_facts()`);26 个 `types.ts` 接口对着 pydantic 模型逐个 diff 零编造字段;8 条被删路由无人引用,它们背后的函数都还从 CLI/proof 可达。pyright 在那 8 个文件:reviewer 的工作树 **0 errors**,我这棵树多两条 `runtime.py:283` 的 tuple 告警——它只在 `qwen_vl_utils` 那个无类型导入被解析时出现,HEAD 的副本同样有,不是本轮引入;两边都不是新增。 + - 第 3 轮 **PASS**(`9f91ff7..b0895eb`,~40 条 shell / 14 次工具调用,本轮 34 分钟)。reviewer 是跑过不是读过:`ui_smoke.sh` exit 0(4.26s,拒绝挂载整句可见);三个变异各自红——删 `nextPage()` 的 setCursor+loadBrowse → `the pager is not paging`,翻页改追加 → `repeated 12 of 12`,它自己加的第三个(删 `previousPage()` 的复原)→ `Timeout 15000ms`;改完 `git checkout` 后回到 exit 0。门禁重跑:263 passed、npm build+lint 干净、go build/vet/test+gofmt 干净、`mcp_write_smoke.sh` PASS 3.26s、ruff 干净、mypy 冷缓存查 8 个文件 Success、全仓 mypy 24 错/6 文件。数字全对:schemas.py 469、status_schemas.py 74(只从 schemas 拿 `TrainingAdapterKind`,反向无导入)、多行 docstring 114、App.tsx 131、拒绝文案与 `cartridge.py:169-173` 逐字一致、30 条路由与 `HTTP_SURFACE` 完全相等且 8 条删掉的都报 gone、`PAGE_SIZE=12` 两处同值、末页 135−12=123 行、`types.ts` 26 个接口、前端最大文件 `styles.css` 492。它同时指出两点不是缺陷但记着:`PAGE_SIZE` 是手拄到 harness 的(组件改了会变红不会变绿,已在记录里写明);末页的 `total−12` 读的是未过滤的 `GET /api/atoms?limit=1`,只对是因为前一行刚好把 modality 清掉了。 - [ ] **p1-6** 代码卫生 - [ ] p1-6.1 `evals.py` 2413 行拆到 ≤500 行/文件 - [ ] p1-6.2 删 dead code 与未调用函数 diff --git a/bench/filesize_check.py b/bench/filesize_check.py new file mode 100644 index 0000000..6c7a876 --- /dev/null +++ b/bench/filesize_check.py @@ -0,0 +1,53 @@ +"""Fail when a tracked source file outgrows the line budget the repo agreed to.""" + +import subprocess +from pathlib import Path + +LINE_LIMIT = 500 +CODE_SUFFIXES = (".py", ".go", ".ts", ".tsx", ".mjs", ".css", ".sh", ".ps1") + + +def tracked_files() -> list[Path]: + """Every file git tracks under the repository root.""" + listing = subprocess.run( + ["git", "ls-files"], + cwd=Path(__file__).resolve().parents[1], + capture_output=True, + text=True, + check=False, + ) + if listing.returncode != 0: + raise SystemExit(f"git ls-files failed: {listing.stderr.strip()}") + return [Path(name) for name in listing.stdout.split() if name.endswith(CODE_SUFFIXES)] + + +def line_count(path: Path) -> int: + return len(path.read_text(encoding="utf-8", errors="replace").splitlines()) + + +def offenders(root: Path, files: list[Path] | None = None) -> list[tuple[int, str]]: + """Files over the budget, biggest first.""" + rows: list[tuple[int, str]] = [] + for name in files if files is not None else tracked_files(): + path = root / name + if not path.is_file(): + continue + lines = line_count(path) + if lines > LINE_LIMIT: + rows.append((lines, str(name))) + return sorted(rows, reverse=True) + + +def main() -> None: + root = Path(__file__).resolve().parents[1] + over = offenders(root) + if not over: + print(f"OK: no tracked source file exceeds {LINE_LIMIT} lines") + return + for lines, name in over: + print(f"{lines:5d} {name}") + raise SystemExit(f"{len(over)} files exceed the {LINE_LIMIT}-line budget") + + +if __name__ == "__main__": + main()