fix(app-iced): M90 r2 —— 找回窗口装饰 + 按需节拍 + 数据根一致 + 假绿守卫

复审 P1-1(产品页丢窗口装饰):shell 加内容槽位 view_with_content(ui, nav, title, content, forced),
app/view.rs 把 pages::page(...) 塞进真外壳;shell::view 保留给 Route::Agent 回落(删了会让私有
view/nav::rail 变死代码,-D warnings 红)。content() 拆到 shell/fallback.rs 让 mod.rs 回到 365 行。
1180 浅/深新图右上角三个 caption 键实测:ink 中心 y=23.5(栏高 48 的一半)、x 中心 1064.5/1110.5/
1156.5 = 46px 分档的 1065/1111/1157(±0.5px),close 命中区右缘 = 1180 窗角。
偏离 #7 改写成「交互面缺失」并注明本轮已修。

P1-2(harness.rs 402 行):tests 外置到 pages/harness/tests.rs(343 + 64 行);
components/gate.rs 的行数守门从走查 components/ 扩到 src/**(新测试当场抓出 app/tests.rs 416 行,
已按同样办法拆成 app/tests.rs + app/tests/presenter.rs)。

P2-1(常驻重绘 + 每拍重建模型):subscription 只在「截图 / 有 Busy-Running / 有 toast / 3 s 派发
观察窗」时订阅 window::frames();refresh_view 加 view_dirty 门。实测交互模式 9 s:只有 2 行 tick
trace(n=30/60,观察窗内),之后 6.5 s 一条都没有;refreshes 全程停在 7。

P2-2(两个数据根):--data-dir 时 SettingsBridge::with_path(config_path(root)),与后端同根。

P3-2(假绿):新增 RecorderBackend(dispatch 只记账、drain_events 恒空)+ launching_only_dispatches
_and_never_echoes_locally;植入本地回显后该测试实测转红(status 变 Downloading · 0%、can_stop 翻
true),撤回后转绿。
P3-3:尺寸字面量守门目录加 app;P3-1:--force-state 经 pages::Model::forced 作用到产品页控件
(hover 图里页头/列表/动作行/rail/caption 全部可见状态层);视觉 P2-2:加载器名统一走 badge()。

gallery 回归改口径:r2 与「主线 + r1」的 gallery 逐字节相同(cmp IDENTICAL);与 r1 记的
c825e1a 基线不同,差异来自主线 M86/M88 的令牌收口,不是本 mission。
This commit is contained in:
AskaEth committed 2026-11-02 15:56:58 +08:00
1 parent b484998fc9
commit 022778a5a7
17 files changed
+980 -496

No files matched your search

+22 -3
View File
@@ -22,6 +22,10 @@ use std::path::{Path, PathBuf};
/// 单文件行数上限(AGENTS.md §3-1)。
const MAX_LINES: usize = 400;
fn src_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src")
}
fn components_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
@@ -192,10 +196,25 @@ fn t2_no_size_literals_in_components() {
);
}
/// 单文件 ≤400 行:**扫整个 `src/`**,不只 components。
///
/// M90 r2(P1-2)的教训:这条守门原来只遍历 `components/`,于是 `pages/harness.rs` 悄悄长到
/// 402 行没人拦,直到 `guards.yml` 的 file-size job 在 CI 上判红才发现。`guards.yml` 的口径是
/// **全仓**(`git ls-files '*.rs' '*.md' …`),这里至少把本 crate 的 `src/**` 对齐:
/// 谁在 `app/` / `pages/` / `shell/` 把文件推过线,`cargo test` 就先红,不用等 CI。
#[test]
fn every_component_file_stays_under_the_line_limit() {
fn every_source_file_stays_under_the_line_limit() {
let mut files = Vec::new();
rust_files(&src_dir(), &mut files);
assert!(
files.len() >= 40,
"src/ 至少 40 个 .rs,实际 {}:扫描逻辑坏了,这条门禁等于没跑",
files.len()
);
let mut offenders = Vec::new();
for (path, text) in sources() {
for path in files {
let text = std::fs::read_to_string(&path).expect("读源文件");
let lines = text.lines().count();
if lines > MAX_LINES {
offenders.push(format!(
@@ -206,7 +225,7 @@ fn every_component_file_stays_under_the_line_limit() {
}
assert!(
offenders.is_empty(),
"单文件 ≤400 行(AGENTS.md §3-1,guards.yml 会判红):\n{}",
"单文件 ≤400 行(AGENTS.md §3-1,guards.yml 按全仓判红):\n{}",
offenders.join("\n")
);
}