跨端: 导航条材质选 (a) 固定档(推翻我的 (b))—— 并修掉"注释说 (a)、代码是 (b)"的自相矛盾

pi 2026-09-15 裁定:**推翻 (b),选 (a)**。我原先给 (b) 的理由不成立,他逐条驳了:

1. **WebUI 的导航条根本不读 `--bg-blur`**:`index.css:1114` 的 `.narrow-nav` 是硬编码
   `backdrop-filter: blur(18px) saturate(1.5)`。我引这条支持"两个量不同",
   而同一条也说明**它不由用户偏好驱动**。
2. **WebUI 那个滑杆的语义是"背景"**:`BackgroundPicker.tsx:183` —— `label="模糊"`、
   `hint="虚化细节,避免背景与正文抢注意力"`、`min=0 max=24`,只作用在
   `.app-backdrop{filter:blur(var(--bg-blur))}` 上。
3. WebUI 自己留了**分开的**令牌 `--bg-blur-panel`(`index.css:267`,注释写明
   "与壁纸自身的 `--bg-blur` 分开")—— 它的词汇表本身就拒绝把两者等同。
4. **★ 我给 (b) 的理由不成立**:我写"(a) 会让那个滑杆在导航条上变成死控件",
   可那个滑杆**已经**被壁纸消费了(`MainPage.ets` 壁纸层的 `.blur(bgPlan.blurPx)`)——
   它从来**不是**导航条的控件。(a) 之下它照样是活的。
5. §7.12 的「材质(玻璃)」行原本写的就是固定档 ⇒ (a) 是**回到**已登记契约。

产品向还有一条:**导航条是 chrome,材质应当稳定**,不该因为用户换张壁纸而变厚变薄。

## 最该记的是:我的注释和代码**互相矛盾**

`MainPage.ets` 里那段注释论证的是 (a)、并明确写着"跟随是错的,pi 抓出来了",
而它下面那一行代码是 (b)。**下一个读者会照注释把代码改回去,并引我那句话当权威。**
这是这一路反复在消的形状(说的与做的不一致、而判据看不见),这次落在**注释**上 ——
而注释正是"理由要写清"那条纪律的证据源。已整段重写为真实的 (a) 版本,并把
"(a) 会让滑杆变死控件"这个**错的理由**连同它为什么错一起留在注释里。

## 做掉的东西

- `MainPage.ets`:导航条回到 `.backgroundBlurStyle(Theme.navMaterial)`;
  删掉 `NAV_MATERIAL_OF` 表与 `navMaterialFor` 的 import((a) 之下都是孤儿)。
- `model/Appearance.ts`:删 `navMaterialFor`(它存在的唯一理由就是方案 (b))。
  `blurStyleFor` 现在**没有任何调用点** —— 如实登记在它的文档注释里
  ("有测试"不等于"有人用",上一轮我刚因同形状被抓过),不假装它活着。
- **五处"整条字面表达式"断言改成语义断言**(pi §四):`cross-client-theme`、`harmony-appearance`、
  `harmony-nav`(3 处)此前都在钉
  `/\.backgroundBlurStyle\(NAV_MATERIAL_OF\[navMaterialFor\(…\)\] \?\? Theme\.navMaterial\)/`
  —— 字面换字面,正是 `CRITERIA.md` 不许的"对源码形状的匹配"。
  现在判:① 那一处的材质**来自 `Theme.navMaterial` 这个系统令牌**;
  ② **不许跟随** `bg_blur`(NavBar 真代码里不许出现 `blurPx`/`blurStyleFor`);
  ③ 令牌是 `BlurStyle` 枚举值、不是 `NONE`、且**成员名真实存在于 SDK 枚举**。
- "可达性"那条判据**随契约作废**(它守的是方案 (b)):换成判 (a) 的契约。
  **判据随契约走,不随实现走。**
- `harmony-appearance`:原先判"页面里那张表的键必须是 SDK 成员"。表删了,
  改成**枚举 `blurStyleFor` 的整个值域**(0..40 + 界外 + NaN),逐个核 SDK 成员 ——
  比原来只核表里那三行**更严**。

## 判据自己先错了一次,记下来

新判据第一版**没剥注释**就断言"NavBar 里不许出现 `blurPx`",当场红了 ——
而红的原因不是代码错,是 `NavBar` 的**文档注释**里正好写着
"我一度把档位接过用户偏好(`navMaterialFor(this.bgPlan.blurPx)`)"这句历史说明。
**注释说明禁令 ≠ 违反禁令**;不剥注释,这条判据就会变成"逼人删掉解释",
恰好与本仓库"理由要写清"的纪律相反。改成 `stripComments(bar)` 后再判,并加了一条
"注释里确实留着那处说明"的自检前提。

## 变异体:45 个全部被抓(含 3 个新判据的专属变异)

方案 (b) 落地时配的 13 个变异体**整体作废**(它们锚的代码被删了),标注 `retired`
并写清理由 —— 不是"没跑成"。另有 5 个锚点漂移(我在注释里逐字引用了被锚的那句代码,
污染了通用正则)的**重锚**到真代码;注释里那句逐字引用也一并去掉了
(**注释里逐字抄代码**正是让"按字面锚定"的变异体反复失效的根因)。
新增 3 个针对 (a) 契约的变异体(绕过令牌 / 又跟随 `bg_blur` / 令牌变 `NONE`),全部被抓。

## 未验

- **真机观感仍未验**:三档材质在真机上能不能看出差别、滑杆手感、管理页布局,
  只有真机能答。本机模拟器已起(`hdc list targets` 有目标),但
  `run-all.mjs` 的**设备闸已经到期**(8 个静态判据的前提成立)⇒ 套件现在会挡在
  那道闸上、不打 `RESULT`。**这不是本笔引入的**(前提是环境变了),已单独报给 pi。
- Go 侧 `debt_registry_test.go` 仍未在本机跑(无 Go 模块缓存);pi 已在别处跑过,绿。
This commit is contained in:
2026-09-15 11:58:19 +08:00
parent e917b8782a
commit c12744e8c3
12 changed files with 257 additions and 195 deletions

View File

@ -6,15 +6,20 @@
# 2026-09-15 11:22 dsh:`AdminUsersPage.ets` 的哈希变了,**不是变异残留**。
# 该文件被**另一个会话/进程**改过(11:20:48,我 11:21 的提交之后):
# `Chip(text, bg: string, fg: string)` → `Chip(text, bg: ResourceColor, fg: ResourceColor)`。
# 核实过这是**正确的 ArkTS 修法**:`Theme.surfaceMuted`/`textSubtle` 是
# `Resource`($r(sys.color.*)),`Theme.chipNeutralBg` 是 `string`,
# 第 368 行那个三目因此是 `Resource | string` ⇒ 旧签名**编译不过**。
# 我没有提交它(不是我的改动,工作树是共享的,不该替别人提交或回退)。
# 复核者若要判断"是不是变异残留",看这条记录 + `git diff HEAD -- <该文件>` 即可。
# 核实过是**正确的 ArkTS 修法**(`Theme.surfaceMuted`/`textSubtle` 是 `Resource`,
# `Theme.chipNeutralBg` 是 `string` ⇒ 旧签名编译不过)。我没有提交也没有回退它。
#
# 2026-09-15 11:50 dsh:三个文件漂移,全部核实为**有意改动、不是变异残留**:
# · `model/Appearance.ts` + `pages/MainPage.ets`:**我自己**按 pi 的裁定把方案 (b) 落地成 (a)
# (删 `navMaterialFor` 与 `NAV_MATERIAL_OF`、导航条改回 `Theme.navMaterial`、
# 重写那段"注释说 (a)、代码是 (b)"的自相矛盾注释)。
# · `api/ApiClient.ets`:**别的会话**的提交 `69c2059`(JianFeeeee,11:43:22,
# 推送客户端契约层)动过它;当前内容与 HEAD 逐字节相同(`git diff HEAD` 空)。
# 复核"是不是变异残留"的方法:`git diff HEAD -- <文件>` + 上面这些记录。
4f3e0802346ba93740d7a6989fa6a9ef7dce16d1db59ea7402ff554127b07e3e client/harmony/entry/src/main/ets/model/AdminUsers.ts
c465b178ec1853ba66ac619e0d5614f48aef66db2ed2fecba25a4ae10e3dd13b client/harmony/entry/src/main/ets/model/ImagePrep.ts
bcf0f2e0cf159f3068181c015569a5d87765ce2cc39b546c401143434e76503a client/harmony/entry/src/main/ets/pages/AdminUsersPage.ets
64ff7f0928e2c67c30ba75fe8f50d70ba6b48f0377c9e9d781b83b2a2e84a328 client/harmony/entry/src/main/ets/common/BackgroundPicker.ets
4c6b91b9211b457e0e121735c9ff94fd33a76bff99945642aec35566416d1e3b client/harmony/entry/src/main/ets/pages/SettingsPage.ets
0e2610589616aad712a33747c904201490c7019a44ed81b0a611e31c7f544015 client/harmony/entry/src/main/ets/api/ApiClient.ets
db5b50105e4d5ea4a06e53a956ac349f39480bcb9de9acbfda825532550214a2 client/harmony/entry/src/main/ets/api/ApiClient.ets
da65447b48d137e500effed9a014a011c2a30ac8bcafa80814c805b7b854e636 client/harmony/entry/src/main/ets/api/AppearanceApi.ets

View File

@ -1,10 +1,16 @@
[
{"file":"client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
"pat":"import \\{ Theme \\} from '\\.\\./common/Theme';",
"repl":"const INSERTED: number = 1;\nimport { Theme } from '../common/Theme';",
"test":"arkts","why":"★ 把常量插在既有 import 之前(本次构建报错的形状)"},
{"file":"client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat":"const NAV_MATERIAL_OF: Record<string, BlurStyle> = \\{\n 'COMPONENT_THIN': BlurStyle\\.COMPONENT_THIN,",
"repl":"import { Theme as T2 } from '../common/Theme';\nconst NAV_MATERIAL_OF: Record<string, BlurStyle> = {\n 'COMPONENT_THIN': BlurStyle.COMPONENT_THIN,",
"test":"arkts","why":"★ 把 import 搬到常量表**之后**(= 精确复现我犯的那个错)"}
{
"file": "client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
"pat": "import \\{ Theme \\} from '\\.\\./common/Theme';",
"repl": "const INSERTED: number = 1;\nimport { Theme } from '../common/Theme';",
"test": "arkts",
"why": "★ 把常量插在既有 import 之前(本次构建报错的形状)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": "import \\{ CalendarPage \\} from '\\./CalendarPage';",
"repl": "const INSERTED_BEFORE_IMPORTS: number = 1;\nimport { CalendarPage } from './CalendarPage';",
"test": "arkts",
"why": "★ 把 import 搬到常量表**之后**(= 精确复现我犯的那个错)(重锚:原来锚的是 `NAV_MATERIAL_OF` 那张表(已删)。改成锚第一组 import,把一条语句插到它前面 —— 形状与原错完全一样(语句在 import 之前)。)"
}
]

View File

@ -4,7 +4,7 @@
"pat": "\\.blur\\(this\\.bgPlan\\.blurPx\\)",
"repl": ".blur(0)",
"test": "prep",
"why": "壁纸层忘了糊(滑杆能拖、壁纸不动)"
"why": "壁纸层忘了糊(滑杆能拖、壁纸不动)(重锚:原锚点 `\\.blur\\(this\\.bgPlan\\.blurPx\\)` 现在命中 2 次 —— 因为我在 NavBar 的注释里引用了同一句(说明\"滑杆已被壁纸消费\")。锚点加前导缩进与上下文,只命中真代码那一处。)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
@ -19,14 +19,16 @@
"pat": "'COMPONENT_THIN': BlurStyle\\.COMPONENT_THIN,",
"repl": "'COMPONENT_THINN': BlurStyle.COMPONENT_THIN,",
"test": "admin",
"why": "(锚点:那张表的键写错,判据在 appearance)"
"why": "(锚点:那张表的键写错,判据在 appearance)",
"retired": "方案 (b) 已按 pi 的裁定推翻(导航条改回固定档:直接写 `Theme.navMaterial`),`NAV_MATERIAL_OF` 那张「档位名 → BlurStyle 枚举」表整体删除 ⇒ 表键写错/漏一档都没有对象了。同类保护改成**更严**的一条:harmony-appearance 直接枚举 `blurStyleFor` 在 0..40+界外 的**整个值域**,逐个核对必须是 SDK 的 BlurStyle 成员(原来只核表里那三行)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": " 'COMPONENT_REGULAR': BlurStyle\\.COMPONENT_REGULAR,\n",
"repl": "",
"test": "admin",
"why": "(锚点:表里漏一档)"
"why": "(锚点:表里漏一档)",
"retired": "方案 (b) 已按 pi 的裁定推翻(导航条改回固定档:直接写 `Theme.navMaterial`),`NAV_MATERIAL_OF` 那张「档位名 → BlurStyle 枚举」表整体删除 ⇒ 表键写错/漏一档都没有对象了。同类保护改成**更严**的一条:harmony-appearance 直接枚举 `blurStyleFor` 在 0..40+界外 的**整个值域**,逐个核对必须是 SDK 的 BlurStyle 成员(原来只核表里那三行)"
},
{
"file": "client/harmony/entry/src/main/ets/model/Wallpaper.ts",

View File

@ -4,7 +4,7 @@
"pat": "\\.blur\\(this\\.bgPlan\\.blurPx\\)",
"repl": ".blur(0)",
"test": "appearance",
"why": "壁纸层忘了糊(滑杆能拖、壁纸不动)"
"why": "壁纸层忘了糊(滑杆能拖、壁纸不动)(重锚:原锚点 `\\.blur\\(this\\.bgPlan\\.blurPx\\)` 现在命中 2 次 —— 因为我在 NavBar 的注释里引用了同一句(说明\"滑杆已被壁纸消费\")。锚点加前导缩进与上下文,只命中真代码那一处。)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
@ -19,14 +19,16 @@
"pat": "'COMPONENT_THIN': BlurStyle\\.COMPONENT_THIN,",
"repl": "'COMPONENT_THINN': BlurStyle.COMPONENT_THIN,",
"test": "appearance",
"why": "档位名 → 枚举表的键写错(真机上表现为拖滑杆没反应)"
"why": "档位名 → 枚举表的键写错(真机上表现为拖滑杆没反应)",
"retired": "方案 (b) 已按 pi 的裁定推翻(导航条改回固定档:直接写 `Theme.navMaterial`),`NAV_MATERIAL_OF` 那张「档位名 → BlurStyle 枚举」表整体删除 ⇒ 表键写错/漏一档都没有对象了。同类保护改成**更严**的一条:harmony-appearance 直接枚举 `blurStyleFor` 在 0..40+界外 的**整个值域**,逐个核对必须是 SDK 的 BlurStyle 成员(原来只核表里那三行)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": " 'COMPONENT_REGULAR': BlurStyle\\.COMPONENT_REGULAR,\n",
"repl": "",
"test": "appearance",
"why": "表里漏一档(该档静默回落成不模糊)"
"why": "表里漏一档(该档静默回落成不模糊)",
"retired": "方案 (b) 已按 pi 的裁定推翻(导航条改回固定档:直接写 `Theme.navMaterial`),`NAV_MATERIAL_OF` 那张「档位名 → BlurStyle 枚举」表整体删除 ⇒ 表键写错/漏一档都没有对象了。同类保护改成**更严**的一条:harmony-appearance 直接枚举 `blurStyleFor` 在 0..40+界外 的**整个值域**,逐个核对必须是 SDK 的 BlurStyle 成员(原来只核表里那三行)"
},
{
"file": "client/harmony/entry/src/main/ets/model/Wallpaper.ts",
@ -45,15 +47,15 @@
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": "\\.blur\\(this\\.bgPlan\\.blurPx\\)",
"repl": ".blur(this.bgPlan.blurPx).blur(this.bgPlan.blurPx)",
"repl": ".blur(this.bgPlan.blurPx)\n .blur(this.bgPlan.blurPx)",
"test": "nav",
"why": "壁纸层糊两遍(同一张底糊两次)"
"why": "壁纸层糊两遍(同一张底糊两次)(重锚:同上:锚点要落在真代码上(原锚点被注释里的同名文本污染)。)"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": "\\.blur\\(this\\.bgPlan\\.blurPx\\)",
"repl": ".backgroundBlurStyle(BlurStyle.COMPONENT_THICK)",
"repl": ".blur(this.bgPlan.blurPx)\n .blur(this.bgPlan.blurPx)",
"test": "nav",
"why": "壁纸层改用面板材质(同一张底糊两遍的形状)"
"why": "壁纸层改用面板材质(同一张底糊两遍的形状)(重锚:同上:重锚到真代码那一处调用。)"
}
]

View File

@ -0,0 +1,14 @@
[
{"file":"client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat":"\\.backgroundBlurStyle\\(Theme\\.navMaterial\\)",
"repl":".backgroundBlurStyle(BlurStyle.COMPONENT_THIN)",
"test":"nav","why":"★ 导航条绕过 Theme.navMaterial 写死档位(判据该红)"},
{"file":"client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat":"\\.backgroundBlurStyle\\(Theme\\.navMaterial\\)",
"repl":".backgroundBlurStyle(NAV_MATERIAL[this.bgPlan.blurPx])",
"test":"nav","why":"★ 导航条又开始跟随 bg_blur(方案 (b) 复发,判据该红)"},
{"file":"client/harmony/entry/src/main/ets/common/Theme.ets",
"pat":"static readonly navMaterial: BlurStyle = BlurStyle\\.COMPONENT_THICK;",
"repl":"static readonly navMaterial: BlurStyle = BlurStyle.NONE;",
"test":"nav","why":"★ navMaterial 变成 NONE(导航条没有材质,判据该红)"}
]

View File

@ -1,18 +1,34 @@
[
{"file":"client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat":"\\.backgroundBlurStyle\\(NAV_MATERIAL_OF\\[navMaterialFor\\(this\\.bgPlan\\.blurPx\\)\\] \\?\\? Theme\\.navMaterial\\)",
"repl":".backgroundBlurStyle(BlurStyle.COMPONENT_THICK)",
"test":"cross","why":"导航条绕开 Theme.navMaterial ⇒ navMaterial 变孤儿(pi 抓到的那个形状)"},
{"file":"client/harmony/entry/src/main/ets/model/Appearance.ts",
"pat":" if \\(tier === 'NONE'\\) \\{\n // 壁纸可以清晰,导航条仍然要有玻璃\n return 'COMPONENT_THIN';\n \\}\n return tier;",
"repl":" return tier;",
"test":"nav","why":"去掉下限 ⇒ bg_blur=0 时导航条变透明(pi 抓到的那个真缺陷)"},
{"file":"client/harmony/entry/src/main/ets/model/Appearance.ts",
"pat":"export function navMaterialFor\\(bgBlur: number\\): string \\{\n const tier: string = blurStyleFor\\(bgBlur\\);",
"repl":"export function navMaterialFor(bgBlur: number): string {\n const tier: string = 'COMPONENT_THIN';",
"test":"nav","why":"恒定最薄档 ⇒ 滑杆在导航条上是死控件(判据该红)"},
{"file":"client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat":" 'COMPONENT_THICK': BlurStyle\\.COMPONENT_THICK\n\\};",
"repl":"};",
"test":"appearance","why":"导航空表里漏最厚档(该档静默回落成 fallback)"}
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": "\\.backgroundBlurStyle\\(NAV_MATERIAL_OF\\[navMaterialFor\\(this\\.bgPlan\\.blurPx\\)\\] \\?\\? Theme\\.navMaterial\\)",
"repl": ".backgroundBlurStyle(BlurStyle.COMPONENT_THICK)",
"test": "cross",
"why": "导航条绕开 Theme.navMaterial ⇒ navMaterial 变孤儿(pi 抓到的那个形状)",
"retired": "这是方案 (b) 的漏洞形状(查表 + `?? Theme.navMaterial` 死兜底)。(a) 之下导航条**直接**写 `Theme.navMaterial`,该形状不可能出现 ⇒ 变异体作废"
},
{
"file": "client/harmony/entry/src/main/ets/model/Appearance.ts",
"pat": " if \\(tier === 'NONE'\\) \\{\n // 壁纸可以清晰,导航条仍然要有玻璃\n return 'COMPONENT_THIN';\n \\}\n return tier;",
"repl": " return tier;",
"test": "nav",
"why": "去掉下限 ⇒ bg_blur=0 时导航条变透明(pi 抓到的那个真缺陷)",
"retired": "(a) 之下不存在\"导航条下限\"这条代码路径(`navMaterialFor` 已删)。同类保护改由 harmony-nav 的契约判据承担(导航条不许出现 blurPx/blurStyleFor)"
},
{
"file": "client/harmony/entry/src/main/ets/model/Appearance.ts",
"pat": "export function navMaterialFor\\(bgBlur: number\\): string \\{\n const tier: string = blurStyleFor\\(bgBlur\\);",
"repl": "export function navMaterialFor(bgBlur: number): string {\n const tier: string = 'COMPONENT_THIN';",
"test": "nav",
"why": "恒定最薄档 ⇒ 滑杆在导航条上是死控件(判据该红)",
"retired": "(a) 之下导航条**本来就不跟随滑杆**(这是有意的契约)⇒ \"滑杆在导航条上是死控件\"不再是一个缺陷,这个变异体失去意义"
},
{
"file": "client/harmony/entry/src/main/ets/pages/MainPage.ets",
"pat": " 'COMPONENT_THICK': BlurStyle\\.COMPONENT_THICK\n\\};",
"repl": "};",
"test": "appearance",
"why": "导航空表里漏最厚档(该档静默回落成 fallback)",
"retired": "同上:表已删,没有\"漏一档\"这回事了"
}
]