状态:实施中 —— 批 0-A(设计系统基座)与批 0-B(图标集)已交付并通过评审;批 0 的其余部分(ADR-033~035 · 豁免表纠偏 · 拆 4 个 >600 行文件 · 原语三层)待立计划 2026-09-12 追加(批 2 收口,原文保留不改):批 1(删除批) 与**批 2(包体治理)**已交付,交付记录见下「交付记录」节(批 1 = 「删除批」节 · 批 2 = 「批 2 · 包体治理」节)。上面那句「批 0 其余部分待立计划」写于 2026-09-11,批 2 收口时未复核其是否仍成立 —— 批 0-C1(行数治理)/ 0-C2(拆超限文件)/ 0-D(L1 原语层,ADR-033)的落地状态请以规格 §14 的表格与本文件各节记录为准。 权威规格:2026-09-11-frontend-redesign-design.md(513 行,本系列的唯一定义源;本文档只做批次归属与交付记录) 关联:UX 市场惯例审计(本设计的直接输入)· 长期优化清单 · 需求池 · ADR-010(本系列修订为退役)
v0.21 已由「执行型智能体(目标执行层)」预留,且预留写得很实 —— 2026-09-05-goal-execution-agent-design.md 内有 v0.21.0(P0 执行数据层)/ v0.21.1(P1 AI 增强层)/ v0.21.2(P2 闭环增强)三档明确映射,并记录「裁决点:执行层走 v0.21 系列顺延,建议顺延不插队」;v0.20.md 的 D6 亦载明「v0.21 系列留给执行型智能体」。
本系列为不同主题(前端重设计 ≠ 目标执行层),故取 v0.22:不插队、不改动既有预留、不要求任何已记录决策回退。若将来执行型智能体顺延,其 v0.21 归属不受本系列影响。
把「一份内容只有一种样子」的产品,改造成「一份内容有多种样子 + 会呼吸、会生长、会显影的纸」—— 在此之前先补上它从未有过的地基:token 层、原语层、视图层。
REQ 预留:REQ-318 起(现池止于 REQ-317)。具体条目于每批开工轮的「需求池登记」步骤落位,本文档不预写未排期条目,避免出现指向不存在条目的引用。
| 批 | 内容 | 主题归属 | REQ |
|---|---|---|---|
| v0.22.0 · 批 0 | 基座:ADR-032~035 + 修订 ADR-010 · 豁免表纠偏 · 拆 4 个超限文件 · token 变量层 · z-index 六档标尺 · 图标集 + 单测 · 原语三层 | 治理 + 基建 | REQ-318 起 |
| v0.22.1 · 批 1 | 删除批(纯减法):21 条命令 + 补缝三连及其连带模块 + 清理死文案 | API 面收敛 | — |
| v0.22.2 · 批 2 | 包体基线治理:manualChunks + 按页动态 import + 量首屏 gzip(现状 651.25 kB gzip / 预算 200 kB) ✅ 已落(2026-09-12) |
性能 | — |
2026-09-12 批 2 收口更正:上表 v0.22.2 行的「现状 651.25 kB」是过期快照 —— 实测开工基线是 654.72 kB;交付终态 92.79 kB(−85.83%)⇒ ✅ 达标。逐条读数、瓶颈清单与 follow-ups 见「批 2 · 包体治理」节。 2026-09-12 批 3 收口追加:上表 v0.22.3 行已标 ✅。批 3 的开工点 = 上表 v0.22.2 交付终态 92.79 kB;批 3 终态首屏 97.16 kB(Δ+4.37 kB)⇒ 仍远低于 200 kB 判据。逐条读数、三条验收、计划错误与 follow-ups 见「批 3 · 壳层落地」节。 | v0.22.3 · 批 3 | 壳层落地:A′ 顶部 Tab + ⌘K + 溢出两级策略 + 窗口尺寸 + 列注册表 + 断点 +
--nav-h✅ 已落(2026-09-12) | 布局 | REQ-318 起 | | v0.22.4 · 批 4 | 原语迁移进各域:20 弹层 / 44 空态 / 85 加载态 / 196 错误行 / 4 toast / 2 confirm / Button·Surface·Text | 组件体系 | — | | v0.22.5 · 批 5 | 视图层样板:viewRegistry+ViewSwitcher+ 会话 4 视图 + 笔记 3 视图 + 惰性挂载 + flushSave 守卫 | 展示形式 | REQ-318 起 | | v0.22.6 · 批 6 | 动效系统:GSAP 接入 + token + 四层纲领 + 三档强度 + 相变两态 + 6 个签名动效 +usePresence✅ 已落(2026-09-13) | 动效 | REQ-318 起 | | v0.22.7 · 批 7 | 未接线落地:12 条补 UI(含kb_search→ ⌘K)· 标签线 · 档位通道 · B 桶 3 条撤下 IPC | 能力补齐 | REQ-318 起 | | v0.22.8 · 批 8 | 治理收口:豁免表终态 · 回写ui-ux-system.md/theme.md· 新增动效规范章节 · 需求池同步 | 治理 | — |
2026-09-13 批 6 收口追加(R6.7 的批次归属就地消歧;上表原文一字未改):上表 v0.22.6 行已标 ✅(批 6 = 动效系统,终态见「批 6 · 动效系统」节)。
⚠️ 上表 v0.22.8 行的「新增动效规范章节」与规格 §14(:836)两说 —— 实际落点:动效规范章节(docs/standards/motion.md)已在批 6 落地(T1,bffed928;并已进docs/standards/README.md索引),批 8 留下的是docs/product/ui-ux-system.md/theme.md的四层动效 / 三档强度回写(规格 §14 逐字仍留批 8;progress.md§一 的「🟡 待裁」仍在)⇒ v0.22.8 行按本加注读。
实施粒度约定:不建议一次性生成全部 9 批的实施计划。每批各自一份实施计划,且后一批的计划在前一批验收通过后再写 —— 批 3 之后的细节依赖批 0–2 的实测结果(尤其包体瓶颈清单与拆件后的真实文件结构)。
| 层 | 关键裁决 |
|---|---|
| L0 视觉基座 | 基座路线 C 全部从代码(回写规格为目标态)· 视觉方向 C 活页(纸 + 中文衬线正文 + 印章 + 到期刻度)· 材质语言 D 显影(四档墨度 = 确定度)· 来源标记 剪报底纹默认开 · 图标语言 A 自绘线性图标集 |
| L1 原语层 | 收敛 10 类原语 · 删除哲学 甲 两档分级(低危可逆 → 撤销 toast 10s;高危 → 确认框并列明级联;级联不给撤销)· 软删回收站不做(独立技术债)· 拆件顺序 NotesPage → NoteListView → SessionDetailPanel → ClassroomPage(行为等价) |
| L2 容器与壳 | 导航 A′ 顶部 Tab(8 项 + ⌘K + 设置下沉齿轮)· 域数纪律:新增能力进域内页签 · 顶栏溢出两级 · 相变两态(采集/复习)· 列契约三列上限 + 单一注册表 · 窗口 1280×800 / 最小 1024×640 |
| L3 视图层 | 四部件 ViewSpec / viewRegistry / ViewSwitcher / 依赖方向 · 本批会话 4 + 笔记 3 视图(新增 5 个组件)· 原文永远保留 · 非默认视图惰性挂载 · 编辑态切视图先 flushSave(失败则阻断) |
| L4 动效 | 引擎 GSAP(core + Flip + ScrollTo + CustomEase)· 纲领 「活的纸」四层(响应/环境/编排/生长)· 基调 丙 双基调(有「读数」用仪器,有「文字」用纸墨)· 强度三档,系统 prefers-reduced-motion 优先 |
| L5 未接线 | A/B 桶能接入 UI 的尽量接入 · C 桶除视频档案四连外删去 · 视频档案四连删 3 留 2 · 档位通道做完整 · 标签线补完 · AI 补缝三连全删并修订 ADR-010 |
红线:本地优先不破 · 不引入路由库 · 不砍任何已接线功能 · 每批 tsc/vitest/cargo test 全绿 · 行数红线(不往 4 个超限文件里加代码)· 后端数据模型零改动,除下列两处。
| # | 例外 | 原因 | 回滚 |
|---|---|---|---|
| E1 | MemoryEntry 增加 tier 字段 |
档案记忆库根本没有 tier 轴 → 「画面档位选完不生效、也不跨会话记住」 | 旧 JSON 无该字段时按 None 读取(向后兼容读,无需迁移) |
| E2 | tag_colors 补种子/迁移写入 |
表建了但永远没有数据 → 前端色板第三档恒不生效 | 迁移可空跑;标签色本身是可逆 UI 状态 |
新增例外须再次裁决;不得由这两处推而广之为先例。
- 15 个 >600 行文件 → 0(实测值:前端 5 + Rust 10;规格原文的「4 个」只扫了前端且漏掉
SessionListPanel.tsx);>300 行 100% 在豁免表内且数值与实测一致。2026-09-11 用户裁决:范围取实测 15 个;口径取「全部行数」,以
[System.IO.File]::ReadAllLines(path, UTF8).Count为准(即scripts/line-limits.mjs),禁用Get-Content(少算可达 56 行)·Measure-Object -Line(只数非空行)· 字节0x0A计数(末尾无换行时少算 1)。 执行机制:node scripts/line-limits.mjs(本地提交门禁 + CI--full守数值),>600 用棘轮只减不增 —— 拆分由 0-C2(前端 5)/ 0-C3(Rust 10)推进,每拆完一个从FROZEN_OVER_LIMIT删一行。 债务未关:15 个文件当前仍全部 >600,棘轮只保证「不再增加」,→ 0由 0-C2 / 0-C3 兑现。该缺口的完整实测与豁免表治理债登记为TD-2026-09-11-H(清单与证据在docs/tech-debt/review-2026-09-11.md——⚠️ 该文件目前未入 git,故此处不写成 Markdown 链接,否则新克隆会断链)。🔻 2026-09-13 加注(T26 归档后补记):该目录已于批 8 归档到docs/archive/2026-09-13/(快照 review-2026-09-11.md,内容零改动);本行理由在当时成立,原文保留。 - 手写弹层 20 → 全走
Modal;z-index 不同值 17 → ≤6 档;role="dialog"+ 焦点陷阱 20/20 - 空态 / 加载 / 错误行 / 弱化文本 / 卡片边框 五类重复 → 各自 1 个原语
- CSS 变量 0 → 覆盖全部语义色/字阶/间距/圆角/时长/缓动;hex 88 → ≤ token 数
prefers-reduced-motion覆盖率 100%,系统优先于强度档位- 会话与笔记各 ≥2 种展示形式可用,原文形态不丢
- 47 条未接线命令逐个有结论,无「不知道」
- 标签能写进去且标签过滤面板有内容;画面档位选完真的生效且跨会话记住
- JS 包首屏 gzip 达标或给出瓶颈清单;GSAP 只在独立 chunk 懒加载
进度(批 2 收口,2026-09-12):✅ 达标 —— 首屏 JS gzip 654.72 → 92.79 kB(预算
< 200 kB),守卫scripts/check-bundle-budget.mjsexit 0、余量 107.21 kB。GSAP 未安装(批 2 硬非目标),但vendor-gsap独立 chunk 槽位已预留并被单测钉住,批 6 必须用import()。⚠️ 达标不来自manualChunks(它一字节不降首屏),全部来自import():8 页懒 + 课堂页静态 + 两窗变体 + 对话面板。 - 6 个签名动效各自可中断、可反向,reduced-motion 下正确降级
npx tsc --noEmit0 错 ·npx vitest run全绿 ·cargo test全绿(每批)进度(批 3 收口,2026-09-12):八门禁全绿 ——
line-limits --full>6000 · 301–600 档 123 · 登记条目 123(exit 0)·docs-checkexit 0 · registry 312/312/0 ·tsc --noEmit0 错 · vitest 143 文件 / 1370 用例 / 0 失败(既有 1233 条逐文件一模一样、一条未少;+18 个新文件 / +137 用例)·cargo test --test app_lib_tests2300 passed / 0 failed / 6 ignored(逐字持平,本批零 Rust 改动)· 首屏预算守卫 exit 0 · 97.16 kB · 余量 102.85 kB(CSS 与字体不计入该判据,只报告)· clippy 唯一位置集合 20 = 基线(SET-IDENTICAL)。⚠️ 一条既有 flake 的处置:app/src/components/KnowledgeGraphView.test.tsx > 单击节点 → 1~2 度邻居展开、范围外淡出在批 3 开工基线树a7bd1899上复现过(全量1232 passed / 1 failed,隔离复跑 11 passed / exit 0);批 3 终态这次全量未复现(1370/1370)。⇒ 既有负载敏感 flake,非本批引入;两种读数都记在「批 3 · 壳层落地」节。
逐批追加。
2026-09-12 追加(收口评审 M-3 结清)—— 提交数的口径声明:本行的「12 个提交」= 含左端点(实测
git rev-list --count 4e3bfa1a^..7148533e= 12)。同一记号按 git 原生语义A..B不含左端点,读数为 11。⇒ 本文档批次行一律采用「含左端点」口径(A^..B);批 2 行是全文唯一例外,已在彼处就地注明。
交付:ADR-032(前端设计系统与 token 层落地)· token 单一真源 app/scripts/gen-tokens.mjs + 生成产物 app/src/ui/{tokens.ts,tokens.gen.ts,tokens.css} · 对比度纯函数 contrast.ts(WCAG 相对亮度 / 对比度 / AA 判定)· z-index 六档标尺 zIndex.ts(17 个散值收敛为 6 档)· 漂移守卫 tokens.drift.test.ts(行尾归一,防新检出假阳性)· 对比度守卫(绑定底色而非硬编码常量)。
验收:tsc 0 错 · vitest 全绿 · 终局全分支评审 + 修复波 + 受限复审通过。
规格修正:§4.1 色阶 16 token 的对比度按实测回写 —— --due 亮档 #B26A12(4.06:1) → #A05F10(4.86 / 5.07),作废值 3.1:1 → 3.22:1。
过程中纠正的计划错误(6 处,均由实施者或评审者实测抓出):ADR 相对链接层级写错 · 生成器「有第二份 WCAG 公式」的不实描述 · 漂移测试逐字节比对在新检出会假阳性 · 对比度守卫测硬编码常量而非底色 · 两处 normalizeEol 已分叉 · 断言计数不符。
2026-09-12 追加(收口评审 M-3 结清)—— 口径同上(含左端点):实测
git rev-list --count 25bd5d99^..2fbf81d4= 21;不含左端点25bd5d99..2fbf81d4= 20。
交付:app/src/ui/icons/ —— types.ts(几何契约,三种元素白名单 path/circle/rect、无颜色字段)· paths.domain.ts(域 9)+ paths.action.ts(对象与动作 15)= 24 个自绘图标 · paths.ts(合并注册表 + 启动期重名检测 + 零列名字面量联合 IconName)· Icon.tsx(唯一渲染入口:currentColor / 默认 aria-hidden / 有 label 时角色转为 img)· index.ts(导出面 10 项)· 三个测试文件共 21 例 · 内联 <svg> 棘轮守卫 no-inline-svg.test.ts · app/src/node-builtins.d.ts 扩写(无 @types/node 前提下的最小环境声明,不用 any)。
验收:tsc --noEmit 0 错 · vitest 103 files / 809 tests 全绿(图标层 21/21)· cargo test exit 0(2337 passed / 0 failed / 6 ignored;本批零 Rust 改动,属回归确认)· docs-check ✅ · 零新增依赖 · 界面外观零变化(本批只定义不消费:未改任何组件、未替换任何 emoji,消费在批 4)。
终局全分支评审(2026-09-11):READY_WITH_FOLLOWUPS —— 0 Critical / 0 Important。批次验收 4 条经评审者逐条独立判定,4/4 满足;三个历史静默缺陷(网格测试空转、IconName 塌回 string、棘轮同前缀漏判)均已闭合并由评审者独立复现。未发现新的 Critical/Important 级静默失败模式。 评审提出的 follow-up 已全部写进计划「交接给批 3 / 批 4 的遗留项」节,无需本批返工。
评审新发现的代码缺陷(1 处,已修 ecbaf364):paths.ts 的重名检测 if (merged[name]) 走原型链 —— 名为 constructor 的图标(命名规范恰好放行)即使毫无重名也会抛「图标重名」,属误导性的启动期崩溃。修为 Object.prototype.hasOwnProperty.call(...)(不用 Object.hasOwn:它是 ES2022,而本仓 target/lib 为 ES2020)。已用真实模块探针自证:插入 constructor 图标后模块正常导入(旧代码则导入期抛错、全灭)。
两项关键实测结果:
- 24 组几何数据零转录漂移 —— 与计划数据逐字比对(域 9/9、动作 15/15,键序一致),并用变异探针证明该比对非空转。
- 棘轮基线为空 ——
src/**/*.ts(x)共 327 个文件,src/ui/icons/之外没有任何内联<svg>⇒ 棘轮语义实际为「一个都不许新增」(比「不许增加」更强,且无需特赦任何存量文件)。守卫已用探针证明会真实失败。⚠️ 其第 2 个断言(基线过期项检查)在空基线下休眠,不计入当前防护力。
过程中纠正的计划错误(10 处,逐条见批台账):index.ts 的真实 TS2459 · IconName 偏差裁定撤回并改为立即修 · ACTION_ICON_PATHS 用了计划自己明令禁止的宽注解 · DOMAIN_ICON_PATHS 缺 satisfies · 「as const satisfies 会 TS1360」不成立(实测不报错)· 圆越界举例方向写反 · 类型断言片段缺 void(noUnusedLocals 下 TS6133)· Task 3 的守卫探针位置无效(写在被设计性排除的目录内)· Task 3 守卫代码在本仓编译不过(缺声明,tsc exit 2)· 棘轮守卫用裸字符串前缀排除图标目录 ⇒ 同前缀兄弟目录(ui/icons-legacy/)被静默豁免(计划原文如此,由终局任务评审用双针实测抓出,见提交 c22d2bda)。
另有 2 处「控制方在交接单里给出的结论」被终局评审推翻并已更正(记录在案,勿重犯):① 「mergeGroups 重名不可测 ⇒ 接受现状」——错,评审者用 vi.doMock + vi.resetModules 在不动数据文件下即复现该抛错(本仓已有 46 个测试文件用 vi.mock),结论改为可测、应补;② 「Icon.tsx 的 <rect> 兜底会静默渲染坐标全 undefined」——错,向联合加入第 4 种元素必然 5×TS2339 编译失败,故 switch + assertNever 只是可读性收益、批 3/4 不必排期。两处已改写进计划交接单。
交付:IPC 注册面 334 → 312(−22 条「有定义、有注册、前端生产代码零调用」的命令)· 补缝式 AI 在代码层清空(三命令 + ai_judge 判定器模块 + AiMockAdapter::enhance + ai_protocol.rs 的 AiEnhance* 半边)· 产物模板子系统整族退役(commands_artifacts.rs + artifact_templates{,_visual,_voice,_tests}.rs + narrative_detect{,_tests}.rs)· ADR-010 转「已废弃」(文件保留 + 退役节 + 索引 / 2 处交叉引用 / 需求池同步)· structuredBlocks.ts 的 "AI 增强待 V1.0" 死文案及其函数与断言清除 · 豁免表 app_commands.rs 行人工理由列按实测更正(334 → 312 条)。
验收(收口单元 2026-09-12 串行实测,全部 exit 0):check-command-registry = 定义 312 / 注册 312 / 重复 0 · cargo test --test app_lib_tests = 2300 passed / 0 failed / 6 ignored · cargo build = 0 条 dead_code(仅既有 lib.rs 多 target 提示 + build-script DLL 占用噪声)· cargo clippy --all-targets = 19 条,集合与开工基线 identical · line-limits --full = >600 0 · 301–600 档 123 · 登记条目 123 · docs-check exit 0 · tsc --noEmit 0 错 · vitest 124 文件 / 1124 用例。
账(与计划的差额逐条归因):Rust 用例 2359 → 2300(−59),而计划原预测只删 16 条 —— 2359 → 2334(T3,−25:控制方把删除面扩大为整族 7 文件)→ 2308(T4+T5 合并单元,−26 = 9+7+10)→ 2304(T6,−4)→ 2300(T7,−4)。前端 1125 → 1124(−1,T9)。删文件 10 个(git diff --name-status --diff-filter=D e96ab63d HEAD)· 301–600 档 125 → 123。每一笔计划外删除都由控制方在「STOP → 实测绿色解 → 授权 → 落地 → 门禁回绿」的闭环里逐条裁决,不是实施者自行扩大范围。
规格漂移纠正:§9 汇总 21 → 22(open_capture_float 由「待核实」改判为「删」,B 桶唯一无把握项结清)· §10 批 1 行打进度标记 + 归属注 · §11 验收 7 补进度注 · §13「删命令删到活代码」缓解栏升级为三向复核 + 同名三域归属 + 子串陷阱清单 · §14 豁免表与交付记录落点行更新 · 需求池 REQ-055 / REQ-056 / REQ-135 / REQ-193 / REQ-201 改真(REQ-050/052/053 属功能级改写,登记待办)。
过程中纠正的计划错误(本批最有价值的交付,逐条可复现):
- 「不删」清单被证伪五次:
artifact_templates族(T3)·ai_protocol.rs的AiEnhance*半边(T4)· 「5 处调用点」实为 4 调用 + 3 定义(T2)·vad_threshold_slot三符号(T6)·spec_from_kind(T7)。根因统一:用「看起来还有人用」代替「删除后可达性」,而build_artifact的「25 处命中」多为同一子系统内部自引用。替代方法已写进批 1 计划「收口回写」节收口一。 - 计划与自身 Global Constraints 不自洽(T4 / T6 / T7 各一次):保留某符号必然新增
dead_code⇒ 收口门禁不可达绿。裁决一律以 Global Constraints 为准(先例是规格对vad_threshold_diag的「不留半成品」判词),并要求先给出实测绿色解再授权。 - 删除粒度可升可降:T3 首次 STOP 时把「符号级警告」误读成「模块级矛盾」,正解是降一个粒度(按警告逐符号外科删除);T4/T6/T7 则是升一个粒度(整族删除才自洽)。⇒ 门禁红了不是让你放宽门禁,而是提示删除粒度不对。
- 一条「覆盖损失」被评审证伪:T7 报告称夹具改写损失了
lookup_form的 kind 回退分支覆盖,实测该分支删除前就从未被任何测试执行(先存缺口,非回归)⇒ 补测动作仍批准,理由改写为「补先存缺口」。 Copy-Item保留 mtime ⇒ cargo 回放陈旧警告:还原源文件后必须先touch再复验(曾读出 build 20 / clippy 35 的假读数,与哈希证据矛盾)。- PowerShell 辅助函数命名撞内置别名:删除脚本把函数命名为
Rd,而rd是Remove-Item的别名 ⇒ 「读失败但写/删照常执行」(7 文件被删、lib.rs被写成 1 行;已从 HEAD 全量恢复重做)。⇒ 辅助函数禁用rd/rm/mv/cp/ls/cd等别名名。 cmd /c "git show X^:path"会吃掉^(静默变成看当前提交)⇒ 读历史文件一律在 PowerShell 里读完整文件,绝不读 diff hunk 推断全文。
本批新增/确认的读数陷阱(通用,建议后续批次当清单用):
\b正则在全角)(U+FF09)前永不匹配 ⇒ 残留面扫描一律git grep -nF逐名字面量(本批因此漏过 1 处悬挂注释)。git archive在未跟踪的子目录里执行 ⇒ 10240 字节空归档 + exit 0 ⇒ 基于它的「0 命中」全是假绿。一律在仓库根 + 绝对-o,并以「完整树约 14.6 MB」自检。- 在
git archive解包树里跑git grep⇒ 静默 0 命中(该目录无.git)——仪器坏,不是树干净。 - 裸
includes()/ 子串 grep 判「命令是否还有人调用」⇒ 本批实测 6 例假活(refine_session⊂"auto_refine_session"·finish_session⊂"finish_photo_session"·video_profile_memory⊂"video_profile_memory.json"·recognize_image⊂recognize_image_timeout·remember_video_profile⊂remember_video_profile_form/_domain)。 - 全树扫描必须排除
.superpowers/:评审者在tmp/解包的归档副本会被当成命中源(本批一次假 313 命中)。 core.autocrlf=true且工作树存在 LF-only 异类文件 ⇒git hash-object相等与空的git diff都可能掩盖 EOL 差异;git status干净是唯一可靠判据。- 任何「0 命中」结论必须点名仪器,并先证明它能命中一个已知存在的串、且对无意义串报 0 —— 本批 6 次假绿/假阴性全部由这一条抓住或本该抓住。
未做(登记,逐条带归属):structuredBlocks.ts 整模块存废 → 批 7(接线或删除二选一,含 .ed-low-confidence)· 25 条「补 UI / 登记不排期 / 撤下 IPC / 有意保留」→ 批 7(有意保留 3 条无期)· 旧凭据槽 "default" 的应用内撤销路径 → 处理 AI 凭据的批次(产品裁决)· VAD 写端 publish 当前 0 测试覆盖 → 批 7 或 VAD 诊断批次(可选)· artifact 行已无任何新建路径(refine 链的正当性只对历史产物行成立)→ 登记,与批 7 的产物判定同批· ASR_REQUEST_TIMEOUT 的删除事实 / 取回方式 / 重引入触发条件 → 登记(无期)· commands_video.rs:279 的 @param form 注释与实现不符 → 登记(无期,纯注释)· REQ-050 / REQ-052 / REQ-053 的功能级陈旧表述 → 产品文档 pass · 真机 IPC 冒烟整批跳过(2026-09-11 用户裁决;等价性依据是静态证据链 + 编译期路径解析,批 3 起如需真机结论必须重新派发,不要沿用「已跳过」)。
2026-09-12 追加(收口评审 M-3 结清)—— 本行是全文唯一采用「不含左端点」口径的批次行,现已声明:
e46e0e82..9921767c按 git 原生语义不含左端点 ⇒ 11 个提交(含左端点e46e0e82^..9921767c= 12)。相邻批次行用的是「含左端点」口径(见批 0-A / 0-B 行的注),两种数法都成立、但不可混用。 另:批 2 的收口回写提交不在该区间内 ——3f9c64ce(计划/规格回写)·af57dab8(本节落盘)·49f953f4(超长 subject 登记)·f5c35990(回写定位改锚)共 4 个都在9921767c之后 ⇒ 批 2 的提交应按「11(实施,不含左端点)+ 4(收口回写)」表述(若用含左端点口径则是 12 + 4)。
交付:app/vite.config.ts 接线 manualChunks(7 个 vendor 族:editor/katex/canvas/md/react/tauri + 为批 6 预留的 gsap 槽)· 纯函数 app/src/build/manualChunks.ts + 单测 manualChunks.test.ts(本批唯一新增的测试文件)· 首屏预算守卫 scripts/check-bundle-budget.mjs(含 14 条 --self-test,口径 = 入口 + 只沿静态 ESM import 可达的 .js,gzip zlib level 6,十进制 kB)· 首屏静态可达性探针 scripts/bundle-eager-graph.mjs · app/src/App.tsx 的模块加载边界重写(8 个页面按页 import() + 首访挂载保活、两个窗口变体面板按变体懒加载、AiConversationDock 首开挂载)· .gitignore 取反 app/src/build/。三个非目标全部守住:不装 GSAP · 不动 app/src/ui/primitives/** · 不碰任何 Rust。
验收(收口单元 2026-09-12 串行实测,全部 exit 0):check-command-registry 312/312/0 · line-limits --full >600 0 · 301–600 档 123 · 登记条目 123 · docs-check exit 0(扫描 273 / 检查 173)· tsc --noEmit 0 错 · vitest 125 文件 / 1233 用例 · cargo test --test app_lib_tests 2300 passed / 0 failed / 6 ignored · cargo clippy --all-targets 19 条,集合 identical(集合比对,禁止比 sha256)· check-bundle-budget.mjs(含真实构建)exit 0 · 首屏 92.79 kB · 余量 107.21 kB。
账(首屏 gzip 前后对比 + chunk 拓扑):首屏 JS gzip 654,722 → 92,789 B = 654.72 → 92.79 kB(−561,933 B = −85.83%),预算利用率 46.39%;首屏 chunk 1 → 3(index 27.87 + vendor-react 60.37 + vendor-tauri 4.55 kB);懒 chunk 0 → 22 个 / 574.84 kB;全部 JS chunk 1 → 25;首屏可达应用源文件 251 → 47、首屏 npm 包 15 → 4(react / react-dom / @tauri-apps/api / plugin-dialog);构建模块数 746 不变。两窗变体首屏 ?float=1 97.29 kB · ?overlay=1 94.19 kB(均达标)。
诚实代价(不许省略):全部 JS gzip +12,908 B = +12.91 kB(+1.97%)(25 chunk 的样板与跨 chunk
import开销,总量守恒不成立)·index.html+166 B(两条modulepreload)· CSS gzip +36 B ·>500 kB警告仍在(vendor-editor608,384 B raw / 208.59 kB gzip,整块落在懒 chunk 内)·dist总量只降 4,415 B(−0.14%),59 个 KaTeX 字体 1,072,948 B 一字节未动 ⇒ 磁盘与安装包不因此变小(首屏省下的 561.93 kB 是挪进懒 chunk,不是消失)。
规格漂移纠正:§2 包体行 651.25 → 654.72 kB(过期快照;「超标 3.26 倍」→ 3.27×)+ 批 2 终态与诚实代价注 · §10 批 2 行打进度标记并加口径注(manualChunks 自身一个字节都不降首屏;下降全部来自 import(),Task 6/7/8 三条缺一不可)+ 收口行 + 瓶颈清单相对链接 · §11 验收 9 加进度注(✅ 达标;GSAP 未装但槽位已预留并被单测钉住)· §13「包体继续膨胀」缓解栏补批 2 已落项与守卫两个待修缺口 · §14 豁免表行(App.tsx 439→519,登记值已同步)与交付记录落点行更新。
过程中纠正的计划错误(本批最有价值的交付,逐条可复现;全文见批 2 计划就地加注):
- 计划 L1317「窗口变体首屏 = 入口 + 零 vendor」为假 —— 三个窗口共用同一份
index.html(WebviewUrl::App("index.html?float=1"))⇒ 入口静态闭包逐字节相同,早返回只能切断动态边。实测 = 入口 + 4 个 vendor chunk ⇒ 变体 97.29 / 94.19 kB。连带「变体 < 60 kB」结构性不可达(vendor-react单独即 60,367 B > 60 kB)。 - 计划 Task 6 的「9 页 lazy / 0 静态页面 import」经控制方裁决改判为「8 懒 + 课堂页静态」:课堂是默认页,懒它会让「首屏即被抓取的 20.04 kB」被记作 lazy ⇒ 首屏读数被低估 20.04 kB。计划 Step 2 预期、Step 3 标题与代码、提交 subject、V1/V2 全部随之过期(实测 V1=8 / V2=1)。
- 计划 Task 6/8 的 Files 清单漏了必须的
docs/standards/line-limit-exemptions.md刷新(App.tsx439 → 519 行)。收口时node scripts/line-limits.mjs --write无 diff(前序任务已刷新)⇒ 收口提交不含该文件(按计划 Step 6 的规则)。 - 计划 Task 10 V4 期望 vitest
124/1124不可能成立:本批净增恰好一个测试文件 ⇒ 终态 125 文件 / 1233 用例。判据改为「用例数只增不减 ∧ 0 处断言修改 / 0 处新增await/ 0 处改 mock」(Task 6/7/8 各自前后逐字相同)。 - 计划 Task 9 说「四个候选」实为五个(
katex双版本 ·structuredBlocks孤儿 ·@codemirror/lang-markdown传递链 ·basicSetup附带件 · 59 个 KaTeX 字体),交付是五行结论表,无一条同时过「size-only ∧ behavior-neutral」双闸。 - 单位漂移(会造出假 Δ):计划 §表 1 的「字体 1,047.80 kB」「dist 3,157.49 kB」与 Task 9 候选 5 的
1,047.80 / 797.64都是 KiB,十进制是 1,072.95 / 3,233.27 与 1,072.95 / 816.78 kB。候选 3/4 的59.07 / 24.11 kB是分裂前的探针值(探针总量比真实构建膨胀 +6.3%),落地 A/B 实测为 −84.04 / −45.10 kB,且 100% 落在懒 chunk 内。 - 计划 Task 7 Step 5 给的 commit subject 53 字符,超 ≤50 限 —— 交付改用 42 字符的
perf(app): lazy-load window variant panels。 - 计划 V3 判据「首屏 gzip 变化 ≤3 kB」被实测 −4.39 kB 突破 ⇒ 控制方改判为「只许变小 ∧ modules 不变」(原判据建立在「分块不会改变总量」这一错误假设上)。
- 计划自带的「子串碰撞」反例恒假红(
@xyflow/react的 id 里没有连续子串node_modules/react)·@types/katex覆盖闸必然红(dependencies实为 14 个,计划写 12;已加 1 行惰性登记,根因 F4 登记批 8)。 .gitignore的build/未被锚定 ⇒ 静默吞掉app/src/build/(Task 3 的两个文件靠git add -f才入库)。本批只做点状取反!app/src/build/**,未动锚定语义(登记批 8)。- Task 1 冻结的 clippy 基线 sha256 不可复现(基线文件 BOM+CRLF 1724 B vs 抽取器无 BOM+LF 1702 B)⇒ 判据一律改集合比对(本批实测集合 19/19 相同、sha256 不同)。
- 「文件不存在」被假报两次(Task 5 报
task-3-fix-report.md不存在但实际 247 行;Task 9 同类)⇒ 断言「不存在」与断言「0 命中」同等对待:说明仪器并自检。
本批新增/确认的读数陷阱(累计 13 类,逐条见批 2 计划 Global Constraints 的仪器纪律注):含中文的搜索模式经 PowerShell 字符串层被 GBK 误解码(给出 0 命中的假阴性)· 无 BOM 的 UTF-8 中文 .ps1 被 -File 按 GBK 解码(连脚本内 cmd 行一起毁)· 整树 ripgrep 遵守 .gitignore ⇒ 对被忽略目录整体失明(同一仪器实测 0 vs 19 命中)· PS 5.1 > 重定向写 UTF-16LE · Tauri 命令名不是唯一 chunk 标记 · chunk 依赖边是「模块图」的性质、不是「归属表」的性质(环的根因:只挪模块不挪它自己的依赖闭包)· git archive 在未跟踪子目录出 10240 B 空归档 + exit 0 · 解包树里 git grep 静默 0 命中 · Copy-Item 保留 mtime ⇒ cargo 回放陈旧诊断(还原后先 touch)· A/B Δ 恰为 0 先当仪器故障、自证仪器能测出已知差异再下结论。
未做(登记,逐条带归属):路线 A 叶级懒加载(被 B′ 在首屏上完全包含 · 测试面更险)→ 批 5 · 页级错误边界 / 懒 chunk 加载失败重试(PageSlot 的 <Suspense fallback={null}> 之上只有全局 AppErrorBoundary ⇒ 一次失败卸载整个 MainShell、已访问页状态一起丢,这是本批新增的失败模式)→ 批 3/4 · 两个窗口变体分支没有错误边界(chunk 加载失败 = 空白窗)→ 批 3/4 · 首访加载态 fallback={null} → L1 Loading 原语 → 批 3/4 · 变体首屏正式度量口径(本批只给实测值 + 证明 < 60 kB 不可达)→ 批 3 · structuredBlocks.ts 整模块存废 + katex 版本偏斜(含 @types/katex)→ 批 7 · @codemirror/lang-markdown 传递链(懒 chunk −84.04 kB)+ basicSetup 附带件(−45.10 kB)两条耦合,须一起裁决 → 批 4/5 · 59 个 KaTeX 字体 1,072.95 kB(仅 .woff2 可省 816.78 kB)→ 批 8 · 批 6 装 GSAP 必须 import() 且核对 vendor-gsap 不在首屏(槽位已预留并被单测钉住)→ 批 6 · check-bundle-budget.mjs 接线 .husky/pre-commit / CI(本批有意不接:它要跑真实构建并写 app/dist/)→ 批 8 · 守卫的嵌套输出路径盲区(assets/vendor/*.js 既不计首屏也不计懒,仍打印 ✅ 达标 + exit 0;已用真实构建复现)→ 批 8 · 守卫把「非首屏」一律说成「仅动态可达」的假文案(从未验证动态可达性)→ 批 8 · 没有任何门禁看构建日志里的 Circular chunk(环本批已断:1 → 0 条,但「依赖升级可能让死边复活」⇒ 建议纳入某处判据)→ 批 8 · 两个贴限文件:scripts/check-bundle-budget.mjs 299/300、app/src/build/manualChunks.test.ts 292/300 ⇒ 任何新增必须按语义拆分(守卫拆「口径 / CLI」,测试拆「分组规则 / 反例」)→ 批 8 · 下次改动者当次拆 · .gitignore 的 build/ 锚定语义未动(本批只点状取反)→ 批 8 · scripts/**/*.mjs 不在 line-limits 扫描域(SOURCE_EXT 不吃 .mjs、SCAN_DIRS 只有 app/src + app/src-tauri/src)⇒ 本批两个新脚本无门禁保护 → 批 8 · app/vite.config.ts 同时不在 line-limits 扫描域与 tsc --noEmit 的 program(--listFilesOnly 879 文件 0 命中,正样本 main.tsx = 1)→ 批 8 · F4 把 @types/* 挪 devDependencies(依赖卫生)→ 批 8。本批未复核「批 0 其余部分」的落地状态(本文档「批 0 其余部分(未落地)」节写于 2026-09-11)→ 批 8 复核 · AGENTS.md §5 的「subject ≤50」是一条无机器门禁的约定 —— commitlint.config.js 沿用 config-conventional 的 header-max-length = 100,未覆盖为 50,故本批有 2 条 51 字符提交(e46e0e82 / f0592654)照抄计划落地并顺利入库;建议加 'header-max-length': [2, 'always', 50] → 批 8。
瓶颈清单指针:本批的瓶颈清单(14 行,每行含实测 gzip / 为什么降不下去 / 具名归属批次 / 复现命令)在批 2 计划 2026-09-11-frontend-redesign-batch2-bundle.md 的 §收口回写节,另有 Task 12 收口终态节(终态六门禁表 + 回写落点表 + 追加 follow-ups 15–18)。规格 §10 明写「后一批的细节依赖批 0–2 的实测结果(尤其是包体治理量出的瓶颈清单)」⇒ 批 3 的计划者请先读该清单。
提交数口径(本文档既定规矩):本文档批次行一律采用「含左端点」口径(
A^..B,见批 0-A 行的声明)。本行同款:85d51d83^..至收口提交 = 22(git rev-list --count实测)。其中截至本行落盘时85d51d83^..d9d0dfc0= 21(1 计划 + 19 实施与修复 + 1 修复单元),加本节所在的收口提交 = 22。批 2 行是全文唯一例外(不含左端点,已就地注明),本行不与它混用。
交付
- 单一导航注册表
app/src/shell/navRegistry.ts(111 行):PAGE_COMPONENTS(9 页组件,保留各自精确 props 类型)+NAV_ENTRIES(8 项,顺序 = 今日NAV_ITEMS顺序)+SETTINGS_ENTRY(设置下沉齿轮)+ALL_ENTRIES/PRIMARY_KEYS/navComponent/navEntry/isPageKey/PageKey(由组件表键集派生)。App.tsx不再直接 import 任何页面模块。 - 单一列注册表
app/src/shell/columnRegistry.ts(77 行):规格 §6.2 的 13 行 +columnSpec(未注册即抛)+columnsOf(page)+COLUMN_KEYS;7 个字段(规格的 6 个 +page)。执行器仍是useColumnLayout(A5 裁决:注册表持规格、hook 执行,hook 零改动)。 - 断点单一真源
app/src/shell/breakpoints.ts(52 行):threeCol 1024/twoCol 1100/navFull 1180/navActionsFull 1400/outlineCol 1280;6 处散落阈值改判,页面 0 残留。 --nav-h进 token 生成器:app/scripts/gen-tokens.mjs(单一真源)→ui/tokens.css产物;10 处 / 9 文件的56全部改为消费变量(App.tsx高度 +AiConversationDocktop+ 8 个页面的calc(100vh - 56px))。- 窗口尺寸
app/src-tauri/tauri.conf.json:960×720→1280×800+ 最小1024×640;app/index.html加全局 reset(html, body, #root { margin:0; height:100% })+ 6px 滚动条。 - A′ 顶栏
app/src/shell/TopBar.{tsx,css}:品牌 + 8 个域 Tab(自绘线性图标 + 纯文字,emoji 出局)+ ⌘K +right插槽 + ⚙ 齿轮;溢出两级(≥1180文字 /1024–1179仅图标 +title)+ 右簇第二级(<1400仅图标 +title);AI toast 移出导航行进 fixed 覆盖层。 - ⌘K 命令面板
app/src/shell/CommandPalette.{tsx,css}+ 数据源kbCommands.ts(纯函数、零 React)+useKbPaletteSearch.ts(180ms 防抖 + seq + 降级标记)+utils/kbHits.ts;Ctrl+K 接在window,与既有Ctrl+Shift+A先判更具体组合。 - 页级错误边界 + 首访加载态
app/src/shell/ShellFallback.tsx(60 行):PageSlot(边界在 Suspense 之外、children 之内)·?overlay=1·?float=1(CaptureStatusProvider仍在边界外层)· dock —— 四处接线,「叶级」性质由测试证明(出错只卸载那一页、壳层 state 保活、兄弟槽位仍在)。 - 19 个新守卫测试文件(
app/src/shell/*与 3 个组件/页面测试),既有 1233 条一条未改。🔻 收口评审 M-5 就地加注(2026-09-12,上句原文保留)——「19」是误计,实测 = 18 个新测试文件:
git diff --name-only --diff-filter=A 85d51d83^..42e88740 -- app/src实测新增 18 个测试文件(app/src/shell/*14 +components|pages4)。两个口径:① 新文件数 = 18(本行 + §11-11 批 3 进度注 + 批 3 计划 §收口回写 §二 门禁表第 5 行的 +18 新文件 / +137 用例,三处一致);② 上句里的「3 个组件/页面测试」也偏小 —— 实测是 4 个(ChatSidebar.test.tsx·ClassroomRightPane.test.tsx·notes/NotesReadingColumn.outline.test.tsx·pages/GoalsPage.test.tsx)。⇒ 本行按 18 / 14+4 读(「19」无出处:它把KnowledgePage.test.tsx这个被修改的既有文件也算了进去)。
验收(三条 + 八门禁;原始读数见批 3 计划 §收口回写 · tmp/acceptance.md)
| 验收 | 判据 | 读数 |
|---|---|---|
| ① 9 页全走注册表 | navRegistry.test.ts 12 用例全绿(① 键集/孤儿页/import 路径 ② App.tsx 的 page === "key" + navComponent + 不直连页面 ③ 图标 ④ 取值口正/负样本 ⑤ 顺序与 label 冻结 + 保活)+反向证据(非同源第二仪器:注册表源码抽 9 键 ↔ App.tsx 的 page === 字面量集合双向相等)+阴性样本 "not-a-page" → MISS |
✅ 三条全过(探针 exit 0) |
| ② 1024 无溢出(限定词:常态;toast 已不在导航行) | 合成页探针(真 TopBar 组件 + CDP 精确视口):3 档 × 3 个 toast 态(ok/err/errlong) × 2 徽标 × before/after = 48 行,判据 natural > clientWidth ⇒ OVERFLOW;改前 21 行溢出 / 改后 0 行;加跑 1440 档覆盖 navActionsFull=1400 的第二级 ⇒ 64 行 0 溢出。真实产物探针(加载真 app/dist):1024 / 1180 / 1280 三档判据②③全过 |
✅ 1024 +317.89(最坏徽标 +245.89)· 1180 +137.06(最坏 +65.06)· 1280 +237.06(最坏 +165.06)· 1440 +237.2(最坏 +165.2)· 真实产物 1024 +410.47 / 1180 +229.64 / 1280 +329.64 |
| ③ 「7 处魔数归零」 | 不迁就数字:判据 = 「能否被单一真源吸收」(A1)。逐处 before/after + 剥注释口径 + 阳性对照取自不可变旧版本 a7bd1899 + 阴性对照 |
✅ 已吸收 8(M1–M7 七处全部归零 + 大纲列 180)· 有目标未吸收 1(KnowledgeDetailPanel 的 34)· 无目标 2(ColumnBar 的 26 · ColumnResizer 的 5)⇒ 不压回「7」 |
八门禁终态(2026-09-12,干净树,HEAD=d9d0dfc0,app/dist mtime 2026-09-12 14:06:11 且由本次真实构建产出)
line-limits --full >600 0 · 301–600 档 123 · 登记条目 123(exit 0,--write 复跑零 diff)· docs-check exit 0 · registry 312/312/0 · tsc --noEmit 0 错 · vitest 143 文件 / 1370 用例 / 0 失败 · cargo test --test app_lib_tests 2300 / 0 / 6(9.26s,逐字持平)· check-bundle-budget.mjs exit 0 · 首屏 97.16 kB · 余量 102.85 kB(766 modules;懒 21 个 574.71 kB 不计入;CSS 52.27 kB 原始 / 12.58 kB gzip 不计入判据,只报告)· cargo clippy --all-targets 唯一位置集合 20 = 基线,SET-IDENTICAL(汇总行口径:lib 15 / lib test 19(15 重复)/ app_lib_tests 19(19 重复))。
首屏账:92,789 → 97,155 B = 92.79 → 97.16 kB(+4,366 B = +4.37 kB,+4.7%);入口 chunk index-*.js 87,573 → 99,860 B(+12,287 B 原始);index.html 655 → 1,558 B(+903 B,reset + 两条 modulepreload);懒 chunk 22 → 21 个(CaptureFloatPanel 改名重组)。
首屏静态可达图(三件套,永不使用裸绝对数):① 工具口径(把 import type 也算边)47 → 67 文件 / 4 → 4 包;② 真实边口径(TS 编译器 API 剔纯类型边)36 → 56 文件;③ Δ 两口径一致 = +20,新增 20 个文件全部是批 3 的壳层/ui 模块(shell/* 10 个 + ui/icons/* 6 个 + ui/tokens{,.gen} + ui/zIndex + utils/kbHits),pages/** 新增 0 · npm 包新增 0 ⇒ 没有任何页面被静态拉回首屏。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
| D1 §2「9 个顶部 Tab」遗漏对话面板钮 + 采集徽标 + AI toast | 规格 §2 回写块 |
D2 §2「useColumnLayout 只被 4/9 页采用」→ 页数一致、处数是 7 不是 4 |
规格 §2 回写块 |
D3 §6.2 笔记列表列写 1024、今日 700(三值并存 860/700/1100) |
规格 §6.2 回写块 |
| D4 审计 J1-8「56px 硬编码三处」实测 10 处 / 9 文件 | 规格 §2 回写块(审计文档本身归批 8) |
D5 审计落点 NotesPage:395 / App:225 因批 0-C2 拆件已过期 |
规格 §2 回写块(只登记) |
D6 §6.2 大纲列「接线或删钩子」→ 走接线;onToggleOutline 走 setManualFolded 不含 expand()(J1-3 死局坐实) |
规格 §6.2 回写块 |
D7 §6.1「9 个 focus* 参数跳转」实测 10 个(多 focusChatId) |
规格 §6.1 回写块 |
| §6.1 两个估数 「约 1070px」的前提是右侧簇不带文字(实测满档 1281.8 → R2 后 1027.94);「约 720px」准确(改前 717.11,Δ2.89) | 规格 §6.1 回写块 |
§6.2 ColumnSpec 字段 规格写 6 个、实现 7 个(多 page) |
规格 §6.2 回写块 |
| §10 批 3 行 验收词与进度标记 | 规格 §10 表(本行 + ↳ 批 3 的收口 行) |
| §12「3 套 markdown 渲染器 · 可并入批 4」 → 批 4 裁决 B8 不并入,去向 批 5/7 | 规格 §12 该行就地加注 |
| §14 ADR-034 未写(实盘最高仍是 ADR-033,已列目录复核)⇒ 建议批 4 前补写或并入批 8 | 规格 §14 该行 + §10 ADR 归属行 |
| §11-2 / §5.2 的弹层 20 / 28 与 z-index 17:批 3 未涉及,只登记(本批未迁任何弹层) | 规格 §11-2 就地加注 |
过程中纠正的计划错误(本批最有价值的交付,逐条可复现;全文见批 3 计划就地加注)
- Task 3 的验收正则含被转义的
\|(第 1 处判据缺陷):3 种形态只匹配 1 种 —— 「10 处里只有App.tsx的height:56在射程内,其余 9 处(top:56+ 8 处calc)未迁移时恒给 0 ⇒ 判绿」(全未迁移时会红,1 命中)。结论在正确仪器下仍成立(10 处消费 / 9 文件、旧写法残留 0)。 - Task 6 的 V4 把
import type算成静态边(第 2 处):47与57两个口径并存;评审用 TS 编译器 API 剔掉纯类型边后,判据重定为「Δ + 机理」三件套(永不使用裸绝对数 —— 同一个「真实静态可达」曾被三方测出 38 / 39 / 49)。 - Task 7 Step 5 的预期值被实测推翻(第 3 处):计划写
a-tabs@1280 ≈ 909.99(余量 ≈370),实测 1281.8(−16.8)⇒ 在默认窗宽上的可见回归,而「1024 无溢出」这条验收反而判绿 —— 判据没覆盖的地方,绿灯不是证据。A7 裁决 R2 返工后三档全绿。 - Task 8 的
onToggleOutline字面指令有歧义(第 4 处):逐字「改为outlineCol.expand()」会把 ✕「收起大纲」也变成expand(),凭空制造新缺陷 ⇒ 实现为folded ? expand() : setManualFolded(true)(两个控件各自语义正确)。 - 计划自相矛盾(第 5 例,W28):
## Global Constraints逐字「本批不许改ChatPage.tsx」vs Task 9 的 Files/Step 2 逐字要求改它。裁定走 Task 9 侧(与既有 6 处调用点形态一致);代价:ChatPage.tsx变 599/600(余 1 行),下一个动它的任务必须先拆。 - 计划自相矛盾(第 6 例,W30):Task 11 的 Interfaces 要
onPick: (cmd: Command) => void,Step 4 逐字要onPick { kind:"page",key }/{kind:"dock"}⇒ T11 取可执行的 Step 4,Command仍按计划导出。 - Task 14 Step 2 的探针路径走不通(第 7 处判据缺陷,本节新增,收口时实测):计划逐字让探针打开
file:///…/app/dist/index.html—— vite 产物用绝对路径/assets/index-*.js+crossorigin(Tauri 从应用协议根提供,绝对路径是对的)⇒file://下解析成file:///assets/…(不存在),实测#root子节点 = 0。正解 = 用本地只读静态服务器提供app/dist(探针--mode http,绑 127.0.0.1、结束即关)。--mode file的失败读数保留在tmp/acceptance.md用于复现,不得用作结论。 - 验收计数与口径的三处过时数字(均已重定):① vitest 基线「≥1256」是 T6 之后的读数,真基线是 125 文件 / 1233 用例 ⇒ 判据改为「既有 1233 条逐文件一条不许少 ∧ 新增只增不减」(实测:125 个既有文件用例数一模一样、0 消失、0 减少);② V6 期望「12–15 个原子提交」,实数 22(构成见提交清单,不为落进区间而合并提交);③ 计划 Step 8 写「A1–A5 五处裁决」实为 A1–A7(A6 = 删
legacyLabel的授权;A7 = 顶栏 ≥1180 回归与 R2 返工)。 - 计划 V 表里的 PowerShell 单行命令在 PS 5.1 下
SyntaxError(第 4 处判据缺陷,W29):T9 的 V3 逐字命令跑不起来 ⇒ 改用等价 Node 脚本;判据一律改成可粘贴的脚本文件。 - Task 4 缺「行为中立性」核对程序(W7):只给了结论没给程序 ⇒ 本节按 T4 实际做法补写该程序(见计划 Task 4 就地加注)。
- 计划两处计数错(W9):表 2 的 M1 写「8 个页面」实测 7 页(8 处,
ReviewPage占 2);表 1 写useColumnLayout「5 页」实测 4 页。 - Task 1 节无可粘贴 argv / 无代码围栏(W24)· 宽度探针全部读数出自离线复刻页、且
A_TABS顺序与已提交注册表已分叉(W23/I-3:…复习,体系,目标,AI对话 vs …复习,AI对话,体系,目标)。⇒ T14 的探针按注册表真实顺序渲染(复用真TopBar组件,顺序由注册表 map 决定)。 - Task 7 Step 3 第②层「只测
title」口径不足(W11/A6):删legacyLabel后,注册表label成为规范态文字的唯一真源 ⇒ 补「可见文字textContent逐字 ===e.label」+ A2 的 emoji 负判据(DOM/注册表双口径),配 4 个变异体。 - 「7 处魔数」的「7」从未被定义(W1/A1):规格全仓仅 1 命中、从不展开 ⇒ 判据取「能否被单一真源吸收」,不迁就数字(终态 8 / 1 / 2)。
--nav-h = 56是计划者取值(W4):规格只给名字不给值 ⇒ 只把56搬进 token 生成器,值暂保持 56(不在本批发明数字)。
未做(登记,逐条带归属批次)
真机 1024×640 / WebView2 冒烟 → 批 8(用户已裁决本批跳过;不得出现「已在真机确认」类表述)· 命令面板迁移到 Modal 原语 → 批 4 · ShellFallback → Loading / StatusLine → 批 4 · focus* 状态机收敛(本批只收敛入口,10 个字段一个未删)→ 批 5 · 列折叠的连续运动(Flip)→ 批 6 · 相变两态(§6.3)→ 批 6 · pinnable 无消费方 → 批 6 · 列状态对象对齐(A5 选项 (b):删 useColumnLayout、注册表自实现)作为日后可能的合并方向,不得声称能力对等 → 无期 · 快捷键集中注册表(⌘K 与 Ctrl+Shift+A 都注册在 window)→ 批 4/8 · index.html 的细滚动条在弹层/虚拟列表中的核对 → 批 4 · ADR-034(壳层)未写 → 批 4 开工前或批 8(需控制方裁决)· §6.2「本次改动」列里的 🗂 会话·详情头改粘性 与 📝 笔记·工具栏三层合并为单行 → 未做(不属壳层/列契约;去向需裁决)· 34px 窄条吸收 → 批 4(与统一列头/ColumnBar 收敛一起做)· 26 / 5 两处无规格目标 → 登记不碰 · 3 套 markdown 渲染器归一 → 批 5/7(批 4 裁决 B8 不并入)· scripts/**/*.mjs 与 app/vite.config.ts 不在 line-limits 扫描域 → 批 8 · check-bundle-budget.mjs 未接 pre-commit/CI → 批 8 · bundle-eager-graph.mjs 把 import type 计成静态边 → 批 4 或独立小单元(改它会改历史读数 ⇒ 必须新旧口径并列)· W27 pre-commit 跑全树、--write 按工作树刷新 ⇒ 并行提交必生窗口(批 3 实证 3 次)→ 批 8 加 --staged 模式。
诚实代价(不许省略)
- 首屏 gzip +4.37 kB(92.79 → 97.16 kB,+4.7%),入口 chunk 原始 +12.29 kB —— 涨的是必要成本(导航注册表 + 列注册表 + 断点 + 窗口常量 + 顶栏 + 命令面板 + 三个守卫 + 四个新测试面)。仍远低于 200 kB(余量 102.85 kB)。
index.html变大(655 → 1,558 B,+138%):全局 reset + 两条modulepreload。- 这是本系列第一次「界面真的变了」:顶栏 emoji 被自绘线性图标替换、AI toast 换了位置(从导航行 → 右上 fixed 覆盖层)、右簇在 <1400px 只剩图标、设置从 Tab 下沉为齿轮、「课堂助手」改名为「课堂」(用户可见改名,非纯样式 —— 建议产品口径确认,见 follow-ups)。规格 §10 末句明写「骨架在批 3」,与批 0–2 的「界面几乎不变」不同。
- 三个贴边文件:
ChatPage.tsx599/600(余 1 行) ·NotesPage.tsx300/300(余 0) ·App.tsx574/600(余 26)(批 2 收口时 519)⇒ 下一个动它们的任务必须先拆。🔻 收口评审 M-8 就地加注(2026-09-12,上句原文保留)—— 按「任务预算贴边」口径还须加第四个:
app/src/shell/CommandPalette.tsx219/220(余 1 行)(=scripts/line-limits.mjs的countLines()口径;硬限 ≤300 不贴边、无需豁免登记,但 T11 预算 ≤220 已贴边:T11 交付 179 → T12 追加「取数 / 降级 / skipped」三条渲染 +40)。批 4 的Modal迁移必动它 ⇒ 提前登记(同列:先拆CommandList子组件,或由批 4 计划把预算提升到 ≤260)。四者性质分两档:ChatPage/NotesPage/CommandPalette是预算贴边(动它们前必须先拆/提预算),App.tsx是余量登记(余 26 行)。 - 4 个文件超计划预算(均 ≤300 硬限、无需豁免登记、
--write零变化;控制方裁定接受并回写计划预算,理由:计划预算只是估算,绑定约束是 ≤300 且不登记;拆文件解决不了,压回预算只能删减既有判据覆盖面 —— 那正是 A1 明禁的「为凑数字牺牲实质」):TopBar.css142(≤120)·columnConsumption.test.ts126(≤120)·ShellFallback.test.tsx163(≤120)·ClassroomRightPane.test.tsx138(≤120)。 - 首屏静态可达 +20 文件(
shell/*+ui/icons/*+ui/tokens*+ui/zIndex+utils/kbHits)—— 这是必要的(新壳层就是要在首屏),但它是批 2 挣来的余量第一次被实质消耗;pages/**与 npm 包均 0 新增(机理核查)。 - 一条既有 flake 未消除:
KnowledgeGraphView.test.tsx的负载敏感用例(批 3 开工前就存在,已在基线树复现)。 - 真机未验证:
tauri.conf.json的四个数字在真实 Tauri 窗口里的表现一次未跑;顶栏像素证据来自 headless Edge,不是 WebView2。 - 1 条提交超
≤50约定:ecc36a8d= 53 字符(commitlint沿用 config-conventional 的 100,未拦住)⇒ 与批 2 同类,建议加header-max-length: [2,'always',50](归批 8)。🔻 收口评审 M-7 加注(2026-09-12):同一条
ecc36a8d还有第二个性质须登记 —— 它是卫生修复(视口复原),无可红判据(见上方提交清单第 12 行注)。⇒ 本行不得被读成「它是一条有判据的修复(只是 subject 超长)」。
app/src-tauri/tauri.conf.json 的 §10 额外审查记录(W25 —— 之前只留在 gitignored 的报告里,此处 durable)
AGENTS.md §10 把
tauri.conf.json列为「变更需额外审查的文件」。批 3 确实改了它(Task 4),审查结论如下(出处:.superpowers/sdd/2026-09-11-frontend-redesign-batch3-shell/task-4-report.md§3,评审 M-f 已独立核对):
- 改动面 =
app.windows[0]的五个键:width: 960 → 1280·height: 720 → 800· 新增minWidth: 1024· 新增minHeight: 640· 新增resizable: true。title未动(原值已是「熵减 · 本地知识提取」)。security(CSP +assetProtocol)与bundle(resources / icon / targets)逐字节未动 —— diff 之外没有第二个 hunk。- 无夹带:未动 Rust(
commands_window.rs的采集浮窗inner_size(360,240)+resizable(false)保持原样);未新增/删除任何权限、capability 或 CSP 指令。- 可验证性:JSON 的四个数字由
app/src/shell/windowSize.test.ts(4 用例)与 TS 常量逐字对齐;EOL 保持纯 CRLF(crlf=43 / bare_lf=0),未引入 EOL 噪声。- 未验证:真实 Tauri 窗口是否真按 1280×800 打开、最小尺寸是否真的夹住拖拽 —— 一次未跑(需要桌面会话),归批 8 真机验收。
提交清单(22 个,85d51d83^.. 至本收口提交;逐条 subject ≤50 除 ecc36a8d 53 字符)
| # | sha | subject | 归属 |
|---|---|---|---|
| 1 | 85d51d83 |
docs(plan): 批 3 壳层落地实施计划(14 任务) |
计划 |
| 2 | 71ca8600 |
feat(ui): add nav height design token |
T2 |
| 3 | 02032cfe |
refactor(shell): consume nav height token |
T3 |
| 4 | d01a623f |
feat(shell): set window size and reset html |
T4 |
| 5 | c7d20954 |
feat(shell): add single source of breakpoints |
T5 |
| 6 | 4c89c687 |
fix(shell): make scrollbar 6px take effect |
T4 修正 |
| 7 | 742b892d |
feat(shell): add navigation registry for 9 pages |
T6 |
| 8 | 92ea5d6b |
feat(shell): add column spec registry |
T8 |
| 9 | fd83abb4 |
feat(shell): rebuild top bar, float ai toast |
T7 |
| 10 | 4f8f3d3c |
feat(shell): wire three pages to column specs |
T9 |
| 11 | 882a61ef |
test(shell): pin column tier mapping |
T8 补强 |
| 12 | ecc36a8d |
test(notes): restore viewport in knowledge page tests |
微单元(M-c)· 卫生修复(无仓内可红判据) |
| 13 | 6b81f414 |
fix(classroom): unify right pane width wrapper |
T10 |
| 14 | 477bf604 |
feat(shell): add command palette and Ctrl+K |
T11 |
| 15 | a8854292 |
fix(chat): wire sidebar resize handle |
T9 评审 I-1 |
| 16 | 767a8b32 |
test(shell): pin key identity and 0/0 guard |
T8 评审 I-1/M-1 |
| 17 | 2989c8c3 |
test(shell): 补常驻状态件装配判据 |
T7 评审 I-1/I-2 |
| 18 | b567f0e6 |
feat(shell): wire kb search into palette |
T12 |
| 19 | 9bcb4720 |
feat(shell): add slot error boundary and loading |
T13 |
| 20 | 2b426236 |
fix(shell): 修 T12 评审 I-1/I-2 与 M-1/M-2/M-4/M-5 |
T12 修复单元 |
| 21 | d9d0dfc0 |
fix(shell): 加固 T10/T13 五条评审 Minor 判据 |
T10/T13 修复单元 |
| 22 | (本次收口提交) | docs(spec): close out shell batch three |
T14 |
注:第 22 行的 sha 无法写进它自己的提交内容里(自引用);批 2 的先例同样把「收口回写提交」单列在区间之外。本行的「22」=
85d51d83^..<收口提交>含左端点。🔻 收口评审 M-7 加注(2026-09-12)—— 第 12 行
ecc36a8d的性质是「卫生修复」,不得列进「有判据的修复」:它是环境卫生修复(KnowledgePage.test.tsx的afterEach补视口复原),没有任何仓内可红判据 —— 收口评审的变异体ecc-no-restore(去掉复原)实测 exit 0 · 6/6 全绿(导出副本,未用--reporter=basic、未用eval),即该风险在本仓(vitest 默认每文件独立环境 + 该文件beforeEach每例重设视口)不可证伪。修复有效性由探针实测:用「后续 describe 的beforeAll」读环境值 ⇒ 修复态 1024 / 泄漏态 1280(修复确实生效)。⇒ 判据归属:防泄漏的机器判据(例如全仓afterEach环境还原守卫)归批 8 的测试治理单元,本批不声称它有判据。
🔻 提交树自洽性更正(收口评审 I-1,2026-09-12)—— durable 载体上「实证 3 次」记错,实测 5 个提交:本节先前的台账/计划口径是「批 3 提交树不自洽实证 3 次(
92ea5d6b/4f8f3d3c/fd83abb4之前同类)」。收口评审把批 3 的全部 22 棵提交树逐一导出(git -c core.autocrlf=false archive -o t.tar <sha>→tar -xf→ 在树内跑它自带的node scripts/line-limits.mjs --full)实测:5 个 exit 1 · 17 个 exit 0。
92ea5d6b(T8):(e) 行数不一致:app/src/App.tsx 声明 **509** / 实测 **503**;4f8f3d3c(T9)·882a61ef(T8 补强)·ecc36a8d(微单元 M-c)·6b81f414(T10):四处逐字同形 —— 声明 548 / 实测 509,全落在fd83abb4(T7) 与477bf604(T11) 之间的同一并行窗口;fd83abb4其实自洽(先前把它算进「不自洽」是错的);其余 17 个(含收口提交42e88740)全部 exit 0。- 口径更正:批 3 实证 = 5 个提交(不是 3 次),点名 5 个 sha;
docs/superpowers/plans/2026-09-11-frontend-redesign-batch3-shell.md的 §一 W27 注与 follow-up #1 已就地加注(原文保留)。ecc36a8d的门禁读数取自工作树(见上条 M-7 注):该单元的「提交后门禁 exit 0」只在工作树口径成立,它自己的提交树带一处并行窗口不自洽 —— 这是本批「工作树绿 ≠ 提交树绿」的第 5 个实例。- 机理结论不变(
--write按工作树刷新登记表):⇒ follow-up #1(批 8 给门禁加--staged模式)的依据比原先记的更强(5 个,不是 3 个)。HEAD 本身不受影响(42e88740自洽)。
提交数口径(本文档既定规矩):本文档批次行一律采用「含左端点」口径(
A^..B,A= 该批第一个提交,见批 0-A 行的声明)。本行同款:4905d4d8^..至收口提交 = 49(git rev-list --count实测 = 48 个实施/评审/修复提交 + 本节所在的收口提交 1 个)。同口径校验:批 3 的85d51d83^..42e88740实测 22,与批 3 行的「22 个提交」逐字相符 ⇒ 口径无误。另报两个字面读数以免歧义:git rev-list --count 42e88740..HEAD= 48(不含左端点)·git rev-list --count 42e88740^..HEAD= 49(它把批 3 的收口提交42e88740也算进来了)⇒ 批 4 自己的提交数按4905d4d8^..那一行读。批 2 行是全文唯一例外(不含左端点,已就地注明),本行不与它混用。
交付
- 原语层补齐(批 4 的三处能力扩展,全部走 B6 的「≥3 共用 ⇒ 改原语」或「结构上无法表达」例外通道):①
Modal的 body 滚动锁(20 个弹层共用 ⇒ 改原语;引用计数 + 原值快照、门控presence.mounted而不是open);②Text的两个属性级受控槽testId/title(B16:各 ≥3 处,不加role/onClick/aria-*/任意 DOM 透传);③Surface的第 5 档圆角radius="pill"(B17:切片内999实测 3 处 ⇒ 加档,落2360c3d9)。 - 五条棘轮 + 切片清单(B11 的「切片 + 棘轮」中间态):
emptyStateRatchet(切片 28 文件 + 例外 8 + 余量 5)·loadingRatchet(冻结 8,表 18 键逐格钉死)·statusLineRatchet(迁移面 49 文件 + 三红 114 处 / 67 文件)·textRatchet(弱化灰 249 → 63;字号越界 558 / 120 只冻结)·surfaceRatchet(边框 240 → 226 · 越界圆角 270 → 261 · 阴影 24(值 11 → 6) ·FROZEN_SURFACE_TAG_TOTAL 0 → 14)。每条都带防真空阳性对照、逐文件牙齿(或显著登记的下界)、防僵尸豁免。
↳ 收口后更正(2026-09-12 · 收口评审 I-6 + 修复单元
ed07d491;上行原文一字未改):本行textRatchet的(弱化灰 249 → 63)终态是 64 ——FROZEN_MUTED_GRAY_TOTAL = **64**、逐文件格components/NoteRowContextMenu.tsx1 → 2(条目数/文件数仍 44/44)。249 = 186 + 63是旧剥注释仪器口径下的恒等式;物理真值 = 250 = 迁移 186 + 例外 64。逐类真源(我自测tmp/docfix/d2-kind.mjs):条目数14 / 8 / 9 / 7 / 4 / 1 / 1(Σ44)· 处数19 / 11 / 11 / 14 / 7 / 1 / 1(Σ64);旧分解「interactive*35 ·ternary-no-equivalent10 ·nontext6 ·b1-non-migrated9 ·tag1 ·colorMap2 · C 类 2」自列之和 = 65 且colorMap与「C 类」重复计数,不得再引用。
- 20 个手写弹层全部迁入
Modal(A14 + B4 + E2 = 20,清单钉死在dialogMigration.e.test.ts的DIALOG_20);z-index 六档整段迁移(裸值 58 处 / 43 文件 / 17 值 → 3 处 / 3 文件 / 3 值,那 3 条是 B2 的例外且逐条带理由)。 - 四套 toast → 3 套收敛 + 1 套机器可判例外(
App.tsxAI toast 走新的placement="belowNav"槽 ·SessionsPage改useTransientToast· hook 换渲染并归toast(500)档 · 面板级内联 banner 带 4 条理由不迁)。 - 8 处
window.confirm→ConfirmDialog(6 个文件;文案按分隔符逐字拆解,疑问句进title,不新造一句;取消路径逐处渲染级取证,含NotePreviewView的setStatus副作用)。 - 按钮收敛:
*Btn*常量族 →<Button>,原生<button>493 → 394 处 / 121 → 114 文件(Δ −99,逐文件 Δ 之和 == 形状表总数 99);const *Btn*79 → 56 行 / 55 → 44 文件;棘轮 510 → 394。
↳ 收口后更正(2026-09-12 · 收口评审 M-11 + 修复单元
531eb93f;上行原文一字未改):上行「394 处 / 114 文件」(与棘轮 510 → 394)是f6dd012f时点的读数,不是 HEAD。收口修复单元把nativeButtonBaseline收紧到实测 ⇒ 终态 = 394 → 393 处 / 121 → 115 文件、FROZEN_NATIVE_BUTTON_TOTAL = **393**(文件数 +1 来自 T13-b 拆件把components/chat/ChatLaunchMenu.tsx计入,SPLIT_MOVES已登记守恒、守卫未失效)。独立复算(node …/tmp/docfix/measure.mjs <tree>/app/src,剥注释后整段/<button[\s>]/g):f6dd012f导出树 394 处 / 114 文件 · HEAD 393 处 / 115 文件。
- 五类切片迁移:空态(切片 28 文件全走
EmptyState;ChatPage先拆件 599 → 578 + 新件ChatLaunchMenu.tsx77)· 加载(10 文件,6 处骨架)· 错误行(49 文件走StatusLine)· 弱化文本(186 处走Text tone="ink-3";testId/title两槽实用 12 处)· 卡片边框/圆角/阴影(<Surface>14 处 ·6→89 处 · 阴影 token 20 处)。 - 23 个新测试文件 / 227 用例(逐条见批 4 计划 §收口回写 §二);新增 6 条独立守卫族(原生按钮棘轮 · z-index 棘轮 · 四条切片棘轮 · 两条 shell 守卫 · 两个弹层形态判据族)。
🔻 收口评审后的更正与溯源(2026-09-12 · 收口评审 + 收口修复单元;以上「交付」原文一字未改)
更正块 A · 修复单元带来的 3 处数字变化(那 4 条提交不计入下面的 49):
# 项 旧 新 机理 提交 1 Text弱化灰例外总量63 64 sliceScan.stripComments不再把 JSX 闭合标签</x>的/当正则起点 ⇒ 受害行components/NoteRowContextMenu.tsx:175由「被抹掉」变「被数到」ed07d4912 同上 · 逐文件格 components/NoteRowContextMenu.tsx1 2 同一文件内 +1;条目数与文件数仍是 44 ed07d4913 原生 <button>总量 /components/WindowSelectCard.tsx格394 / 4 393 / 3 T12 后 271a281c把 1 处换原语但基线未同步(收口评审 M-3 的 slack)⇒ 收紧到实测;FROZEN_NATIVE_BUTTON_TOTAL = **393**531eb93f独立复算(本单元自跑,非照抄):弱化灰三口径并列(HEAD 工作树,域 =
app/src/**减*.test.ts(x)减ui/primitives/**)—— OLD 仪器(091d1c3d的sliceScan)63 行 / 44 文件 · NEW 仪器(HEAD)64 行 / 44 文件 · NAIVE(朴素剥注释)64 行 / 44 文件,三口径唯一差异文件 =components/NoteRowContextMenu.tsx(1 / 2 / 2);原生<button>HEAD 393 处 / 115 文件 ·f6dd012f394 处 / 114 文件(命令:node .superpowers/sdd/2026-09-12-frontend-redesign-batch4-primitives/tmp/docfix/measure.mjs <tree>/app/src)。另登记两条:①
dialogMigration.e.test.ts不受该修正影响 —— 它不 importsliceScan(只 importnode:fs/node:path/vitest,自带stripComments)⇒ 未改一行;② 贴边表变化 ——ui/primitives/loadingRatchet.test.ts拆出ui/primitives/loadingScan.ts(101 行)后自身降到 181 行(不再是贴边文件);ui/primitives/textBaseline.ts仍 299/300(贴边);ui/primitives/dialogMigration.e.test.ts仍 300/300(余量 0)。
更正块 B · 收口评审 I-5 / I-6 / I-7 与 13 条 Minor 的落点(原文保留 + 只追加):
- I-5(弹层测试覆盖写反):下文「两条未验证的诚实边界」里的「20 个弹层里只有 5 个有同名测试 / 无覆盖的 15 个」实测不成立 ⇒ 真值 = 10 个有同名测试文件且该文件真的
render(<X)/ 10 个无(该处已就地加注,含逐个列名与复现命令;批 4 计划 §六 第 3 条同款更正)。- I-6(弱化灰「7 类」分解):见更正块 A 的独立复算;真源逐类 = 条目
14/8/9/7/4/1/1(Σ44)· 处数19/11/11/14/7/1/1(Σ64)。- I-7(规格 §11-2 例外表 3 个成员错):
BrowserChrome/GroupSidebarRow/NoteHeaderActions不在NON_MIGRATED_14,缺NoteEditView/NoteLinkToSystem/RichEditorView⇒ 规格 §11-2 与ADR-033:162均已追加「🔻 更正表」(逐行成员资格 + 复现命令)。- M-1 计划 ADDED 分组「
ui/primitives/16 个(158 用例)」与其自列清单之和 175 不符(175 + 30 + 22 = 227 = 同句总数)⇒ 更正为 175(本单元复算:70 + 9 + 6 + 6 + 7 + 6 + 8 + 3 + 8 + 7 + 4 + 16 + 25 = 175,见批 4 计划 §二 门禁 5)。- M-2
dialogMigration.e.test.ts:218的onkeydown=是死分支(TSX 里 React 只写onKeyDown;git grep 'onkeydown=' -- app/src的 4 处命中全在该族测试文件自己的注释/断言串里,生产源码 0;onKeyDown=实测 19 处)⇒ 只登记不修(该文件 300/300 余量 0)。- M-3 已由
531eb93f关闭 ⇒ 编码数字同更正块 A 第 3 行。- M-4
pages/ChatPage.tsx行数:579 权威(cbc15837拆件 → 578 · T16-B 的be925809→ 579;控制方 20:4x 已就地更正台账、豁免表:24亦为 579)⇒ 本行下方贴边表的578已就地加注。- M-5
app/src/ui/zIndex.guard.test.ts:221的失败文案「对已知存在的 5 处应命中 5」陈旧 ⇒ 已改为「3 处应命中 3」(只改这句文案、零断言改动;该文件 262 行 < 300,line-limits --full仍 exit 0 且零新增登记)。- M-6 计划「296 是手抄噪声」这个机理不成立:296 是朴素剥注释口径的真值(
42e88740导出树:OLDsliceScan295 / NEW 296 / NAIVE 296,差额 =components/NoteRowContextMenu.tsx:175)⇒ 那是口径差、不是手抄;解释读数差异必须点明两种口径。- M-7 五条新仪器陷阱已入册(见下文「陷阱 4 · 批 4 收口新增的仪器陷阱」)。
- M-8 「精确写法」终态 = 157(
42e88740180 → T17-A0bc09a41171 → HEAD 157)⇒ 计划 §八 4 的「终态 171 精确」实为 T17-A 冻结值(本单元复算:border:\s*"1px solid #e5e7eb"口径 = 180 / 171 / 157;含复合口径 = 259 / 240 / 226)。- M-9
fontSize全量终态 = 1088(42e887401274 →8f5bd9f11172 → T16-A/T17-A3ed9cfe9/0bc09a411123 → HEAD 1088)⇒ 计划 §八 4 的「终态 1123」实为 T16-A 时点(本单元复算逐字一致)。- M-10 「弱化灰 249 行 / 100 文件」是 T16-A(
3ed9cfe9)时点的值,不是终态;同一时点的修正仪器读数是 250 / 100,终态 = 64 / 44 ⇒ 计划 §八 4 需带时点。- M-11 原生按钮「394 处 / 114 文件」是
f6dd012f时点的值,不是终态(HEAD = 393 / 115)⇒ 本节「按钮收敛」那行已就地加注。- M-12
b1-non-migrated的「9 处」是回退动作数(tmp/t16b/revert-b1.mjs的SITES= 9 条 / 7 文件);该类冻结处数是 14(收口修复前 13)⇒ 两个数必须分开写。- M-13 规格
:614的「CommandPalette两处zIndex("modal")」在 HEAD 为 0(bde807dc已把层级交给Modal;git grep -n 'zIndex(' -- app/src/shell/CommandPalette.tsx实测空、bde807dc^上为 2)⇒ 规格该处已补时点更正。
🔻 溯源与提交数(收口后):批 4 的 closed range =
4905d4d8^..091d1c3d= 49 提交(含左端点口径,不变;git rev-list --count 4905d4d8^..091d1c3d实测 49,与本节开头逐字相符)。收口评审后的修复提交 = 4 条(不计入那 49,在此作为「收口后修复」登记):
sha subject 关闭的评审条目 ed07d491test(ui): fix slice scanner closing tag bugI-1( sliceScan的</x>误判 + 弱化灰重冻)8a2dd5e1test(ui): harden loading ratchet teethI-2( aria-label穿透)+ I-3(迁移面只许增锚)531eb93ftest(ui): tighten native button baselineM-3(原生按钮棘轮 slack 收紧) cd85e4c3test(ui): stabilise graph focus assertionsI-4(flake 最小稳定性修改) 另:
7d541254(docs(plan): 批 5 视图层实施计划)是并发单元的产物,不属批 4(既不计入 49,也不计入上面 4 条)。
🔻 I-4 的 flake 处置(控制方已裁):
components/KnowledgeGraphView.test.tsx的「局部聚焦」是既有负载敏感 flake(批 3 已在a7bd1899上复现过;批 4 未改该测试文件,git diff --name-only 42e88740..091d1c3d -- …/KnowledgeGraphView.test.tsx= 0)。修复单元做了最小稳定性修改(18 处waitFor超时 5000 → 15000,与vitest.config.ts的testTimeout: 15000对齐;未放宽任何断言、未加睡眠、未改配置、未加retry),但本机两种负载各 8 次 + 无负载 6 次均未复现 ⇒ 状态记为「已加固、未复现」(不声称已修好)。纪律:① 变异体实验不得与全量测试并发;② 今后若在顺序执行下再红 ⇒ 按新 flake 重新定位。
验收(两条 + 八门禁终态;原始读数与命令见批 4 计划 §收口回写 §一/§二)
| 验收(规格 §10 批 4 行逐字) | 判据 | 读数 |
|---|---|---|
① z-index ≤6 |
count-bare-zindex.mjs(exit 0)+ zIndex.guard.test.ts(7 用例 exit 0) |
裸值 58 处 / 43 文件 / 17 值 → 3 处 / 3 文件 / 3 值(10·999·1000,全部是 B2 例外、逐条 why >20 字);冻结名单 58 → 3;六档逐字 = raised 10 · panel 100 · popover 200 · modal 300 · modalNested 400 · toast 500 ✅ |
② role="dialog" 20/20 |
dialogMigration.{a1,a2,b,e}.test.ts + zIndex.guard.test.ts(5 文件 / 77 用例,exit 0) |
20/20 只经原语(barrel ∧ 无深导入 ∧ 无自建遮罩 ∧ 无 keydown ∧ 无裸 z-index);role="dialog" 的源码命中只出现在 ui/primitives/Modal.tsx(恰 1);三口径并列 = 20(验收)/ 28(ADR-033 同行)/ 34(跨行容忍),等式 34 − 20 = 14 = 11 锚定菜单 + 3 覆盖层 ✅ |
| R2 的中间态(必读) | 五条棘轮 | 验收第 3 条「五类重复 → 各自 1 个原语」在批 4 结束时并不成立:批 4 = 切片内清零 + 切片外余量冻结(去向批 5/7)。规格 §11-3 已就地加注(含「若选 (A) 全量的余量清单在此」与判据限度)。 |
八门禁终态(HEAD = 199da54b · 静止干净树 · 真实构建产出 app/dist mtime 2026-09-12 19:54:33 · 采集 19:52–19:56)
line-limits --full >600 0 · 301–600 档 122 · 登记条目 122(exit 0;--write 复跑零 diff ⇒ 豁免表不在本次提交路径)· docs-check exit 0(扫描 276 / 检查 176,五项全 ✅)· registry 312/312/0 · tsc --noEmit 0 错 · vitest 166 文件 / 1608 用例 / 0 失败(逐文件对拍批 4 开工基线 143/1370 ⇒ LOST=0 · SHRUNK=0;GROWN 6 · ADDED 23)· check-bundle-budget.mjs(真实构建,取 tmp/build.lock)exit 0 · 首屏 100.30 kB gzip(原始 317,778 B;余量 99.70 kB;CSS 62.63 kB 原始 / 14.42 kB gzip 不计入判据,只报告;入口 index-4qKuUwYr.js 108,099 B)· bundle-eager-graph 89 文件(源 76 + CSS 13)/ npm 包 4,TS-API 真实边口径 65 / 4,Δ = 0 · Rust 未复跑(本批零 Rust 改动:git log 42e88740..HEAD -- app/src-tauri 为空)—— 判据仍是批 3 的 2300 / 0 / 6,不得读成「已跑」。
首屏账(Δ + 机理;未做逐提交二分定位):计划表 1 基线 97.16 kB(= 97,155 B gzip / 309,524 B 原始) → 终态 100.30 kB(100,297 B / 317,778 B) ⇒ Δ = +3,142 B gzip = +3.14 kB。机理逐项(有独立 A/B 证据):T9 的 barrel + 原语层进首屏 = +2,348 B(ShellFallback 半程 +2,159 · palette 半程 +189;真实边 52 → 65 = ui/primitives/** 全层;pages/** +0;npm 包 4 → 4)· T10 = +373 B · T16-B 的 Text 迁移 = −112 B · T17-B 的 Surface 首次进首屏 = +101 B(产物里 ed-surface--bordered 迁前 0 命中 ⇒ 组件曾被 tree-shake)· T16-A 两槽 = +17 B · T17-A 结构性 0 · 剩余 ≈ +357 B 属 T11–T15 的调用点接入(未逐提交二分)。index.html 18 B 纯 CRLF、CSS 排序后逐段相同 ⇒ 差异来自 rollup 的 CSS 拼接顺序,非确定性)。B5 的诚实代价实测 = +2.35 kB,低于 B5 给出的上界 +3.41 kB。
首屏静态可达图(三件套,永不使用裸绝对数):工具口径 67 → 89 文件(= 源 63 → 76 + CSS 4 → 13)· 真实边口径(TS 编译器 API 剔 import type)52 → 65 · npm 包 4 → 4 ⇒ +13 全部是 ui/primitives/** 全层(barrel + 12 个原语模块),没有任何页面被静态拉回首屏。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
§4.2「四档圆角」→ 批 4 新增第 5 档 pill(实测 3 处;token 真源仍 4 档、走 var() 兜底;SURFACE_CLASSES 是自计数式守卫) |
规格 §4.2 加注(原文逐字保留) |
§4.3 条件③(审校模式 ≥4.5:1)在仓内无实现 ⇒ 批 4 的 Text 一律 ink-3、ink-4 0 使用 |
规格 §4.3 加注 |
§5.1 收敛账本 10 行 → 逐行「批 4 实测口径」(Button 107/63 不可考 ⇒ 三口径并列 510/121 · 80/55 · 103/37;Surface 180 ⇒ 真面 172、实迁 14;Text 251 ⇒ 249 = 186 + 63;Loading 85 ⇒ 棘轮口径 18/18 → 8;StatusLine 196 ⇒ 迁移面 49 + 三红 114/67;Toast 4 → 3 + 1 例外;ConfirmDialog 21 ⇒ 实测 confirm( 24 = 8 window.confirm + 16 非 window) |
规格 §5.1 加注(表下整块) |
§10 批 4 行 → 加 ↳ 批 4 的收口 行(✅ + 两条验收读数 + R2 的中间态 + 八门禁 + 观测口径) |
规格 §10 表 |
| §11-2 → 20 的构成(A14+B4+E2)+ 例外表(11 菜单 / 3 覆盖层,逐条理由)+ 28/34 并列 + 有意值收敛 | 规格 §11-2 加注 |
| §11-3「五类重复 → 各自 1 个原语」→ 加注中间态(B11 的附带硬要求;含终态表与「(A) 全量的余量清单在此」) | 规格 §11-3 加注 |
| §11-11 八门禁 → 加批 4 进度注(含「cargo 未复跑」的显式声明与 flake 登记) | 规格 §11-11 加注 |
§14 ADR-034 行 → ✅ 批 4 已补写(4905d4d8 + 两轮加注 + 已进 docs/adr/README.md);ADR-035 仍顺延批 6;S-4 两条本批未做 ⇒ 归批 5 |
规格 §14 加注 + ADR-034 §登记 加注⑦ |
| §12「3 套 markdown 渲染器」(B8) | 已在批 3 收口提交 42e88740 就地加注(「不并入批 4 ⇒ 批 5 或批 7」)⇒ 本批不重复加注(避免第二处真源) |
| ADR-033 §7「28 个手写弹层」的适用对象 → 明确为「对话框类」(B1 的落点)+ 三口径并列 + ESC 残留 5 处的「必须一并处理」改读为「必须一并登记」 | ADR-033 §7 加注 |
ADR-033 §4 的行内 style 禁令 → 自 69489f9f 起有真实输入(14 个 <Surface> 开标签、覆盖命中 0)+ style={S} 间接写法是假阴 + 两条 Surface 缺口 |
ADR-033 §4 加注 |
过程中纠正的计划错误(全表 ①–⑲;⑧–⑰ 是台账 §四 点名的那一段,⑱⑲ 为本次补登)
① Task 5 的「6 个测试文件需改」实测 0 处需改(全仓对那 9 个锚点零引用)· ② Task 5 的 V5 把 zIndex.guard 记成 4 用例(实为 7)· ③ Task 6 的 M5 是空变异(锚已无引用)· ④ Task 0 Step 2 的两处口径(六档值判据的真身是 ui/zIndex.test.ts:16-25;删规格行红在模块加载期)· ⑤ 计划 :13 的 gitignored 链接(导出树 docs-check 必红)—— ✅ 已修 0228a013 · ⑥ T1:Step 5 的 M4 期望写反 · ⑦ T1:计划者探针在 Windows 下域过滤失效(includes("/ui/primitives/") 对反斜杠恒假)· ⑧ SessionListPanel.tsx 误记为第 4 套 toast(只是消费者 ⇒ 零 diff)· ⑨ Task 5 的「6 个测试文件需改」(同 ①,T5 侧登记)· ⑩ Task 6 的 M5 空变异(同 ③)· ⑪ Task 9 Step 2 的 autofocus 前提错(Modal 首个可聚焦元素是关闭钮)· ⑫ 任务总表把 T11 标为可与 T12 并行、漏了 AiProviderSettings.tsx 双点名 · ⑬ B4 的 37 文件清单未扣除 B1/B2 的 14 条 · ⑭ Task 11 的「16 处 confirm(」与「impacts{ ≥ 8」两个数都不成立(实测 confirm( 24 = 8 + 16;impacts={ 6)· ⑮ Task 13 的 Step 3 + V2 与铁律①自相矛盾 · ⑯ 施工图 §13.1/§13.2 与守卫 ② 的文本口径互斥 · ⑰ 施工图未核对「文件是否本就 >300」(23 个里 8 个已 >300)· ⑱ Task 14 的 V2/V3 三个数不可复现(真值 18/18;「门控 9/5」用任何可辩护口径都复现不出)· ⑲ Task 8 的 V3「四个测试文件共 92 条」实为 70(6+31+18+15)。
另有三种「非计划错、但必须记住」的口径事故(逐条见批 4 计划 §收口回写 §八):仪器没跑到断言被读成「判据无牙」(
--cache.dir在 vitest 4 已废弃 ⇒ exit 1 且 0 用例;纪律:变异体 harness 必须把「跑到了断言(用例数 >0)」与「跑红了」分开判)· 同一棵导出树上「改→跑→还原」给假红(copyFileSync保留 mtime + vitest 缓存写在借来的node_modules里;正解 = 每个变异新解一棵树)· 把上一单元的门禁读数抄成自己的(7457c7f1的 163/1557 实为 164/1561 ⇒ 纪律:门禁读数必须在本次提交的树上重跑)。
未做(登记,逐条带归属批次)
真机 / WebView2 验收 → 批 8(用户已裁决本批跳过;不得出现「已在真机确认」类表述)· 像素/排版探针(6→8 9 处 · 边框暖色 · 20 处阴影 · Text 行高 · 20 弹层宽度 Δ · StatusLine 间距 · belowNav 落点 · right 16→18 的 2px · Modal 退场手感)→ 批 8 · 五类棘轮余量(空态例外 8 + 余量 5 · 加载 8 · 三红 114/67 · 弱化灰 63/44 · 边框 226+261+24)→ 批 5/7 · 11 锚定菜单的退出语义(含 4 处元素级 onKeyDown 与 SelectionActionMenu 的捕获相 ESC)→ 批 5 或批 8 · Text 的 558 处字号越界(映射规则已在 tmp/t16a/slice.md)→ 批 5/6 · ink-4 与 §4.3 条件③ → 批 5/6 · b1-non-migrated 9 处 + NON_MIGRATED_14(批 5/7 要迁它们的排版,必须先裁决 B1/B2 的守卫范围)→ 批 5/7(前置裁决) · token 真源补 pill 档四处(gen-tokens.mjs / tokens.gen.ts / tokens.css / tokens.drift.test.ts:52)→ 批 5/6 · Surface 的 DOM 属性透传(解锁 3 处)与透明容器是否接受多一层底(+28 处)→ 批 5 · 错误行的位置问题 → 批 5 · SURFACE_CLASSES 是否升级为真判据 · MIN_CALLS 与 T15 探针表逐格对拍 · bundle-eager-graph.mjs 把 import type 计成静态边(批 3 #2)· Toast 的 belowNav 堆叠失效 · --ed-nav-h 兜底 56px 无绑定判据 · Modal 滚动位置不恢复 · docs/tech-debt/review-2026-09-11.md(191 KB,mtime 2026-09-11,未入库)→ 待用户裁决 · 规格 §6.2 的「会话详情头改粘性 / 笔记工具栏三层合并」(批 3 #15 = ADR-034 S-4;本批实测未做)→ 批 5(回落批 8) · 3 套 markdown 归一(批 3 #16)→ 批 5/7 · ADR-035(L4 动效)→ 批 6 · 门禁 --staged 模式(批 3 #1)→ 批 8。
↳ 收口后更正(2026-09-12;上行原文一字未改):本行三处读数已过期 —— ① 五类棘轮余量里的弱化灰
63/44→64/44(FROZEN_MUTED_GRAY_TOTAL = 64;见上文「更正块 A」)· ②b1-non-migrated的「9 处」是回退动作数,该类冻结处数 = 14(收口修复前 13)· ③ 既有 flake 的处置已定为「已加固、未复现」(cd85e4c3;见上文「I-4 的 flake 处置」)。↳ 批 7 T10 更正(2026-09-13;上面原文一字未改):① 上行逐字写的
FROZEN_MUTED_GRAY_TOTAL = 64已过期 —— 真值63(textBaseline.ts的常数 == 逐文件表之和 == 实测,三者一致;「63/44」亦应作63/43):64是ed07d491的旧值,已在f193808d随一次真实迁移收紧回63/43。② 上行逐字写的「边框226+261+24」亦已过期 —— 批 7 T7 迁完<Surface>后重冻为201 + 254 + 24(边框 201/99 · 越界圆角 254/107 · 阴影 24/24;三者「常数 == Σ表 == 独立复算」已复测)。⚠️ rulings.md§C10.6 清单原写「223/260/24」= T7 落地前的读数,已被 T7 的重冻取代 ⇒ 以本行实测值为准。
诚实代价(不许省略)
- 首屏 gzip 97.16 → 100.30 kB(+3.14 kB,+3.2%),入口 chunk 原始 +8,239 B。涨的是必要成本(原语层 barrel + 12 个模块 + 10 份原语 CSS 首次进首屏),低于 B5 给出的上界 +3.41 kB,远低于 200 kB(余量 99.70 kB)。CSS 62.63 kB 原始 / 14.42 kB gzip 不计入判据,只报告。
- B9 的逐字中间态:「只有接缝、没有纲领」—— 三档强度 / 双基调 / GSAP 在批 6。 批 4 把
[data-phase]三态、--ed-dur-*与 reduced-motion 块接到了真实调用点上 ⇒ 界面第一次真的会动,但手感未设计、未调参;验收不得把接缝当最终手感,也不得声称动效系统已交付。 - 这是本系列「观感变化」最大的一批,而且大部分变化是「不便逐条列举的观感」:叠放值收敛(
50/51/60/999/1000/1100/1150 → modal(300)·30–61 → popover(200)·900 → panel(100)—— 规格 §10 逐字「观感从批 4 开始变」在这里的形态就是它)· 20 个弹层的档位宽度 Δ(10 个变宽:560/680/460/340/360/640 → 720/720/520/380/380/720等,最大 +160;RefineWorkbench1200/90vw → 720 = −480)·RefineWorkbench并排 → 单栏可读(面板 −36.7% · 两栏 −40.7% · 每行 46 → 28 字;顺带修掉 720 下 32px 水平溢出)· 卡片6→89 处 · 边框冷灰 → 暖纸(14 处)+ 近白底冷灰 → 暖纸(8 处) · 20 处阴影换 token(含 1 处有损) · 遮罩统一rgba(26,26,26,.34)· 11 处 / 13 串标题装饰 emoji 去掉(🗑等语义字符保留)· 关闭钮统一 · 加载态由「居中块」变一行 + 6 处骨架首上线 · 错误行改StatusLine(flex + gap 8px) · 弱化文本 186 处墨度 2.54:1 → 5.13:1、行高由字阶类接管。这些全部只有类级/属性级/源码级证据(jsdom 不排版;真机已裁决跳过)⇒ 批 8 的像素探针才是判据。 - 两处「规模缩小」是本批最大的计划-实际偏差,逐条带分区:①
6→8计划 254 处 → 实改 9 处(254 的完整分区:控件 161 · NM14 25 · 交互 13 · 透明 13 · 间接 1 · 有底色 41;其余 245 处维持现状,控制方 B22 裁决「不机械拉齐」);② 卡片边框计划 172 处 → 实迁 14(172 = 控件 96 + NM14 14 + 锚定菜单 4 + 交互 4 + 条件底色 4 + 透明 28 + 有底色 22;57 分隔线 + 11 条件色结构上表达不了)。 - T15 的守卫回退代价(明确选中):为守住 B1/B2,6 个文件逐字回退 ⇒ 错误行迁移面 55 → 49、三红回升 +6 行、空态例外 5 → 8 条(B21:代价不对称)。
- 9 个贴边文件(动它必须先拆):
ui/primitives/dialogMigration.e.test.ts300/300(余量 0 ⇒ 禁止再碰) ·ui/primitives/textBaseline.ts299 ·ui/primitives/loadingRatchet.test.ts299 ·ui/primitives/emptyStateRatchet.test.ts296 ·pages/NotesPage.tsx300/300 ·ui/primitives/surfaceRatchet.test.ts287 ·ui/primitives/textRatchet.test.ts266 ·pages/ChatPage.tsx578/600 ·shell/CommandPalette.tsx203/220。
↳ 收口后更正(2026-09-12 · 收口评审 M-4 + 修复单元;上行原文一字未改):①
pages/ChatPage.tsx的 578 是7457c7f1时点的值 ⇒ 579 权威(cbc15837拆件 → 578 · T16-B 的be925809→ 579;豁免表:24声明 579,控制方[System.IO.File]::ReadAllLines(...)亲测 579、LF 579、末尾有换行、29,151 B)。② 贴边表本身也变了:ui/primitives/loadingRatchet.test.ts299 → 181(8a2dd5e1拆出ui/primitives/loadingScan.ts101 行)⇒ 不再是贴边文件;ui/primitives/textBaseline.ts仍 299/300(贴边);ui/primitives/dialogMigration.e.test.ts仍 300/300(余量 0 ⇒ 禁止再碰)。↳ 批 7 T10 实测更正(2026-09-13;上面原文一字未改):贴边表里那 5 个「已变 / 待复核」的行数,按
countLines()(scripts/line-limits.mjs,含空行的全部行数)在当前提交树逐个重测 ——ui/primitives/surfaceRatchet.test.ts287 → 261 ·ui/primitives/textRatchet.test.ts266 → 270 ·pages/NotesPage.tsx300/300 → 295 ·shell/CommandPalette.tsx203/220 → 207;ui/primitives/textBaseline.ts复测仍为 299/300(§C10.6 清单原写「299 → 297」是已过期的预期值,299 才是实测 ⇒ 该处不动)。⚠️ §C10.6 另外四个目标值(261 · 270 · 295 · 207)与本次实测逐字一致。
- 13 个判据文件超计划预算(
dialogMigration.a2268/220 ·.e286/240 ·confirmMigration297/220 ·buttonMigration268/220 ·zIndex.guard284/200 等)—— 全部 ≤300 硬限、零新增豁免登记;口径:预算是估算,不为落进预算删判据(批 3 已有 4 例先例)。 - 两条未验证的诚实边界:20 个弹层里只有 5 个有同名测试(无覆盖的 15 个已在批 4 计划 §六 逐条列名;
PracticeQuestionsOverlays/SopRunOverlay从未被任何测试渲染过)·App.tsx无渲染级测试面(仓内没有App.test.tsx)⇒ 顶栏/命令面板的真实装配只有 T10 的一条渲染级断言 + 真机证据(未跑)。
↳ 收口评审 I-5 就地更正(2026-09-12;上行原文一字未改):上行「20 个弹层里只有 5 个有同名测试(无覆盖的 15 个)」实测不成立。两种口径各测一次(复现命令:
node .superpowers/sdd/2026-09-12-frontend-redesign-batch4-primitives/tmp/docfix/d1-coverage.mjs——DIALOG_20从app/src/ui/primitives/dialogMigration.e.test.ts解析、不手抄):① 有同名测试文件X.test.tsx的 = 10 / 无 = 10;② 其中真的render(<X)的 = 10 / 不是 = 10 —— 两口径完全重合,差额为空(没有「有同名文件却不渲染该组件」的项)。
- 有测试面的 10 个:
ChatSaveNoteDialog·GoalPlanApprovalDialog·GraduateDialog·InterviewDialog·KnowledgeDecisionForm·KnowledgeSystemWizard·ModelCardCreateDialog·RefineLaunchDialog·RefineWorkbench·TaskLaunchDialog。- 无同名测试文件的 10 个:
GroupCreateDialog·GroupDeleteConfirm·KnowledgeConceptDialog·KnowledgeModelDialog·ModelCardFromNoteDialog·NoteAiDialog·PracticeQuestionsOverlays·ProofreadPanel·SecondPassPanel·SopRunOverlay。 差额逐个列名(口径① 有 · 口径② 无)= 空。原文点名的 5 个(ChatSaveNoteDialog/InterviewDialog/RefineWorkbench/KnowledgeSystemWizard/TaskLaunchDialog)是这 10 个的真子集。「原写法 5/15 的来源不可考」:批 4 只改过其中 1 个测试文件(RefineWorkbench.test.tsx),其余 9 个git diff --name-only 42e88740..091d1c3d= 0 ⇒ 差异也不是「批 4 触碰过」这个口径。同条其余两句仍成立:PracticeQuestionsOverlays/SopRunOverlay在全仓测试文本里零引用 ✅、.e只钉源码形态 ✅。
- 一处历史不实(不重写):
8f5bd9f1是 T13 误--amend的产物(内容无缺失、历史线性未重写);54b9b938携带了 T2 的 ADR-033 加注(索引串味)⇒ 两条都只登记。
提交清单(49 个,4905d4d8^.. 至本收口提交;逐条 sha / subject / 归属 / 文件数见批 4 计划 §收口回写 §三)
| 归属 | 提交数 | sha(按时间序) |
|---|---|---|
| 计划(+ ADR-034 补写) | 1 | 4905d4d8 |
| 批 3 收口评审修复(非批 4 交付,落在区间内) | 1 | e4901247 |
| T1 基线 + 按钮棘轮 | 1 | 357ab117 |
| 前置守卫单元(T0 的 G3/G5) | 2 | 783a62ae · 6effbda5 |
| T2 / T3 | 2 | a9c63c0a · 54b9b938 |
| T4 z-index 六档 | 1 | 8d84ecfe |
| 前置守卫评审 follow-up | 2 | f3b2b6ce · a25ed2c6 |
T5(含授权前置 0228a013) |
2 | 0228a013 · 57a78c7d |
| T6 / T7 | 2 | 09c49941 · cc6cdadd |
回填 + 修复单元(emoji / decorateRefined) |
3 | 4c52cdd8 · 854c0af9 · 45ce9292 |
| T8(20 清单收口) | 1 | 0148b5ed |
| T9(两半) / T10 | 3 | b5c464af · 4a804a58 · bde807dc |
| T11 / T12(三提交) | 4 | 0e17e666 · 5d485ff8 · 1a7762bd · f6dd012f |
| T7–T12 评审修复单元 | 2 | ebac9d73 · 9c2a00a4 |
| T13(拆件 / 空态切片 / 棘轮收紧) | 3 | cbc15837 · 37c068aa · c635c0bb |
| T14(两提交,第二提交被 amend) | 2 | 271a281c · 8f5bd9f1 |
| T15 接管收口(57 路径) | 1 | 7457c7f1 |
| T16-A(地基) | 2 | 3ed9cfe9 · 93763ae7 |
| T17-A(地基 + pill 档) | 2 | 2360c3d9 · 0bc09a41 |
| T13–T15 评审收口修单元(F1–F4) | 4 | f2a91eb6 · 5825fae3 · 451db3fb · 0b27540c |
| T16-B(迁移,三提交) | 3 | 9532b189 · be925809 · a9c7e300 |
| T17-B(迁移,四提交) | 4 | 1ac129ae · 69489f9f · 18d56cbc · 199da54b |
| T18 收口(本节所在提交) | 1 | (自引用,无法写入本节) |
| 合计 | 49 | —— |
注:本收口提交的 sha 无法写进它自己的内容里(自引用);批 2/批 3 的先例同样把「收口回写提交」单列在区间之外或标注自引用。本行的「49」=
4905d4d8^..<收口提交>含左端点;git rev-list --count 42e88740^..199da54b的 49 与42e88740..199da54b的 48 一并报出(前者含批 3 的收口提交42e88740,不是批 4 的提交数)。
提交数口径(本文档既定规矩):本文档批次行一律采用「含左端点」口径(
A^..B,A= 该批第一个提交,见批 0-A 行的声明)。本行同款:批 5 的第一个提交 =ad9d80d2(test(sessions): pin detail panel before split)⇒ad9d80d2^..至收口提交 = 31(30 个 T0–T17 的实施/守卫提交 + 本节所在的收口提交 1 个)。另报字面读数以免歧义:git rev-list --count 2559a3fd..b4edf8e4= 30(= 批 5 本批 T0–T17 的全部提交,不含收口提交;b4edf8e4= T18-A/B 的开工 HEAD)·git rev-list --count 4905d4d8^..b4edf8e4= 88(含左端点,从批 4 计划提交起算)·git rev-list --count 091d1c3d..2559a3fd= 9(批 4 收口后追加的那 9 条)。
⚠️ 边界端点更正(记控制方账上):派发书写「批 4 收口后追加的提交(修复 4 + 文档 4 + 批 5 计划 1 = 9 条,区间091d1c3d..7d541254)」—— 总数 9 正确,端点错:实测091d1c3d..7d541254= 5 条,因为其中 4 条文档提交是批 5 计划提交的「子」提交(顺序:7d541254计划 →6038bb42→11018f40→2901511f→2559a3fd)。正确端点 =091d1c3d..2559a3fd(9 条),且2559a3fd正是 T0 冻结基准的 HEAD(compare-perfile.mjs的FROZEN_HEAD,逐字吻合)⇒ 用它当批 5 起点与全批台账一致。另:那 9 条按 Conventional Commits 类型分实为test×5 +docs×4(派发书的「修复 4 + 文档 4」与实测「test 5 + docs 4」总数一致、内部分类不一致 ——2901511f test(ui): fix stale zindex guard comment被计入「文档」而非「修复」)。如实登记,不擅自改派发书数字。
交付
- 视图层从 0 到 1:新建
app/src/views/子域(session/+note/两个子目录),views/**实测 17 个文件(9 个生产 + 8 个测试),全部 ≤300 行(最大NoteCardFlowView.test.tsx273)。生产件逐个:views/registry.ts109(ViewSpec+load+viewsFor+FROZEN_VIEW_KEYS)·views/useViewMemory.ts70(顶格)·views/session/SessionTriTrackView.tsx207 ·views/session/SessionProofView.tsx168 ·views/session/SessionCardFlowView.tsx104 ·views/session/SessionNotePreview.tsx38(T6b 的会话槽适配器)·views/note/noteCardModel.ts106(结构派生器,文件头显式命名「批 7 归一」)·views/note/NoteCardFlowView.tsx38。 ⚠️ 数字更正(Minor-1 / Minor-2;上面那一行原文一字未改,只在此追加 —— 守「删除行 0」纪律):上一行括号里的生产/测试数写反(写作 9+8)⇒ 实为 8 个生产 + 9 个测试(与上一行随后「生产件逐个」列出的 8 件一致 ⇒ 原句的句内自相矛盾由此解除);「最大NoteCardFlowView.test.tsx273」报小 ⇒ 最大 =views/note/noteViews.test.tsx295(余量 5),273 是次大(views/session/SessionCardFlowView.test.tsx)。total 17与「全部 ≤300 行」两条原本就成立。复现:node tmp/fix18/verify-facts.mjs⇒{total:17, prod:8, test:9, over300:[], max:{noteViews.test.tsx,295}, second:{SessionCardFlowView.test.tsx,273}};同款更正见批 5 计划 §八 #27 与本文档「过程中纠正的计划错误」段紧后的补登(2/2)。ViewSpec按 C1 升级为可执行加载器:字段{ key, label, icon, appliesTo, load? },load?: () => Promise<{ default: ComponentType<P> }>(取代规格 §7.1 的静态Component与lazy布尔),宿主用React.lazy+Suspense(复用既有ShellFallback)。默认视图无load(session[0].hasLoad = false·note[0].hasLoad = false),非默认 5/5 全有,每个load体内恰 1 个import(,注册表顶部 0 个视图组件静态 import(4 条 import 逐字全是import type)。- 一个新原语
ViewSwitcher(ui/primitives/ViewSwitcher.tsx135 +.css63 +ViewSwitcher.test.tsx225 / 14 passed):分段控件,进ui/primitives/index.tsbarrel(45 → 48)并在style-contract.test.ts的枚举里(233 → 296 行,用例 6 → 10,只增不删);零行内 style;落--ed-dur-micro(120 ms)响应层接缝。类名走 R-2:容器.ed-btn-group+ 段.ed-btn--segment(复用ed-btn基座命名空间 ⇒ 既有断言改动数保持 0)。 - 视图矩阵终态 = 会话 5 个 · 笔记 2 个:会话
["raw","tritrack","proof","cardflow","preview"](raw= 原文常驻默认;tritrack= 三轨对齐,三轨 = 转写 / 画面 / OCR 文字;proof= 印样;cardflow= 卡片流;preview= 既有的笔记预览,按 §7.3② 一并进注册表并由页 chunk 转为惰性);笔记["raw","cardflow"]—— 第三种「带证据三轨」是 C2 的条件项,只读探针判不存在逐段级「笔记 ↔ 证据」读取路径 ⇒ 按 C2 逐字「交付 2 视图 + 就地加注规格 §7.2/§11-6 + 登记批 7」,T13 = 零代码登记提交,不建空壳视图。 - 两个视图宿主:
components/session-detail/SessionViewHost.tsx136(会话侧:注册表接线 + 视图记忆 + 默认视图常驻 + 惰性挂载 + web 早退 + C11 槽位)·components/notes/NotesReadingColumn.tsx290(笔记侧:变视图宿主 +flushSave阻断 + 就近StatusLine+ C11 槽位)。 - 三条硬约束全部落到机器判据(规格 §7.3,本批的验收主轴):① 原文永远保留(
registry[0].key === "raw"∧ 默认无load∧ H1 11/11 ∧ F5 11/11)· ② 非默认视图模块级惰性(每个load恰 1 个import(∧ H2/H3 11/11 ∧ F6 11/11 ∧ 懒 chunk 22 → 31)· ③ 编辑态切视图先flushSave、失败则阻断(F1–F4 11/11 ∧ F9;catch⇒ 不切视图 + 保持编辑态 + 就近StatusLine kind="error",不用 toast)。 - 拆件(C9,每个拆件独立原子提交、先补安全网再拆):
components/SessionDetailPanel.tsx297 → 148(T2 四步抽件;随后被 T10 的接线下沉到 182)· 新件SessionRawView.tsx157 ·SessionViewHost.tsx136 ·SessionAuxBlocks.tsx127(三件 + 安全网 164 行)·session-detail/SessionScreenCard.tsx(T3 抽单卡)·pages/NotesPage.tsx300 → 288(T4 拆到 285 → T16 的focus*+ T14 的 2 行接线 ⇒ 288;未新增登记)。 - 会话详情头粘性(C13):
session-detail/SessionDetailHeader.tsx161 → 176,形态position: sticky+top: var(--ed-space-4)(4 px)+zIndex("raised")(10);配套行为级判据SessionDetailHeader.test.tsx9 passed(改前 5 passed / 4 failed)。 - C6 的最小收敛:5 个粘滞字段(
focusSessionId/focusNoteId/focusNoteSearch/focusSystemId/focusGroupId)补onFocus*Consumed复位回调(声明形态与类型零改动 ⇒CommandPalette.kb.test.tsx既有断言一字未改且9 passed);useNotesDeepLink.ts:18的注释与实现不符处已改正(+onConsumed);App.tsx584 → 590/600。{value,key}全量统一登记批 7/8(durable;若届时要动,须先请裁改写那条既有断言)。 - C18 的棘轮向下重同步(T2 独占):迁移吃掉豁免 ⇒ 逐族下调并保持
FROZEN == Σentries+ 锚同步 —— 弱化灰 64 → 63 / 文件 44 → 43 · 字号越界 558 → 551(键 8 → 1)· 边框 226 → 223 + 锚 108 → 107 · 越界圆角 261 → 260 + 锚 109 → 108 · 三红 114 → 113;每条判据各带变异体(M1–M4 全红)+ 反例守卫 M5 绿。 - 测试面:新增 18 个测试文件 / 138 用例(逐条见
tmp/t18/measurements.md§3.1 的ADDED=18清单)+ 4 个既有文件 GROWN(navHeight.consumption.test.ts3 → 6 ·Modal.scroll-lock.test.tsx6 → 9 ·style-contract.test.ts6 → 10 ·colorPalette.test.ts40 → 43);既有用例一条不少(逐文件对拍批 5 开工基线 LOST=0 · SHRUNK=0)。 ⚠️ 数字更正(Minor-3;上面那一行原文一字未改,只在此追加):上一行的「138 用例」标错 ⇒ 实为 149 用例(= 上一行自己引用的「ADDED=18清单」18 件用例数之和8+4+2+17+2+12+10+13+11+9+6+11+5+14+6+5+5+9);同段的 GROWN 增量 = 13(不是 24:6−3·9−6·10−6·43−40)。总数不变:13 + 149 = 162 = 24 + 138⇒1608 + 162 = 1770✅。复现:node tmp/fix18/verify-facts.mjs;同款更正见批 5 计划 §八 #28。- C16 的两条工具侧事实(入账):
scripts/check-bundle-budget.mjs没有任何锁机制 ⇒ 批 5 的真实构建一律走显式取锁协议(flag: "wx"原子创建 + 退避 30 s × ≤6 +finally释放 + 锁体含createdAt/pid/purpose/owner/attempt),且工具不打印distmtime ⇒ provenance 由执行单元自采。
验收(三条硬约束 + 八门禁终态;原始读数与命令见批 5 计划 §收口回写 §一/§二)
| 验收(规格 §10 批 5 行逐字「各 ≥2 种形式可用;原文不丢」) | 判据 | 读数 |
|---|---|---|
| ① 原文视图永远保留 | registry.ts:109 的 [0].key === "raw"(自写结构探针 exit 0)+ views/registry.test.ts(12 用例)+ SessionViewHost.test.tsx(H1)+ NotesReadingColumn.views.test.tsx(F5) |
session[0].key = "raw" ✅ · note[0].key = "raw" ✅ · 默认无 load ✅ · H1 11/11 · F5 11/11;反向对照 T10-M1(6 红含 H1)· T14-M5(唯一红 F5) |
| ② 非默认视图模块级惰性 | A1/A2/G7(图级 + 结构)+ H2/H3 + F6 + 懒 chunk 台账(R-1) | 每个 load 恰 1 个 import((5/5)· 顶部运行时 import 0 · H2/H3/F6 各 11/11 · 懒 chunk 22 → 31;反向对照 T10-M2c(仅 H2 红)· T10-M3(含 H3)· T14-M6(唯一红 F6) |
③ 编辑态切视图先 flushSave、失败则阻断 |
NotesReadingColumn.views.test.tsx 的 F1–F4 + F9(既有断言原样绿) |
F1–F4 各 11/11 passed;F4 断言「阻断全过程 0 个 toast 节点」并证选择器有牙;反向对照 T14-M1(把 catch 改成继续)⇒ 唯一红 = F1;F9 = 文件头注释(无 it、无变异体,设计如此) |
| 验收「各 ≥2 种可用」 | 两个 FROZEN_VIEW_KEYS 清单 |
会话 5 ≥ 2 ✅ · 笔记 2 ≥ 2 ✅(「笔记 3 视图」是条件项、未兑现,见规格 §7.2/§11-6 加注) |
八门禁终态(HEAD = b4edf8e4 · 采集窗口 22:57:07 – 22:58:51 +08:00 · 真实构建产出 app/dist mtime 2026-09-12T14:58:51.595Z = 22:58:51 +08:00)
line-limits --full >600 0 · 301–600 档 122 · 登记条目 122(exit 0;--write 复跑逐字节零 diff、sha256 相同 ⇒ 豁免表不在本次收口提交路径里)· docs-check exit 0(扫描 277 / 检查 177,五项全 ✅)· registry 312/312/0 · tsc --noEmit 0 错 · vitest 184 文件 / 1770 用例 / 0 失败 / 0 skip(逐文件对拍批 5 开工基线 2559a3fd 的 166 文件 / 1608 用例 ⇒ LOST=0 · SHRUNK=0;GROWN 4 · ADDED 18;testResults.length 是权威文件数口径 —— vitest 4.1.11 的 JSON 顶层没有 numTotalTestFiles 字段,而 numTotalTestSuites = 647 是 describe 块数、与文件数差 463)· check-bundle-budget.mjs(真实构建,取 tmp/build.lock,attempt=1、finally 释放、事后锁不存在)exit 0 · 首屏 100.49 kB gzip(原始 318,299 B;余量 99.52 kB;CSS 3 个 63,229 B = 63.23 kB 原始 / 14.51 kB gzip 不计入判据,只报告;入口 index-Bn5oI23G.js 108,620 B)· bundle-eager-graph 91 文件(源 77 + CSS 14)/ npm 包 4,TS-API 真实边口径 66(结论口径),--keep-type-only = 77 自证(「91 − 66 = 25」确由 14 CSS + 11 条纯类型边构成)· Rust 未复跑(本批零 Rust 改动:git log 091d1c3d..HEAD -- app/src-tauri 与 git log 4905d4d8..HEAD -- app/src-tauri 两条均为空)—— 判据仍是批 3 的 2300 / 0 / 6,不得读成「已跑」。
三条硬约束的判据与变异体出处:逐条见批 5 计划 §收口回写 §一(含 ran 闸与 CONTROL)。M1(默认视图条件渲染)≠ T14 的 M1(catch 分支继续切换)—— 两者同名不同物。
首屏账(Δ + 机理;基线 = 091d1c3d 冻结值):首屏原始 317,778 → 318,299 B(+521 B / +0.16%),全部落在入口 chunk(108,099 → 108,620 B);gzip 100,297 → 100,485 B(+188 B / +0.19%);首屏 chunk 个数 3 → 3(Δ = 0,构造性成立);vendor-react / vendor-tauri 逐字节不变;CSS 62.63 → 63.23 kB(+599 B)。懒 chunk 22 → 31 个、原始 1,790,753 → 1,805,017 B(+14,264 B)、gzip 575.16 → 583.98 kB(+8.82 kB)。eager 三件套:工具 89 → 91 文件(= 源 76 → 77 + CSS 13 → 14)· TS-API 真实边 65 → 66 · npm 包 4 → 4 ⇒ +2 全部是 ViewSwitcher.tsx + ViewSwitcher.css(唯一新增的 barrel 导出),没有任何页面被静态拉回首屏。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
§7.1 ViewSpec 的 Component / lazy → load(C1:把布尔升级为可执行加载器;默认视图无 load) |
规格 §7.1 加注(原文一字未改) |
§7.2 会话 4 视图 → 5 个(preview 按 §7.3② 一并进注册表并转惰性) |
规格 §7.2 加注(会话侧读数块) |
| §7.2 笔记 3 视图 → 2 视图(C2 条件项判否;不许空壳视图;R8 防「条件项被当成已交付」) | 规格 §7.2 加注(表格后整块,T13 备好文本逐字落位) |
§7.3 三条硬约束 → 机器判据落点 + 9 条判据 + 变异体出处(含「F9 无 it 无变异体、设计如此」与 A5①/A5② 的守卫自证缺口) |
规格 §7.3 加注 |
| §8.6 签名动效 1 的第三轨 = OCR(C2 连带硬要求;「笔记轨」未交付的原因与去向) | 规格 §8.6 表后加注 |
§10 批 5 行 → 加 ↳ 批 5 的收口 行(✅ + 两处数字更正 + 三条硬约束 + 八门禁 + B9 观测口径) |
规格 §10 表 |
| §11-6 → 会话 5 种 / 笔记 2 种(含「本条验收不因此变红:2 ≥ 2」) | 规格 §11-6 加注(T13 备好文本逐字落位) |
| §11-9 → 批 5 首屏进度注(100.49 kB / 余量 99.52 · CSS +599 B · 懒 31 · GSAP 仍未装) | 规格 §11-9 加注 |
§11-11 八门禁 → 加批 5 进度注(含「cargo 未复跑」的显式声明 + numTotalTestFiles 不存在的仪器口径) |
规格 §11-11 加注 |
§5.1 → 「错误行的位置」处置(批 5 只预留槽位、不重排既有 StatusLine 调用点;像素判定转批 8) |
规格 §5.1 加注(C11) |
§6.2「本次改动」列最后两条(🗂 会话 · 详情头改粘性 ✅ 批 5 已做 + 真实粘性不可验;📝 笔记 · 工具栏三层合并 → 批 8) |
规格 §6.2 加注(A5 = C13) |
| §12「3 套 markdown 渲染器」(C8:批 5 不做归一、转批 7;本批只保证不新增站点;口径更正为「4 套活 + 1 套死」) | 规格 §12 加注 |
| §13 风险表三条(视图层内存膨胀 / 编辑丢稿 / 包体继续膨胀的兑现度与未验证面) | 规格 §13 表后加注 |
§14 两行(v0.22 的批 5 节已落;批 5 未新增任何 ADR、docs/adr/README.md 索引零改动、ADR-035 仍顺延批 6) |
规格 §14 表 |
ADR-033 §1(导出面新增第 10 个原语 ViewSwitcher:barrel / 枚举 / --dur-micro / 零行内 style;上表行数 45 → 48、233 → 296) |
ADR-033 §1 加注 |
ADR-033 §4(R-2 类名空间语义折中的诚实代价 + 产物级前后对照锚 ed-btn--segment 由 NOT-FOUND 变命中;两条 Surface 缺口 → 批 7) |
ADR-033 §4 加注(D12) |
ADR-033 §登记(视图层契约在批 5 的载体 + flushSave 行为 + 两条未做项 + 行数代价 + ADR-035 仍批 6) |
ADR-033 §登记 加注(C3 = C4) |
ADR-034 §登记(:115 两条的最终结果:粘性 ✅ 已做 / 工具栏三层合并 → 批 8;F-3 的文件名更正) |
ADR-034 §登记 加注⑧(C4 = C13) |
过程中纠正的计划错误(①–⑳;逐条带读数与出处)
① C14① 被实测否证 —— 计划写「ViewSwitcher 进 barrel ⇒ 首屏 Δ 不是 0,机理 = barrel 已在首屏」,实测 JS Δ = 0(rollup 把它 tree-shake 进懒 chunk registry-C-RvXIfE.js)+ CSS +604 B ⇒ 结论改成「barrel 里有导出 ≠ 产物里有模块」· ② W4 与 Step 1/Step 3 互斥(Step 1「不设状态类」+ Step 3「枚举恰 2 项」与 W4 第一条子句「选中段与未选中段的 className 不同」不可同时成立)⇒ 控制方裁决 1:接受 T5 实施 + 强化 W4(每段 className 逐字等于 ed-btn ed-btn--segment;aria-pressed 是状态的唯一权威)· ③ V3 与 Step 1③ 互斥 ⇒ 口径改为「新增 ≫ 删除 ∧ token 保序包含」· ④ A2③ 的 components/** 前提不成立 —— 计划原以为 views/** 零 components/**,实测有 4 条真实边(NoteMarkdown ×2 · SessionScreenCard · NotePreviewView)⇒ 判据收窄为「只禁 pages/** / shell/**」(今日独立复测 = 0 条边,且带仪器双侧自证)· ⑤ P2 与 H1 互斥(计划判词与源码不符;P2 从「同步」改「异步」、从「存在性」改「可见性」)· ⑥ SPLIT_MOVES 条目删除(T10 删了 T2 登记的那条 —— 迁移不是搬运:两个原生 <button> 随切换器迁进 L1 原语(原语层在扫描域外)⇒ 计数真的由 1 降到 0;删除它 = 撤掉豁免、恢复逐文件棘轮的牙齿,FROZEN 是上界故判据仍绿)· ⑦ useViewMemory 住面板(C19 GO-3 的三项 STOP 之一:SessionDetailPanel 仍持 viewMode state,记忆 hook 的调用点落在面板层)· ⑧ 三处预算超支(navHeight.consumption.test.ts 165 vs 预算 110 · Modal.scroll-lock.test.tsx 269 vs 追加预算 +60 · NotesReadingColumn.tsx 290 vs ≤260)—— 口径:预算是估算,绑定约束是 ≤300 + 零新增豁免登记 · ⑨ 两处「拆件时点目标」被接线增量推翻(SessionDetailPanel 182 > 150:T2 拆到 148 后被 T10 的接线下沉;NotesPage 288 > 285:T4 拆件时点目标,T14 的 2 行接线 + T16 的 focus* 推到 288;C19 四条条件③逐字要求登记这条偏差)· ⑩ 测试文件从「共用 sessionViews.test.tsx」改为各自测试文件(C17④:计划 Task 7/8/9 的 Files 与「T7∥T8∥T9 可并行」互斥 —— 三单元写同一文件必然丢更新;实测 SessionTriTrackView.test.tsx / SessionCardFlowView.test.tsx / SessionProofView.test.tsx 各自存在,sessionViews.test.tsx 盘上不存在)· ⑪ 「13 个新文件」台账按实测改写(计划 §规模与预算 §1 写「13 个基础 + 1 个条件项」;实盘 views/** = 17 文件(9 生产 + 8 测试),且拆件产物确实是 3 个:SessionRawView + SessionViewHost + SessionAuxBlocks)· ⑫ 计划「预计提交 17(+1 条件项)= 18」→ 实测 30(机理:多数任务按「安全网 / 实现 / 收口」拆成 2–4 个原子提交 —— T5 单独 4 条、T2/T3/T4/T14 各 2–3 条)· ⑬ 懒 chunk 期望「27 或 28」→ 实测 31(逐块归属 10/10 全部闭合;见「诚实代价」的措辞改写)· ⑭ 计划 Task 13 的 V1 归属判据不可用(原写「提交统计不含 app/src/**」在多单元并行下不成立)⇒ 改为「零提交 + 暂存区空 + git status 无我产生的路径」(tmp/t13/zero-change-selfcert.md 的 V1a–V1i)· ⑮ 计划 Task 15 的 A3 判据形态错(整目录裸子串 includes("@tauri-apps") 会让 6 个文件里 5 个假红)⇒ 权威口径 = 剥注释 + 排除 *.test.* + 只匹配 import/export 声明 + 保留阳性对照 + 两个读数并列 · ⑯ 计划 C14① 的「首屏 Δ 不是 0」(同 ①,F 类事实更正)· ⑰ 计划写「CommandPalette.kb.test.tsx 17 用例」是笔误(实测 9 个 it;另一文件 12)· ⑱ 计划点名的 H1 锚点漂移(计划 :966 写 getByTestId("session-raw-view"),全仓 0 命中;落地用 data-testid="resident-probe",SessionViewHost.test.tsx 5 处 —— 双侧自证:前者 0 命中、后者 5 命中,同仪器同次 grep)· ⑲ 贴边表 13 格中 2 格与实测不同(textBaseline.ts 声明 299 → 实测 297,机理未判定(需批 4 中间树,本批禁 checkout)· loadingRatchet.test.ts 声明 299 → 实测 181,已归因:批 4 收口把扫描器搬进新文件 loadingScan.ts(101 行))· ⑳ 控制方前提错误的 6 例(① pwsh 不存在(本机只有 PS 5.1)② numTotalTestFiles 字段不存在 ③ 批 4 后追加 9 条的区间端点写错(..7d541254 只有 5 条)④ 工作树洁净度前提(?? docs/tech-debt/ 始终在场)⑤ 批 4 计划的 1964 行是被 T18 追加 §收口回写之前的时点值(引用一律按节名 + 逐字引文,不要用行数)⑥ scripts/check-bundle-budget.mjs 没有任何锁机制(C16 事实更正 1/2))。
另有两条「非计划错、但必须记住」的口径事故:① 计划 Task 7/8/9 的 Files 与并行互斥(同 ⑩;C17④)· ② 活树
app/dist可能滞后一整个批次(T16 实测:它构建前的活树 dist 只有 25 个.js/ 懒 22 个、无任何批 5 视图 chunk ⇒ 拿它当 before 会误记 +9 懒 chunk;批 5 的 R-1 台账因此改用tmp/t1/lazy-chunks.md(@2559a3fd)作 BEFORE,并在导出树里独立跑了一次真实构建复核,逐字节相等)。纪律:任何「before/after」必须用同源两棵树各跑一次真实构建(= 批 4 「< ~2 kB Δ 必须同源真构建」的强化)。
↳ 收口评审补登(1/2)· surfaceRatchet 判据语义修正 = 新增调用点登记制(T15a cc49b09c,5 文件 +388/−83)—— 计划写「标签数 == FROZEN_SURFACE_TAG_TOTAL 常数」⇒ 任何新视图用 <Surface> 必然红(T9 实测被迫改用 token 变量绕开)⇒ 判据改为「FROZEN == Σ登记值 == Σ实测」+ 逐文件 ≤ / ==(legacy 行 实测 ≤ 登记值、新登记行 实测 == 登记值)+ 表自洽 / 锚({entries:9, TaskConversationView, 3} 三查)/ legacy 和锁(14) + 未登记 = 0 + 防僵尸;唯一新通道 = 新文件同一次提交里登记 {file, count 恰等于实测, reason} + 抬高 FROZEN_SURFACE_TAG_TOTAL + 同步锚(四条堵漏:① legacy 和锁 禁「降值腾位」② 总数是既有 9 文件的紧上界 ③ 新条目恰等于实测 ④ 未登记 = 0 + 防僵尸)。本批新登记 0 条(通道已开,M5 合法登记变异 30/30 全绿证明可用);因 300 行硬限被迫从 3 路径扩到 5 文件:surfaceRatchet.test.ts 287 → 261 · surfaceBaseline.ts 261 · surfaceResidual.ts 81 → 184 · 析出 新 surfaceScan.ts(80) + 新 surfaceTagRegistry.test.ts(145)(加完新牙实测 391 > 300,line-limits 当场红);未动任何 ui/primitives/** 生产代码。逐条见批 5 计划 §八 #23(台账 §二十二 ④ 用词「必须」)。
↳ 收口评审补登(2/2)· 数字更正(Minor-1;上面 ⑪ 原文一字未改,只在此追加 —— 守「删除行 0」纪律):⑪ 括号里的生产/测试数写反(写作 9+8)⇒ 实为 8 生产 + 9 测试(total 17 与「全部 ≤300」两条不变);最大行数见本文档「交付」段第一条紧后的「node tmp/fix18/verify-facts.mjs;同款更正见批 5 计划 §八 #27。
诚实代价(不许省略)
- 首屏 gzip 100.30 → 100.49 kB(+188 B / +0.19%),入口 chunk 原始 +521 B;远低于 200 kB(余量 99.52 kB)。CSS 62.63 → 63.23 kB(+599 B,不计入判据,只报告)。首屏 chunk 个数 Δ = 0(构造性),但入口 chunk 内容变了。
ViewSwitcher进 barrel 的首屏 Δ = JS0 B+ CSS+604 B—— 计划 C14① 的「首屏 Δ 不是 0」被实测否证:ed-btn-group/ed-btn--segment在 dist 的 25 个 JS 里 0 命中、只在首屏 CSS 里命中 ⇒ rollup 把它的 JS tree-shake 进了懒 chunk(registry-C-RvXIfE.js)。⇒ barrel 里有导出 ≠ 产物里有模块。- 懒 chunk 22 → 31(+9)· 583.98 kB gzip(原始 1,805,017 B,不计入预算)。措辞必须照此读(E7 改写):「真新增 9 块 + 1 次共享块再分组(1 拆 2)」 —— 不要写成「ADDED 10 / REMOVED 1」(那会读成新增了 10 块、删掉了 1 块代码)。逐块具名(10 条全部有归属):
SessionTriTrackView2,155 ·SessionProofView2,058 ·SessionCardFlowView1,351 ·NoteCardFlowView1,489 ·SessionNotePreview11,472 ·registry4,943 ·NoteMarkdown6,564 ·SessionScreenCard332 ·fmt634 ·RefineLaunchDialog19,250。再分组的精确归属(导出树实测闭合):BEFORE 那块 21,149 B 的useTransientToast-XJI3diKc.js是一块共享懒块、同时装着RefineLaunchDialog与useTransientToast(rollup 按其中一个模块命名 ⇒ 名字极具误导性);批 5 让views/registry.ts+ViewSwitcher进入同一分组后该块重新分组为两块 ⇒21,149 = 19,250(RefineLaunchDialog 独立)+ 1,899(useTransientToast 迁入新共享块)✅ 无字节丢失;两个源文件在批 5 区间零提交(git log已证)。恒等式闭合:50,248(ADDED 10)− 21,149(REMOVED 1)− 14,835(保留 21 个的字节变化)= +14,264 B= 实测净 Δ(1,805,017 − 1,790,753)逐字节相等。⚠️ 纪律(陷阱 #110):chunk 名不是稳定标识 ⇒ 判 chunk 增删必须用模块级字面量归属,或至少逐块做字节闭合核算;只比名字会同时产生假 ADDED + 假 REMOVED。 - 「页 chunk 变小、总懒基本持平」:
SessionsPage页 chunk 73,703 → 63,415(−10,288 B) ·NotesPage页 chunk 161,732 → 156,917(−4,815 B) —— 视图代码搬出页面 chunk、改由懒 chunk 承载(另有colorPalette+229 B(T4 把笔记派生搬进utils/colorPalette.ts,124 → 175 行)·KnowledgePage+39 B)。 - R-2 的类名空间折中(语义代价):容器
.ed-btn-group+ 段.ed-btn--segment借用了按钮基座命名空间 —— 读到它的人会先以为是Button的一个档位。收益:Button的variant枚举与Button.css零改动,且既有动效/接缝计数(motion-coverage/style-seams)零改动 ⇒ 本批对既有断言的改动数 = 0(这是本批最值得记的一笔)。 - 三处「拆件顺带迁移」的可见/观感变化(登记,不是「写法变了、观感不变」):① 字阶
11 → 11.5与13 → 12(拆件时落到字阶档位)· ② 弱化灰#9ca3af → ink-3(批 4 的 5.13:1 口径延续)· ③ 圆角6 → 5(落--ed-radius-control档;起因是 T2 一度把圆角改成4「躲开冻结集合」被打回,最终落到真档位)—— 这些全部只有类级/属性级/源码级证据(jsdom 不排版;真机已裁决跳过)⇒ 批 8 的像素探针才是判据。 - 行数代价(逐条带口径):
SessionDetailPanel.tsx182 > C9 的 ≤150(T2 拆到 148 后被 T10 接线下沉)·NotesReadingColumn.tsx290 > 260(超 30,已登记)·useViewMemory.ts70 = 顶格(余量 0) · 三处预算超支(navHeight.consumption.test.ts165/110 ·Modal.scroll-lock.test.tsx269/+60 ·NotesReadingColumn290/260)·component/NoteMarkdown.tsx244 → 266。全部 ≤300 硬限、零新增豁免登记(301–600 档 122 → 122、FROZEN_OVER_LIMIT仍为空数组)。 - B9 的逐字中间态:「只有接缝、没有纲领」—— 三档强度 / 双基调 / GSAP 在批 6。 批 5 交付的是内容与结构(视图层骨架 + 多视图可用 +
--ed-dur-micro120 ms 的响应层接缝),手感未设计、未调参;验收不得把接缝当最终手感,也不得声称动效系统已交付。 - 三处「本批没能验证」的诚实边界(详见下节):真实粘性(jsdom 无布局引擎)· 真实滚动恢复(jsdom
scrollingElement不滚动)· 惰性挂载的运行时内存效果(字节面可测、内存面不可测)。
未做(登记,逐条带归属批次)
真机 / WebView2 验收 → 批 8(用户已裁决本批跳过;不得出现「已在真机确认」类表述)· 像素/观感探针(字阶 11 → 11.5 / 13 → 12 · #9ca3af → ink-3 · 圆角 6 → 5 · 视图密度观感 · 切视图卡顿 · 槽位像素位置与可达性)→ 批 8 · 「笔记工具栏三层合并」→ 批 8(C13;要动 NotesPage 288/300 + NoteListView 241 + NoteListToolbar 95 三个无测试面文件)· 错误行的位置重排 → 批 8(C11:批 5 只预留槽位)· flushSave 返回类型升级(NoteEditHandle)→ 批 8 接口卫生 · RichEditorView 内的 Ctrl+E / 完成按钮仍不阻断 → 批 8(C4②,非本批引入的回归)· {value,key} 全量统一 → 批 7/8(C6;要动须先请裁改写 CommandPalette.kb.test.tsx 的既有断言)· 3 套 markdown 渲染器归一 → 批 7(C8;口径「4 套活 + 1 套死」)· Surface 两条(DOM 属性透传 +3 / 透明容器 +28)→ 批 7(D12;接受 ② 会要求抬高 surfaceRatchet 冻结值 ⇒ 须一次显式裁决)· 笔记「带证据三轨」→ 批 7(必须先写规格)(C17①:E2 降级为 ms 最近邻 · E1/E3 改为「带锚点段落数」· 覆盖 OcrDirect/Web/手动笔记/anchor_timestamps=false 四类无锚点情形)· b1-non-migrated 与 B1/B2 守卫范围 → 批 5/7(前置裁决)(本批的编辑态提示落宿主层、不碰 NON_MIGRATED_14)· 卡片插槽 API 若 T9 后续需要 ⇒ 在 T9 消费时设计(本批未预扩) · token 真源补 pill 档四处(gen-tokens.mjs / tokens.gen.ts / tokens.css / tokens.drift.test.ts:52)→ 批 6 · ink-4 与 §4.3 条件③ → 批 6 · Text 的 558 处字号越界 → 批 5/6(映射规则已在 tmp/t16a/slice.md;本批已顺带迁 7 处 ⇒ 实测 551,C18 重同步时由 558 → 551) · 五类棘轮余量(弱化灰 63/43 · 字号越界 551 · 边框 223 + 越界圆角 260 + 阴影 24)→ 批 5/7 · FROZEN_NUMERIC_ZINDEX 等批 4 遗留项 → 批 5/7 · 视图的真实数据分布 · evidence 视图(C17① 的缺数据前置)· markdown 归一 · Ctrl+E/完成按钮仍不阻断 四项的成熟度判断 → 批 7/8 · 守卫自证缺口四条(G-1 A5① · G-2 A5② · G-3 A2③ · G-4 F9)→ 批 6/7(只登记、不在收口提交里补测:收口禁改代码;四条的性质分别由 G2 / F5+H1 / A2③ 判据本身 / T0 的 --frozen 对拍守着 ⇒ 不是覆盖漏洞,只是这几条判据自己没有专属变异体) · bundle-eager-graph.mjs 把 import type 计成静态边(工具本身)→ 批 8(C10 修正②:批 5 留批 5 但只作为判据口径,双口径并列,不修工具) · docs/tech-debt/(未入库)→ 待用户裁决 · ADR-035(L4 动效)→ 批 6。
提交清单(31 个,ad9d80d2^.. 至本收口提交;逐条 sha / subject / 归属见批 5 计划 §收口回写 §三)
| 归属 | 提交数 | sha(按时间序) |
|---|---|---|
| T2 拆件 A(安全网 / 拆件 / 棘轮重同步 / 圆角落档) | 4 | ad9d80d2 · 0bf849d2 · f193808d · d48fca57 |
T4 拆件 C(NotesPage 派生搬 colorPalette) |
2 | e579df63 · 343b38f0 |
| T3 拆件 B(屏卡安全网 / 抽单卡) | 2 | 4bee9d7a · 06116283 |
T5 地基 A(ViewSwitcher,4 提交) |
4 | afd35439 · ca19275a · 3c739c74 · 927aedf8 |
| T6a / T6b(记忆 + 槽契约 / 注册表 + 适配器) | 2 | b2d5d477 · 556515b8 |
| T7 / T8 / T9(三轨 · 印样 · 卡片流) | 5 | f191ab9b · 02dd20ba · d4794227 · e73b3616 · a41e9438(T7 · T7 判据复核 · T8 · T8 判据修正 · T9) |
| T11(粘性头) | 1 | a36145c5 |
| T12(笔记卡片流) | 1 | 6d49bb21 |
T15a(surfaceRatchet 登记通道) |
1 | cc49b09c |
T17(--ed-nav-h 绑定 / Modal 滚动恢复) |
2 | 7deeb274 · c927d547 |
| T14(笔记接线:宿主 + 注入) | 2 | dadd2515 · a9f8fe97 |
| T10(会话接线,重落地) | 1 | 5f39cefe |
T16(focus* 收敛 + 注释更正) |
1 | c652f67f |
| T15(架构守卫,2 文件) | 2 | 1d4023e4 · b4edf8e4 |
| T13(零提交 —— 条件项判否、零代码登记) | 0 | (progress.md 逐字「零提交(开工 6d49bb21 → 收工 c927d547)」) |
| T18(A 只产读数零提交 · B 本节所在收口提交) | 1 | (自引用,无法写入本节) |
| 合计 | 31 | —— |
注:T13 = 0 提交是 C2/C17① 的正确形态(探针判否 ⇒ 交付「为什么不做」的登记而不是空壳);T18-A 也零提交(只产
tmp/t18/**读数包)。上表逐条与tmp/t18/measurements.md§4.2 的 30 条逐任务表对得上(该表按 oldest-first 列 30 条,上表按归属归组)。本行的「31」=ad9d80d2^..<收口提交>含左端点;git rev-list --count 2559a3fd..<收口提交>的 31 与git rev-list --count 2559a3fd..b4edf8e4的 30 一并报出(后者不含收口提交)。
提交数口径(本文档既定规矩:一律「含左端点」
A^..B):批 6 的第一个提交 =ac504b06(docs(plan): 批 6 动效系统实施计划(36 任务))⇒git rev-list --count ac504b06^..975b3285= 77(= 计划 1 + T1–T34 里已提交的 34 个任务的提交 + 微单元;T15 与 T34 各零提交:前者是证据型任务、后者只产读数)。 冻结提交 =975b3285(test(motion): 拆开探针字面量并收紧显影判据= 波 C 最后一个提交);真实构建产出app/distmtime 2026-09-13T05:10:24.838+08:00、入口index-CBZzLV5U.js117,002 B。 🔴 读数正本 =.superpowers/sdd/2026-09-12-frontend-redesign-batch6-motion/task-34-report.md(T34,326 行):本节所有数字一律引用它、未重新实跑(唯一例外 = 「台账行数」一节由 T35 按提交树countLines()亲测,见line-limit-exemptions.md的二次刷新)。
交付
- 纲领与决策载体:新建
docs/standards/motion.md(T1,bffed928;先于任何动效代码落地)· 新建ADR-035(T2,97295d64;含**「后端契约例外」节**)+docs/adr/README.md索引 +1 行。规格 §14(:836)的「docs/standards/新增动效规范章节」由此兑现(批次归属消歧见本节「规格漂移纠正」)。 - 引擎:
app/src/motion/engine.ts(唯一入口,顶层gsap.registerPlugin(useGSAP, Flip, ScrollToPlugin, CustomEase),恰 4 个、顺序逐字)+engine.test.ts+engine.guard.test.ts(闭包交集判据 + 产物三件套,真实构建后复跑 11/11 passed / exit 0);app/package.jsondependencies 15 → 17(gsap@^3.15.0·@gsap/react@^2.1.2)—— R2.1 的唯一一次「零新增依赖」破例。 - token 真源:10 个时长/缓动变量迁入
app/scripts/gen-tokens.mjs(motion.css的--ed-*定义恒 0,回归封条落在style-seams.test.ts)+pill档(radiusScale第 5 档 = 999,取自既有兜底字面量)+ 新 token--ed-nav-h-live: 58px+ 两个基调缓动 token。 - 三档 / 双基调 / 位移:
app/src/motion/intensity.ts(data-motion三档 +motion:intensity持久化 + 跟随系统 + 源序守卫)·components/MotionIntensityControl.tsx+SettingsPage接线(复用ViewSwitcher)·app/src/motion/tone.ts(data-tone+CustomEase具名 ease)·app/src/motion/shift.ts(位移 8px 唯一出口 + 扩域守卫)。 - 底座与出口:
app/src/test/motionHarness.ts(确定性推进底座 +matchMedia桩 + 纪律入册)·app/src/motion/controls.ts(可中断 / 可反向的唯一出口,interrupt()真kill且killTweensOf先、timeline.kill()后)。 - 响应层 / 环境层:
motion.css的元素级全局回执(七类动作,零调用点改动)+ 原语层四类回执 +app/src/motion/responseCoverage.test.ts/responseSeams.test.ts/responseScan.ts;环境层四件 +@keyframes桶边界(app/src/motion/env.ts= 幅度真源)。 - 守卫改判与补测:G1 / G2 / G3 / G6 改判(每条给旧断言原文 / 新断言 / 专属变异体 / 为什么更强)+ G-1..G-4 补测(T15 = 证据型、零提交)+ T16 的三处文档就地更正(
textBaseline.ts头注 · 规格pinnable两处 · 豁免表人工块 19 条漂移)。 - 相变两态与承载面(波 B):
shell/shellPhase.ts+shell/phaseSource.ts(单一写入方)+shell/PhaseChrome.tsx+App.tsx接线(599/600)·components/Waveform.tsx(div 条阵列,禁 SVG)+shell/LiveBar.tsx(采集态 58px LIVE 仪表)· 复习态零 chrome(motion.css相位块 +TopBar.css两态,不 animate height)·components/review/DueScale.tsx(到期刻度视觉)·views/session/TimeRail.tsx+TimeRail.css+ThumbStrip.tsx(时间轨 / 播放头 / 掠过条)+ 音频降级提示 ·SessionViewSlot注入槽 +useSessionAudio.ts(音频引用的唯一过桥点)。 - 后端三条例外(R0.1 第 1 条):E3
Flashcard.intervalDays(Rust 4 文件 / 5 处,含types_contract_tests.rs的追加行)· E4session_audio_path只读命令(312 → 313)· E5 WAV 轴 ≡ 会话轴(audio_align.rs+audio_align_tests.rs+ 写块补静音 + sidecar{id}.wav.meta.json+aligned自证量 +MAX_GAP_MS= 10 min)+ADR-013就地加注(「WAV 轴与会话轴的对齐」节)。 - 6 个签名动效(波 C):
useTriTrackAlign(#1 对齐)·useRevealChoreography(#2 显影编排,字符率近似)·usePhaseFreeze(#3 相变凝固)·useScaleGrowth(#4 刻度生长,回缩用精确intervalDays)·usePlayheadJump+screensFor.ts(#5 时间码回跳 / 掠过缩略)·useRevealMemory(#6 记忆浮现,字距用x而非letterSpacing)·useColumnFlip(列折叠 Flip,授权路径 B)。 - 产品兑现点:
[[ts:ms]]回链接上毫秒 + 修掉死链(T26:NoteMarkdown/NoteReadingView/NotesReadingColumn/NotesPage/App.tsx五处接线;芯片此前整条不可达 = 一个真实缺陷)·[[ts:ms]]的 URL 消毒只放行内部锚点(T26 判据)。
验收(R0.1 第 2 条的验收面逐条 + 八门禁终态)
口径:生产调用点 =
app/src/**的.ts/.tsx减*.test.*(域内 336 个生产文件)里的实际调用 / 挂载行(注释与 import 行不计)。原始清单 = T34 的tmp/t34/callsites.txt。T36 出最终兑现度表;本节是 T34 的中间读数。
| # | 验收项 | 生产调用点 | 落点(逐字) | 兑现度 |
|---|---|---|---|---|
| 1 | #1 对齐 useTriTrackAlign |
1 | views/session/SessionTriTrackView.tsx:251 |
✅ 可判 |
| 2 | #2 显影编排 useRevealChoreography |
1 | components/session-detail/SessionRawView.tsx:96 |
🟡 部分:replay() 无生产入口(= 0) |
| 3 | #3 相变凝固 usePhaseFreeze |
1 | shell/LiveBar.tsx:90 |
✅ 可判 |
| 4 | #4 刻度生长 useScaleGrowth |
1 | components/review/ReviewSessionPanel.tsx:98 |
✅ 可判 |
| 5 | #5 时间码回跳 usePlayheadJump |
1 | views/session/TimeRail.tsx:140 |
🟡 部分:落位 + ≤8px 掠过已交付,长距离连续滑动未交付 |
| 6 | #6 记忆浮现 useRevealMemory |
1 | components/review/ReviewSessionPanel.tsx:102 |
✅ 可判 |
| 7 | 相变两态(data-shell-phase) |
1 写入方 + 1 载体 | shell/phaseSource.ts:84(全仓唯一 useShellPhase,shellPhase.guard.test.ts 名册守)· <PhaseChrome phase={phase}> = App.tsx:394 |
✅ 可判 |
| 8 | 承载面① 采集态 58px LIVE 仪表 + 波形 | 链路闭合 1/1/1 | App.tsx:394 → shell/PhaseChrome.tsx:102 <LiveBar …> → shell/LiveBar.tsx:135 <Waveform …> |
✅ 可判 |
| 9 | 承载面② 到期刻度视觉 | 1 | pages/ReviewPage.tsx:178 <DueScale due={scopeDue} testId="review-due-scale" /> |
✅ 可判 |
| 10 | 承载面③ 时间轨 / 播放头 | 1(+1 内部) | views/session/SessionTriTrackView.tsx:275 <TimeRail …/>;其内 TimeRail.tsx:220 <ThumbStrip …/> |
✅ 可判 |
| + | (附)列折叠 Flip useColumnFlip |
2 / 8 处 | components/ChatSidebar.tsx:80 · pages/GoalsPage.tsx:42 |
🟡 路径 B;其余 6 处未接线 |
| + | (附)环境层第 3 件「未确认段落墨度」lowConfidenceClass |
1(R12.4 要求 ≥2,差 1) | components/session-detail/SessionRawView.tsx:137 |
🔴 未达标(只登记、不补) |
| + | (附)[[ts:ms]] 端到端 |
只通一半 | 笔记侧已接 ms;会话页那一跳未交付 ⇒ 批 7 首要候选 | 🟡 |
| + | (附)E4 的后端契约面 | session_audio_path 已注册 |
registry 313 / 313 / 0 | ✅ |
🔻 T36 收口回写(2026-09-13,上表原文一字未改) —— 最终兑现度表(10 行)的落点 =
.superpowers/sdd/2026-09-12-frontend-redesign-batch6-motion/task-36-report.md(gitignored;本节不复制,避免第二份会漂的手抄副本)。
- 🔴 验收面 = 10 个(R64 #4 的更正:R0.1 正文写「9 个」而列举是 6 + 1 + 3 ⇒ 按 10 读;别处若仍写「9 项」按此加注读)。
- 🔴 上表是 T34 在冻结提交
975b3285上的中间读数;波 D 的 T35b / T35c / T35d 三个 comment-only 微单元改了app/**的注释行 ⇒ 四个行号在终态(7d6d677b)漂移 1–2 行,按终态读:#1 对齐views/session/SessionTriTrackView.tsx:251 → :253·#2 显影编排components/session-detail/SessionRawView.tsx:96 → :97·承载面③ 时间轨/播放头SessionTriTrackView.tsx:275 → :277·环境层第 3 件SessionRawView.tsx:137 → :138。其余行号由 T36 逐条复测不变(LiveBar.tsx:90·LiveBar.tsx:135·PhaseChrome.tsx:102·App.tsx:394·phaseSource.ts:84·TimeRail.tsx:140·TimeRail.tsx:220·ReviewPage.tsx:178·ReviewSessionPanel.tsx:98/:102·ChatSidebar.tsx:80·GoalsPage.tsx:42)。- 🔴 两处口径须并读(T36 点名的分叉):规格 §10 的批 6 收口行把 6 个签名动效写成「6/6 各有 ≥1 生产调用点、唯一缺口 = #2 的反向/重播入口 = 0」—— 该句只点 #2;#5 时间码回跳同样是部分交付(落位 + ≤8px 掠过已交付,长距离连续滑动补间未交付 ⇒ 见上表第 5 行与
task-31-report.md:137)。⇒ 两处并读:#2 的缺口是「入口 = 0」,#5 的缺口是「补间形态只交付一半」。均以 T36 的最终表为准(T35 §7-6 已声明「若分叉以 T36 为准」)。- 🔴 终态补记两条:①
--ed-dur-page今天 0 生产消费者(T35b 实测:全仓只有ui/tokens.css:89的定义与ui/tokens.gen.ts:114的生成物条目,零消费方;控制方引述错误第 7 例)⇒ 去向批 7/8 或删除(不发明消费者)。②docs/tech-debt/造成的docs-check差值已由 T36 直接测实:docs/**磁盘 280 个.md/ 入库 279 ⇒ 唯一未入库件 =docs/tech-debt/review-2026-09-11.md(191,980 B / 1555 行,未入库且未被 ignore)—— 这闭合了 T35c/T35d 记为「强推断」的那条归因。- 🔴 环境层 4 件的终态口径(R11.3「落 seam 不算已交付」):① 探针摆动 1(
ui/primitives/Loading.tsx:64)· ② 采集脉冲 1(shell/LiveBar.tsx:105)· ③ 未确认段落墨度 1 / 要求 ≥2 ⇒ 未达成(components/session-detail/SessionRawView.tsx:138;不得用 T13 的 seam 充数)· ④ 到期刻度微光 1(components/review/DueScale.tsx:120)。⚠️ 另:rich档的「幅度提高」未机械兑现(只兑现频率)⇒ 不得写成「三档全兑现」。
三条硬约束(R0.1 第 1 条)的判据与读数:① 规格 §3 就地加注 = 本批提交(E3/E4/E5 三行 + 四列齐备 + 回滚逐字)· ② ADR-035 单列「后端契约例外」节 = T2 建、T35 定稿回填(五项读数:313/313/0 · sidecar 键名 · aligned 语义 · MAX_GAP_MS = 10 min · cargo test 逐字)· ③ 🔴 cargo test --test app_lib_tests 本批真跑(不是「沿用基线读数」):running 2335 tests → test result: ok. 2329 passed; 0 failed; 6 ignored,exit 0。
八门禁终态(HEAD = 975b3285 · 真实构建产出 app/dist mtime 2026-09-13T05:10:24.838+08:00)
line-limits --full >600 0 · 301–600 档 122 · 登记条目 122(exit 0;零新增登记,对拍批 5 收口 Δ 0)· docs-check exit 0(扫描 280 / 检查 180,五项全 ✅)· registry 313/313/0 · tsc --noEmit 0 错 · vitest 221 文件 / 2132 用例 / 0 失败 / 0 skip(一次通过、零 flake;testResults.length 221;对拍批 5 的 184 / 1770 ⇒ +37 文件 / +362 用例;check-bundle-budget.mjs(真实构建,取 tmp/t34/build.lock,attempt=1、finally 释放、事后锁不存在)exit 0 · 首屏 103.60 kB gzip(原始 326,681 B;余量 96.40 kB;CSS 4 个 68,778 B / 15.62 kB gzip 不计入判据、只报告)· bundle-eager-graph 103 文件(源 89 + CSS 14)/ npm 包 7(结论口径 = TS-API 真实边:75 源 / 4 包)· 🔴 cargo test --test app_lib_tests 真跑 2329 / 0 / 6(exit 0) · cargo clippy --all-targets:error 0 · lib warnings 15 = 基线。
首屏账 / CSS 账 / eager 账(Δ + 机理;基线 = 批 5 收口 b4edf8e4 的真实构建)
- 首屏三件套:gzip 100,485 → 103,603 B = 100.49 → 103.60 kB(+3,118 B / +3.10%);原始 318,299 → 326,681 B(+8,382 B / +2.63%),其中 +8,382 B 全部落在入口 chunk(
index-Bn5oI23G.js108,620 →index-CBZzLV5U.js117,002 B);首屏 chunk 数 3 → 3(Δ 0,构造性成立);vendor-react/vendor-tauri逐字节不变(192,536 / 17,143 B);预算余量 99.52 → 96.40 kB(−3.12 kB)。⚠️ 仪器陷阱(本次新踩,登记):check-bundle-budget的 JSON 里firstScreen.totalBytes装的是 gzip 合计、不是原始字节 ⇒ 原始字节必须自己从chunks[].bytes求和。 - eager 账(结论口径唯一,R63.3 钉死):TS-API 真实边 66 → 75 源文件(+9)· npm 包 4 → 4(Δ 0);工具口径 91 → 103 文件 / 4 → 7 包只作旁证(2 个纯类型边
gsap/@gsap/react+ 1 个注释字面量假命中views)。新进首屏 = 9 个(逐条):components/Waveform.tsx·motion/intensity.ts·motion/tone.ts·shell/LiveBar.tsx·shell/PhaseChrome.tsx·shell/phaseSource.ts·shell/shellPhase.ts·shell/usePhaseFreeze.ts·utils/fmt.ts;REMOVED = 0 ⇒ 没有一个页面或视图被静态拉回首屏(pages/**新增 0 个)。 vendor-gsap的 V4 成立(真实产物上真跑):app/dist/assets/vendor-gsap-BQLVn3Z6.js存在(105,584 B) 且firstScreen.chunks = [index-CBZzLV5U.js, vendor-react-lr0dg1MX.js, vendor-tauri-UIF4jgRy.js]不含它;engine.guard.test.ts在本次构建后的 dist 上复跑 11/11 passed(exit 0)。- CSS 账(不计入预算,只报告):文件 3 → 4 个、原始 63,229 → 68,778 B(+5,549)、gzip 14,508 → 15,623 B。归因必须含 T12 / T13 / T19 / T29(不止 T5/T6),逐源文件:
ui/primitives/motion.css74 → 335(T5 token 迁移 + T6 档位块 + T12 响应层 +113 + T13 环境层 + T19 相位块 + T29 相变凝固)·ui/primitives/Text.css46 → 66 ·ui/primitives/Button.css92 → 100 ·shell/TopBar.css142 → 149 ·ui/tokens.css(生成物)100 → 119 · 新增 2 个懒 CSS:views/session/TimeRail.css78 ·views/session/TriTrackAlign.css20(合起来即懒 CSSSessionTriTrackView-LATzHimF.css772 B)。首屏 CSS 的 +4,777 B 可完整归因到前五个文件(motion.css经ui/primitives/index.tsbarrel 进首屏);bundle-eager-graph的 CSS 计数 Δ = 0(14 → 14)。 - 懒侧账(不计入预算,只报告):chunk 31 → 36(+5)、原始 +354,344 B、gzip 583.98 → 698.86 kB(+114.88 kB);94.1% / 92.0% 来自两块 ——
vendor-katex+227,858 B(内容哈希变DhXGx0Ak→CLrGOHeO)+ 新块vendor-gsap+105,584 B;其余具名:SessionTriTrackView+7,811 ·ReviewPage+6,878 ·SessionsPage+3,369 ·registry−658 · 新小块 ≈ +9,800;余 ≈ 3,400 B 未逐块闭合(诚实登记:chunk 名不是稳定标识)。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
§3 红线 6 → 新增第三处例外 E3 / E4 / E5(「两处」按加注读作「三处」;四列齐备 + 回滚逐字 + cargo test 真跑读数) |
规格 §3 表后整块加注 |
§4.3 条件③(审校模式)仍未实现 + ink-4 保持 0 生产调用点 + 环境层第 ③ 件的落点是 lowConfidenceClass(不是 ink-4)且只有 1 处(要求 ≥2) |
规格 §4.3 表后加注 |
§5 的 42 文件表已完成「三副本同步」(规格 §5 / ADR-033 §1 / 豁免表人工块;逐值 HEAD 实测 + 19 项漂移逐条 + 登记「line-count-src 锚点全仓 0 个读者」) |
规格 §5 加注 + ADR-033 §1 加注 + line-limit-exemptions.md |
| §6.2「采集态整列隐藏」vs §6.3「源列保留(采集配置面)」的内部矛盾(R40.1:两处原文保留 + 就地加注消歧;本批未实现列隐藏,两个口径按加注并存) | 规格 §6.2 + §6.3 两处加注 |
§6.2 pinnable 的消费方仍为 0(本批 Flip 走路径 B、未接线消费) |
规格 §6.2 加注 |
§6.3 实现面回填:三态通道 + 58px token + LIVE 仪表链路(1/1/1)+ 复习态零 chrome 走相位 CSS + 相位块块序 191 < 210 < 260 + navHeight.consumption.test.ts 零改动仍绿 |
规格 §6.3 加注 |
§8.1–§8.7 实现面回填(引擎与双实例陷阱 · token 真源 · 三档 + 源序机理更正 · 6 个签名动效逐条兑现度表 · maxDiff ≈ 0.409 @ x=0.40 · Flip 的 layout 属性冲突 · [[ts:ms]] 只通一半) |
规格 §8 表后整块加注 |
| §10 批 6 行 → 新增「↳ 批 6 的收口」行(✅ + 验收面逐条实际结果 + 八门禁终态 + 「60fps 未测」) | 规格 §10 表 |
| §11-5 / §11-9 / §11-10 / §11-11 四条进度注(机器判据落点 + 首屏与懒侧账 + 四行判据 + 八门禁终态 + 6 个 flake 名单 + 「并行窗口偶发红是一类现象」) | 规格 §11 四处加注 |
§12「登记不排期」四项的被做数 = 0 的自证 + 本批 10 条新增登记项(aligned 残余 D3–D6 · 导入会话音频 · 跨窗口同步 · 孤儿 sidecar · Flip 与 R8.4 冲突 · ADR-019 缺号 · docs/tech-debt/ · 懒侧无门禁 + KaTeX 二份副本 · [[ts:ms]] 会话页那一跳 · hook 无 unmount 清理) |
规格 §12 加注 |
§14 :836「docs/standards/ 新增动效规范章节」的批次归属(本批已做;v0.22:35 的「批 8」按加注读)+ ADR-035 已写 + ADR-019 缺号不补 |
规格 §14 加注 + v0.22.md:35 就地加注 |
ADR-035 定稿:例外节五项读数回填 · 决策 2 快照注释(白名单)与决策 3(闭包交集)两种口径 · 决策 5 的源序机理更正(!important 是承重机理、源序 = 防御性钦定)+ 块序硬事实 · 合规性验证 18 行终态 + 末行「挂账 → 定稿」的语义翻转 · 登记节补批 6 新增项 + 波 D 标签清扫清单 |
ADR-035 就地加注(T2 已冻结正文只加注、不重写) |
motion.md 收口:↔ ADR-035 反向引用(R14.3,此前单向)· rich 档兑现口径(频率兑现 / 幅度上限不动,理由改写)· controls.ts 的适用面(R41.3 经 R61 重述)· getChildren() 的递归口径(默认 = 2)· 「不可用判据」九项的本批读数表 |
docs/standards/motion.md 就地加注 |
docs/adr/README.md 状态列措辞(「波 A 落地」→「波 A 进行中」+ 收口口径)· 例外节位置体例只加注不移动(R14.7 #4) |
docs/adr/README.md 加注 |
ADR-013 复核 + 最终读数补进(WAV 对齐节的 TODO 结清 · MAX_GAP_MS = 10 min · sidecar 键冻结 · cargo test 真跑 · 「不得声称播放已可用 / seek 已验证」) |
ADR-013 新增「批 6 收口复核」节 |
计划两处口径更正(:584 表的 V2 与 Task 11 Step 2 ① 的 getChildren().length === 1 ⇒ 默认递归正确值 = 2)· T8 诚实边界的「微小曲线差」量化加注(maxDiff ≈ 0.409 @ x=0.40,接受 ≠ 可两路横跳)· T15 变异设计表的两处更正(G-1 代守名单 · G-3 目标路径) |
批 6 计划 :586 / :884 / :1009 / :1220 四处加注 |
过程中纠正的计划错误(逐条带读数与出处)
① T3:计划在 .ts 文件里写 JSX ⇒ 不可编译(9 条 tsc 错误 TS1005/TS1161)⇒ 改用 createElement(仓内既有 7 处 .ts React 测试范式)· ② T6:计划 V5 的「jsdom 下」与 Files 表的「node 环境」矛盾 ⇒ 采纳 Files 表(intensity.test.ts 不写 jsdom 头),连带硬要求 T7 补 jsdom 判据 · ③ T8:计划表 5 遗漏 style-seams:188 的同族断言(T8 STOP 请裁 ⇒ 追认;T8 的做法是「先 STOP 不擅改未授权断言」的正面实例)· ④ T12:计划 eco { transform: none } 与 Files/V2 矛盾(档位块不得新增私有 --ed-* 且不得反转无障碍优先级)· ⑤ T12:Files 表 vs V2 的门禁口径矛盾 · ⑥ T13 / T16 的预期值过期(T16 计划预期 style-seams 288 / motion-coverage 147,实测 299 / 186)—— 同族三条:T19 的预算过期(计划给相位块 ≤+40 行,实测 +42 ⇒ motion.css 275 → 317,越过 R11.8 的 ≤300 自律线;.css 不在门禁视野故不阻塞)· T23 的读数更正(R5.5-b 写 audio_store.rs「213 行」实测 212;recon-a A2 的「全仓 58px 0 命中」在本计划者仪器下是 2 命中 —— 两处都是 SelectionActionMenu.test.tsx 的 258px 子串 ⇒ 生产代码仍 0 处裸 58px)· T16 的关口读数(人工块二次刷新的范围由「1 条」更正为「2 条」,见 R63.2)· ⑦ T20:计划 V2 在单测里调 review_card 不可执行(tauri 2.11.5 的 State<'r,T> 字段私有、无 From<&T>、未开 test feature ⇒ 全仓 tauri::test 0 命中)⇒ 按仓内 inner 约定搬进 review_card_inner · ⑧ T20:控制方的「零新增文件」与计划自身的兜底互斥(R17.2 的派发错误)· ⑨ T4:V1 的「两半互证」不成立 + ③ 无法单独成立 · ⑩ T14:计划 G1 的新断言原文有假红洞****(/\d+\s*ms|…s/ 会把 var(--ed-dur-micro, 120ms) 判成裸值)—— 改用 withoutTokenVars 先剥,双向变异证明 · ⑪ T18:计划的 aria-pressed 不可满足 / Step 5 不可交付 / M2 预测为假(App.tsx 596/600 + ClassroomCapturePanel.tsx 298/300 ⇒ 无生产调用点;LiveBar 的挂载并入 T19)· ⑫ T21:计划 Step 3 自相矛盾(点名 scopeDue 而文案取 totalDue ⇒ 选组过滤时分叉;T21 未擅改既有文案 = 正确)· ⑬ T22:计划的跨任务互证不成立 · ⑭ T23:V1 冗余项 + timestamp_ms 是块末**(不是块首)** · ⑮ T24:计划的注册表类型落点不可行 + V3 的顺序探针 · ⑯ T26:V1 不可满足 · ⑰ T27:计划的 Files 表未列 TriTrackAlign.css · ⑱ T28:V5 与 V7 自相矛盾、且 V7 对 inline 元素无效(段正文是 <span> ⇒ transform 无效 ⇒ 「显影必须挂段落行」;这是本批最有价值的实测之一:一个在 jsdom 里全绿、在浏览器里完全看不见的判据形态)· ⑲ T29:计划 V3 的源序改判(相位块必须在档位块之前)· ⑳ T30 V6 / T31 M7 是等价变异体(诊断后换体才红)· ㉑ T32:无计划错误(唯一一条)· ㉒ T33:计划 Files 表写 useColumnFlip.test.ts,而该文件必须渲染组件 ⇒ .ts 装不下 JSX(同 ① 一类)· ㉓ R55.5 的两条计划缺陷(V1 空真 · V9 的「1770 用例」已过期)· ㉔ R58.3:useColumnFlip.test.ts 同类缺陷(= ㉒) · ㉕ 波 A 的 G-1 变异预测为假(批 5 D 表 :1772 与批 6 计划 :1214;代守名单更正为 A4① + A4② + G1①③ / G2① / G4)· ㉖ G-3 的变异目标路径不存在(计划点名 views/session/SessionRawView.tsx,T15 代以 SessionProofView)· ㉗ T15/T16 的守卫自证缺口(4 条) 与 T15 的「F9 无测试级牙」(只由命令级零 diff 代守)· ㉘ T11 的 V1 M1 期望在 paused 下不成立 + V2 的 M2 归因不成立(paused 上绝对 seek 与方向无关 ⇒ 拆成 V2a/V2b/V2c)· ㉙ 🔴 控制方的 3 处引述错误:(a) motion.md 的 === 1(motion.md 全 4 版扫 === 1 命中 0,该字面只在计划 :580/:1009)· (b) 追加 C 的前提为假(motion.md 从无「微小曲线差」措辞,且 :85 是规格 §8.3 的逐字表行、不许改)· (c) R29.2 的「12/12」实测为 6/6(以实测为准)· ㉚ 🔴 控制方的 2 处派发错误:(a) R17.2 的「零新增文件」过紧约束(与计划兜底互斥)· (b) R33.2 的 T16 派发早于依赖落定(motion.css / Text.css / motion-coverage.test.ts 当时仍在飞 ⇒ T16 登记的是工作树口径;二次刷新并入 T35)· 另控制方 1 处裁决错误:R12.1 判「取 ed-text--low-confidence ⇒ 零既有断言改动」漏了 structuredBlocks.test.ts:84(它是改类的必要连带)⇒ 追认为 G19 授权 · ㉛ 🔴 T13 面:M8b 的假读数归因更正(R42.2 ②) —— M8b 的真拦截者是「期望比对」,ran 下降只是旁证(原归因把旁证当主证)⇒ 计入判据纪律:ran 闸只证「跑起来了」、不证「拦下来了」(同族先例:批 4 #30 的 --cache.dir · T20 的过滤器拼错 · T89 的 git archive 取不到未跟踪文件 ⇒ 三次「被 ran 闸拦下」都是流程证据,不是判据证据)。
诚实代价(不许省略)
- 🔴 真实 60fps 未测(jsdom 无合成器;rAF ≈ 39fps)⇒ 代理判据 = 未动 layout 属性;不得出现「60fps 已达成」类表述。
- 🔴 Flip 的几何位移 jsdom 零可观测(
bounds全 0、位移增量恒translate3d(0px,0px,0px))· 真实媒体播放 / seek 不可验证(不得声称「播放已可用 / seek 已验证」)·window级滚动不可用(判据收敛到元素级)· 真机 / WebView2 观感未测(用户已裁决跳过)· 像素面全部未测(真的直线 / 真的 0.72 / 真的 220ms 淡入 / 真的 58px 零 chrome)。 - 🔴 相变两态 = 「文字面 + 结构面已交付、像素面未测」(不得笼统声称「相变两态已交付」)。
- 🔴 「对齐」的「错位语义」是控制方 R5.1 的定义(规格只给一句、代码无对应物)⇒ 用户可否决(R5.1 逐字)。
- 🔴 六个负载敏感 flake 名单(本批登记;判据 = 单跑复绿 + 提交树全量绿):
components/KnowledgeGraphView.test.tsx·components/notes/NotesReadingColumn.views.test.tsx·components/ChatSaveNoteDialog.test.tsx·views/registryResolution.test.ts·components/KnowledgeSampleView.test.tsx(第 6 个候选) ·ffmpeg::tests::run_captured_handles_large_output;⚠️ 「并行窗口内的全量偶发红」是一类现象、不是固定名单(另有 3 个不在名单内的瞬时红)⇒ 全量 vitest 必须在无并发单元时跑。 - 🔴
[[ts:ms]]的芯片在修之前是死的(回链整条不可达)—— T26 修掉了这个真实缺陷(NoteMarkdown一半);NotePreviewView+utils/html.ts:32的另一半未修(批 7 候选)· 定位精度残余 = 块粒度 ±200 ms(写块周期 200 ms)。 - 🔴
katex@0.18.4的第二份副本进产物(T28 让structuredBlocks.ts首次进图)⇒ +227,858 B 原始 / +64,497 gzip,而懒侧今天没有任何预算门禁 ⇒ 登记两条批 7/8 候选:「把lowConfidenceClass析出轻模块」+「懒侧字节纳入门禁」。 - 行数 / 结构代价:
App.tsx599 / 600(余 1) ⇒ 任何后续任务不许动它(硬边)·motion.css335 行(6 次追加,越过 R11.8 的 ≤300 自律线;.css不在门禁SOURCE_EXT视野内)·style-seams.test.ts299 ·views/session/SessionTriTrackView.tsx295 ·shell/TopBar.test.tsx298(余 ≤5 的共 22 个文件,T34 §9 列全)。- 🔻 T36 回写(2026-09-13,上面这句原文一字未改):
views/session/SessionTriTrackView.tsx的 295 是 T34 的冻结读数;T35d(7d6d677b)为把「长列表的滚动/密度手感见批 6」这句悬空承诺改成如实未交付而净 +2 ⇒ 终态 = 297 / 300(余 3)(同提交motion/engine.ts75 → 80)。T36 在终态(7d6d677b)逐条复测:App.tsx599 ✅ ·motion.css335 ✅ ·style-seams.test.ts299 ✅ ·shell/TopBar.test.tsx298 ✅(口径 =countLines());余 ≤5 的成员集不变 = 上列 22 个(app/src572 个文件中 295–300 行者 23 个,去掉 T34 口径排除的ui/primitives/dialogMigration.e.test.ts300 后仍是 22)。
- 🔻 T36 回写(2026-09-13,上面这句原文一字未改):
- 流程代价:每次真实构建都要人工取锁(
check-bundle-budget.mjs无锁机制;取锁协议是人工约定)·docs/tech-debt/(191,980 B)全程占着git status(唯一脏项,待用户裁决)· 1 条新 IPC 与 3 项后端只读改动(live_session*.rs触发 AGENTS.md §10 额外审查记录)。
未做(登记,逐条带归属批次)
docs/product/ui-ux-system.md / theme.md 的四层动效 / 三档强度回写 → 批 8(§14 逐字仍留批 8;本节「规格漂移纠正」只做消歧)· ink-4 接线 / 「审校模式」 → 批 7/8 · Text 字号越界 551 处 / 120 文件 → 批 8(本批只保证新代码不新增)· 暗档 data-theme 接线 → 批 7/8 · 跨窗口档位 / 相位同步 → 批 7/8 · 导入会话的音频承载面 → 产品裁决 · 删会话不删音频 + 孤儿 sidecar → 产品裁决 · aligned 残余 D3–D6 → 批 7/8 · [[ts:ms]] 的会话页那一跳 → 批 7 首要候选(T26 的逐行成本与 patch 落点保留在 task-26-report.md)· lowConfidenceClass 析出轻模块 + 懒侧字节门禁 → 批 7/8 · 波 D 的一次性「标签清扫」(comment-only;涉及 app/** 源码注释 ⇒ 属生产代码面,本批只登记:已过期 4 处 + kbCommands.ts:15 的 312/312 + tokens.gen.ts:83-85 的「0 生产消费者」+ tone.test.ts:23 的「data-tone 0 命中」· 前向引用 4 处 · engine.guard.test.ts ① 的假 console.warn · controls.ts 的过宽措辞)→ 下一个动效 / 治理单元 · 五类棘轮余量 + FROZEN_NUMERIC_ZINDEX + bundle-eager-graph 的 import type 口径 → 批 5/7/8(照原表)· ADR-019 缺号 → 只登记、不补 · docs/tech-debt/ → 用户裁决 · Flip 的 width/height 与属性集合判据的冲突 → 批 7/8 与判据纪律 · hook 无 unmount 清理(时间线在卸载后仍存活)→ 批 7/8 · 真机 / WebView2 验收 → 批 8(不得出现「已真机确认」类表述)。
🔻 T36 回写(2026-09-13,上面这一整段原文一字未改) —— 两处已在本批内关闭,不再是「未做」:
- 🔴 「波 D 的一次性标签清扫」已执行:T35b
9c1f615c(6 文件 / +36 −22)+ T35c04dc9de2(8 文件 / +38 −18)+ T35d7d6d677b(2 文件 / +10 −3)= 16 个app/**文件 / 合计 +84 −43(实测git diff --shortstat 975b3285..HEAD -- app/),上面逐条点名的源码注释项全部封闭(含kbCommands.ts:15的 312/312 → 313/313/0 ·tokens.gen.ts:83-85的「0 生产消费者」→card6 /reveal7 ·tone.test.ts:23→ 4 处data-tone·engine.guard.test.ts的假 warn(用例名 +console.warn两段)·controls.ts的过宽措辞)。🔴 唯一未改 = R66.3 #3 判为「不算说谎」的两处测试名(components/session-detail/useRevealChoreography.test.tsx:283·views/session/useTriTrackAlign.test.tsx:279)⇒ 只登记。⇒ 本条去向随之收敛为「下一个动效 / 治理单元」仅指那两处测试名。- 🔴
--ed-dur-page= 0 生产消费者(T35b 实测)⇒ 去向批 7/8 或删除(控制方引述错误第 7 例;T36 独立复现同读数)。
提交清单(77 个,ac504b06^..975b3285;归组依据 = 逐提交 git show --name-only 的改动面 + subject,探针 tmp/t35/commits.mjs)
| 归属 | 提交数 | sha(按时间序) |
|---|---|---|
批计划(docs(plan)) |
1 | ac504b06 |
| T1 动效规范(+1 微单元:评审三条 Important) | 2 | bffed928 · b508c5e5 |
T2 ADR-035 + 索引 |
1 | 97295d64 |
| T3 装 GSAP + 唯一入口(+4 微单元:引擎头注/转出口径三条) | 5 | 864f4881 · ae868f71 · d2eacd2d · 5ecfe1f7 · a9cf152a |
| T4 懒加载三件套守卫 | 1 | 34fb857b |
T5 token 真源迁移 + pill(+1 微单元) |
3 | 2ebac5ed · 0042ecfa · 92d83623 |
| T6 三档强度通道 + 源序守卫(+1 微单元) | 2 | eb55386e · c9f89692 |
| T7 动效强度控件 | 1 | 3978e2b9 |
| T8 双基调(+1 微单元:量化曲线差) | 2 | fef4a8d8 · b0ab516b |
| T9 位移上限唯一出口(+3 微单元) | 4 | 4d60663b · dd48d933 · 1935dd2c · 17a8b8c3 |
| T10 确定性底座(+1 微单元) | 2 | 869b9f08 · 9508c5dd |
| T11 可中断出口(+1 微单元) | 2 | a53fb506 · 6d10a2db |
| T12 响应层七类回执(+4 微单元) | 6 | 2071ec7a · e531a0cb · 488cb534 · 8f6031bc · 9e94d941 · 32effc92 |
| T13 环境层四件(+T13b 的 5 处小修) | 2 | d5b7b646 · 5467a91c |
| T14 G1/G2/G3/G6 改判(+T14b/T14c 微单元) | 7 | 4c422e05 · 00fafb7c · e3719d03 · a50a3449 · 348f8a81 · 4dc32808 · 19a2a953 |
| T15 G-1..G-4 补测(证据型、零提交) | 0 | (全在 gitignored 报告与 tmp/t15/**) |
| T16 文档就地更正(三处) | 1 | 129b819c |
| T17 相变态通道 + 58px token | 2 | 0840fe44 · b1534d3d |
| T18 LIVE 仪表(+1 微单元) | 3 | b2afd6d8 · 25a4a2e5 · 1a50d2ba |
| T19 复习态零 chrome(+1 微单元) | 2 | 0772d1a7 · 1cc35346 |
T20 intervalDays(+T20b 拆行映射域) |
2 | 89972482 · 6268f34d |
| T21 到期刻度视觉 | 1 | 56303c61 |
T22 session_audio_path(312 → 313) |
1 | 5b881dec |
| T23 WAV 轴 ≡ 会话轴 | 2 | 375e5058 · 911b6190 |
| T24 注入槽 + 取数钩子 | 2 | 7c1899ee · 99ac683e |
| T25 时间轨 + 播放头(+1 微单元 + 台账刷新) | 3 | 103703e6 · 9d3dfa5c · 0ea19a78 |
T26 [[ts:ms]] 接 ms(+1 微单元) |
2 | 4cd9d23d · 3f99d52f |
| T27 #1 对齐 | 2 | c0ce9933 · 0bdad6dc |
| T28 #2 显影编排 | 3 | c518238a · 160d5936 · 975b3285 |
| T29 #3 相变凝固(+台账刷新) | 3 | d90b89d2 · 17e96fe1 · 7d63a1bf |
| T30 #4 刻度生长 | 1 | 66f0e4a9 |
| T31 #5 时间码回跳 | 1 | 48e453e4 |
| T32 #6 记忆浮现 | 1 | 51f60191 |
| T33 列折叠 Flip(路径 B) | 4 | dfcbd496 · c003d739 · 0ee1d0e0 · 3277ebad |
| T34 终态测量(零提交,只产读数包与报告) | 0 | (tmp/t34/** + task-34-report.md) |
| 合计 | 77 | —— |
注:
⚠️ 微单元的归属按「改动面」判定(例如17e96fe1 chore(line-limits)删的是usePhaseFreeze.test.tsx的登记行 ⇒ 归 T29;5467a91c改的是responseSeams.test.ts的缓动名与!important口径 ⇒ 归 T13b 的 5 处小修)。🔴 权威的逐任务提交轨迹由 T36 的收口评审给出(批 6 计划 §收口回写 §3);本表不含 T35 本节所在的提交与 T36 的后续提交(自引用)。
🔻 T36 的归组对拍(2026-09-13,独立复核;上表原文一字未改) —— T35 §7-5 把「77 条提交的任务归组」列为未能验证,R64.2 #3 判「权威轨迹留 T36」;T36 用
git log --pretty=format:%h%x09%s逐条对拍,结论 = 上表成立:
- 🔴 区间与计数:上表 77 的区间是
ac504b06^..975b3285(只到冻结提交);批 6 的终态提交数 = 84(实测git rev-list --count ac504b06^..HEAD= 84)= 上表 77 + T35 的 4 个(b3f2181f·323acb58·c7ef9ca4·e719894f)+ T35b / T35c / T35d 各 1 个(9c1f615c·04dc9de2·7d6d677b)。T36 本节自身的提交不计入(自引用)。- ✅ 0 个幻影 sha:上表 77 个 sha 逐条存在于
git log(git log --pretty=format:%h 6cbe964e..HEAD的 84 条里 77 命中、0 缺失)· 36 行的「提交数」格与并列 sha 数逐行相等(mismatches = 0) · 微单元归属抽查 8 条(17e96fe1→ T29 ·5467a91c→ T13b ·160d5936→ T28 ·1cc35346→ T19 ·92d83623→ T5 ·32effc92→ T12 ·0ea19a78→ T25 ·7d63a1bf→ T29)逐条与--numstat的改动面一致。⚠️ 唯一一类差异(不是归属错误):9 个父任务报告从不引用自己的微单元提交(T1b508c5e5· T35ecfe1f7/a9cf152a· T6c9f89692· T8b0ab516b· T9dd48d933/1935dd2c/17a8b8c3· T109508c5dd· T116d10a2db· T1232effc92· T14a50a3449/4dc32808/19a2a953· T206268f34d)—— 它们的旧/新原文记录在兄弟报告里(task-1-fix/task-6b/task-8b/task-9b/task-13b/task-14b/task-14c/task-20b)。⇒ 归组本身无需更正;读者须知「任务 = 报告集合」而不是「任务 = 单个报告」(T36 逐条差异表见task-36-report.md§3.3)。
提交数口径(本文档既定规矩:一律「含左端点」
A^..B):批 7 的开工 HEAD =681e73c6(批 6 已收口并推送)⇒ T21 落库时git rev-list --count 681e73c6..f0f2998c= 59(= 计划勘误 4 + 7a 的 11 个任务 + 7b 的 T13–T20 + T21 的规格回写 1)。 🔴 这不是全批终态:T22(全批收口) 的提交、以及本节所在的提交均不计入(自引用)。全批终态读数与最终提交清单由 T22 出。 🔴 读数正本 =.superpowers/sdd/2026-09-12-frontend-redesign-batch7-unwired/(台账rulings.md§C0–§C54 ·progress.md· 各task-N-report.md),全部 gitignored。本节数字一律标明来源:凡未由 T21 亲测者,逐字写「引自 §Cxx / Txx 报告,未独立复核」。
交付
- 三条验收(规格 §10 行
:722时点锚 ⇒ 现 775):标签能写进去(T18)· 档位选完真生效(T19)·structuredBlocks已作出接线或删除的明确裁决(T3 删除 + T2 析出 + T20 加宽)。 - §1 L5 的四条规格义务:行 31 B 桶 3 条撤下 IPC 但保留内部函数(T4:
create_session/add_session_segment/add_session_ocr_block;摘属性 + 删注册条目,函数体逐字节保留、无*_inner改名)· 行 34 档位通道 A 做完整(T19:start_live_session第 5 参 tier +resolve_start_tier+ 预置profile_override槽 + 启动失败回滚 ·TierMemoryEntry+tier_entries(serde 缺省零迁移)· 新增remember_video_profile_tier(定义 + 注册成对) · 读端video_profile_for_spec为真源)· 行 35 标签线 A 补完(T18:NoteTagsEditor+ 写端三条命令各 ≥1 生产调用点 + 设色/清色成对 +tag_colors幂等回填)· 行 30 A 桶补 UI。 structuredBlocks的逐导出裁决(§C4.1 的明文授权,§C4.2 的硬条件):escapeHtml只摘:11import +:13再导出(真源utils/html.ts:11一个字不动)·renderLatex/renderMarkdownTable删(唯一消费者是它们自己的测试)·lowConfidenceClass留并析出到utils/lowConfidence.ts(32 行)+ 加宽到 ≥2 生产调用点(T20 兑现:SessionRawView.tsx+SessionTriTrackView.tsx;批 6 R12.4 环境层第 ③ 件的「≥2」欠账就此补齐)。- 🔴 用例净 −7 的说明(非 LOST):全量 vitest 用例数 2132 → 2125(T3 的提交树上复算),逐条归因 = 删
structuredBlocks.test.ts的 8 个it(renderLatex3 +renderMarkdownTable4 +lowConfidenceClass1)减 T3 自建的utils/lowConfidence.test.ts原样迁入 1 个it(内含 4 条expect) ⇒ 8 − 1 = 7。「LOST = 0 / SHRUNK = 0」的对拍纪律未被破坏(该 1 个it是搬家不是删除;T3 的授权出处 = §C9.19 +表 6b的 E-27)。此后 T7/T16/T17/T18/T19/T20 又各自新增用例(T21 未逐文件复算,以 T22 的逐文件对拍为准)。
- 🔴 用例净 −7 的说明(非 LOST):全量 vitest 用例数 2132 → 2125(T3 的提交树上复算),逐条归因 = 删
- markdown 归一(§12 的「3 套渲染器归一」,§C10.1 取代 §C9.15 的形态):新建
utils/markdownLine.ts(100 行:refineDiff.ts的mdLineHtml+NotePreviewView.tsx的renderMarkdown合成一支,两模式具名常量逐字保留原样式)·ChatMessageMarkdown并入NoteMarkdown后删除(react-markdown 站点 2 → 1 · 插件站点 8 → 4)· 终态 = 2 套活(NoteMarkdown+markdownLine)。🔴 禁止把两支手写链换成 react-markdown(它们是给dangerouslySetInnerHTML的串生成器,换 = 改 DOM 形态/样式/安全面)。 [[ts:ms]]深链闭合(批 6 的「只通一半」):T15 给串渲染链的芯片补data-ts-ms/data-ts-chip(utils/html.ts40 → 48)· T17 迁入markdownLine并接容器侧事件委托 + 给 React 链(noteMarkdownComponents.tsx)补同名 marker + 修App.tsx深链 ms 载体 +focusSeekMs四件齐(解构 / 转交 / 消费 / 复位)+ 深链到达后临时切三轨视图(禁止写视图记忆)。- 采集期逐段显影(批 6 登记转批 7):T6 先拆
LiveActivityPanel513 → 242(新件LiveTranscriptStream297 /LiveOcrPreview94,纯搬迁),T20 再拆TranscriptRow.tsx(167 → 挂动效后 201)并挂useRevealChoreography。 - 懒侧字节门禁(批 6 的「懒侧无门禁」欠账):T9 新建(
scripts/check-bundle-budget.mjs首屏 + 懒侧两个独立读数 ·scripts/lazyBudget.json冻结基线 · 逐族上限 + 清单等式 + 总量硬棘轮 + 64 B 容差),口径写死「--no-build的读数不可用于懒侧判据」。 - 规格两章(只交规格、不写实现):§7.4「笔记带证据三轨」(E1/E2/E3 改写 + 两个分母 + 无锚点四类 fixture + 精修前后两态契约)· §4.3 的「审校模式」定义(入口 / 作用域 / 退出 /
data-*形态)。两章正文均逐字含「本批只交规格,实现未做」。 - 补 UI 实做 10 条(§C9.1 逐字名单):
reset_tag_color(#19) ·update_note_tags(#25) ·video_profile_for_spec(#28) ·analyze_session_command(#34) ·delete_session_images_all(#37) ·finish_session(#39) ·get_decision(#40) ·refine_session(#42) ·set_tag_color(#45) ·update_knowledge_system(#47) —— 其中 4 条由 T18/T19 交付、6 条由 T20 交付(落点:SessionAnalysisPanel/GalleryBulkDelete/StaleSessionRecoveryBar/DecisionDetailPanel/SessionRefineSection/KnowledgeSystemEditPanel,判据件batch7UiWiring.test.tsx216 行)。🔻 收口更正(2026-09-13 · T21 追加轮;上一行原文一字未改)—— 实做面收口为 11 条:§C9.1 的「10 条」是计数口径,而逐个列名是 11 个名字 —— 计划
:2304已自陈「数一数是 11 个名字」、:2305裁决「按名字列全 11 个(不删任何一个)……不自行删减」。🔴 实测支撑(§C56.2 / §C57.4④):T20 交 6(其自记口径「6 + T18/T19 的 4 = 10」恰好吞掉了被删减的那一个名字)+ T23 补 1 + T18/T19 的 4 ⇒ 11 / 11 现已齐。- 11 条逐名:
reset_tag_color(#19) ·update_note_tags(#25) ·video_profile_for_spec(#28) ·analyze_session_command(#34) ·delete_session_images_all(#37) ·finish_session(#39) ·get_decision(#40) ·refine_session(#42) ·set_tag_color(#45) ·update_knowledge_system(#47) ·update_fragment_group(#46)(最后一条由 T23 交付:125eec85新件app/src/components/FragmentGroupAction.tsx+5f662811+5d59e332的 feed 地形返工;T21 独立复测 PROD 0 → 1)。 - 🔴 规格 §10 的「12」仍不改(那是规格原文、加注处理)⇒ 差额 =
kb_search(#14),它在批 3 Task 12 已交付(b567f0e6)。 ⚠️ 上行的batch7UiWiring.test.tsx216 行是 T21 首轮的读数;T23 两条提交后 T21 实测 = 218 行(该判据件的describe标题也随之从「六条命令」改为七条命令,T23 自查后落5f662811)。
- 11 条逐名:
验收(三条验收的兑现度 + T21 落库时的八闸读数)
| 验收(规格 §10 行) | 判据 | 兑现度 | 证据 |
|---|---|---|---|
| 标签能写进去 | 写端三条命令各 ≥1 生产调用点 + 关库重开端到端 | ✅ 成立 | T18 的 PROD 各 1(NoteTagsEditor.tsx)· R-10 三路独立仪器(含自建 harness 逐字搬入 db_colors.rs 复现「加标签 → 关库重开 → tags 仍在 → 设色 purple → 清色 None」)· T21 独立复测 PROD 各 1 |
| 档位选完真生效 | remember_video_profile_tier 写入 ⇒ 重新 load 仍是同档(机器代替品)+ start_live_session 五参兼容 |
✅ 成立(代理判据) | T19 的 tier_survives_reload_same_title + 负控 None · R-11 四段逐段实读(含消费端 live_profile_runtime.rs 与启动失败回滚)· T21 独立复测 video_profile_for_spec PROD 4 处 |
structuredBlocks 已作出明确裁决 |
逐导出裁决落地 + 规格 §10 行内授权逐字 | ✅ 成立 | T2/T3/T20 + T21 的规格 §10 加注(逐导出授权逐字) |
| + §11-8「跨会话记住」是否全路径成立 | —— | ✅ 全路径成立 | 🔴 原不成立:source_window == None 路径(未选窗口 / 全屏)用净化去重后的会话标题当记忆键,而前端此时传常量 "实时课堂" ⇒ 该路径必读不回(§C51.4 的 Important I1);已由 T19 的 17d33095 修复(新纯函数 memory_key_for_start:窗口标题优先、未选窗口取去重之前的标题;判据 none_window_path_tier_roundtrip_across_reload + 负控) |
三条验收的口径(必须并读,否则会误读成「已全部真机验证」):① 真机 / WebView2 冒烟由用户裁决跳过(§C6.4)⇒ 三条验收的「端到端」全部止于 jsdom / Rust 单测层;② 验收三的「明确裁决」是规格前置(§C9.10 逐字:写规格 + 裁决落库本身就是交付物形态);③ 「档位选完真生效」的「真生效」= 生效态(可经
live_session_status读回),不是「采样参数真被采集链路消费」的像素级证据。
🔻 §11-8「段① 的『落库』」口径逐字(§C44.2 / §C45.1;T21/T22 照抄):段① 的「落库」= 会话生效态 + 记忆体,非
sessions表落列。 依据:规格 §1 L5 行 34 的四段是「加 tier 参数 / 记忆加字段 / 新命令 / 读端接线」,没有一段要求sessions加列;验收「档位选完真生效」的实质 = 生效态(profile_override→ worker →applied_tier,可经live_session_status读回);「跨会话记住」由记忆体满足(tier_survives_reload_same_title+ 负控);改 schema 撞 AGENTS.md §10 且本批无此义务 ⇒ 属范围蔓延。
🔻 读端角色变更逐字(§C11.4;T21 已同批回写规格 §9 #30 行):
KIND_TO_FORM/KIND_TO_TIER的角色从「并行真源」变成「离线降级路径」(兜底) —— 它仍然存在、也仍有生产调用点(AGENTS.md §3.4 要求本地兜底路径必须留),不是被删除 ⇒ 当年删除video_profile_spec_by_kind的理由在"真源"这一层不再成立,在"兜底"这一层仍成立。
八闸(T21 落库时在工作树上串行实测;🔴 不是全批终态,终态由 T22 出)
line-limits --full exit 0「>600 硬限 0(棘轮内)· 301–600 档 121 · 登记条目 121」· docs-check exit 0(扫描 281 / 检查 181,五项全 ✅)· registry exit 0「定义 311 / 注册 311 / 重复 0」· 其余五闸本节不重跑(tsc / vitest / bundle-budget / bundle-eager-graph / cargo)—— T21 的写集只有 docs/**,对它们零影响;引用 T12/T20 的读数时必须标明来源与树(§C42.3 M-2/M-3 的纪律)。🔴 本批八闸的终态读数一律以 T22 为准。
🔻 批 7 终态回写(2026-09-13 · T21;上段三个读数原样保留为「T21 落库时」的时点读数) —— 全批收口件(gitignored)=
closing-review.md·task-22-report.md(T21 本轮实测 109,327 B / 693 行 与 41,469 B / 323 行;控制方 §C59.1 报的 94,256 B / 28,796 B 是更早的落盘时点值 ⇒ 🔴 两处读数都带时点)。① 第 ⑤ 闸(懒侧真构建**)的三个时点 —— 🔴 本批最有价值的一条读数**
时点 第 ⑤ 闸 读数 0a503cc8(T12 的 7a 段收口重冻)当时✅ 绿 limit 636,243 c0bff722(全批收口树)当时🔴 红(exit 1) 懒侧 637,501 B > 636,243 + 64 ⇒ 超 1,194 B;具名 3 条 = 未归族 lowConfidence-CbMOBOyG.js·KnowledgePage-28,466 > 27,620 ·NotesPage-48,627 > 48,08755f502fa(T22 重冻)之后✅ 绿 limit 637,501 · unlisted = []·fails = []· 逐族红 0 · 首屏 105.95 kBpass=true
- 🔴 T21 本轮逐字复核了两份日志:
tmp/t22/logs/g5-bundle-budget-realbuild.txt(totalBytes 637501/totalMaxBytes 636243/unlisted1 条 /fails4 条 /❌ 懒侧 gzip 预算超标(退出码 1))与tmp/t22/logs/refreeze/g5-realbuild-post-refreeze.txt(totalBytes=totalMaxBytes= 637501、unlisted: []/fails: []、各族pass: true)。- 🔴 加注台账 §C47.4 的那句「7a 正式收口:八闸全绿」:🔴 该句在批 7 终态已不成立(
c0bff722树上第 ⑤ 闸真构建红)⇒ 原文保留、本注为准;这是 T22 的诚实纠错(§C59.10 第 2 条,控制方采信),不是笔误。⇒ 引用一律写「7a 段收口当时绿;全批收口树曾红;重冻后绿」,不得只引「八闸全绿」。⚠️ §C47.4 的原文在 gitignored 的rulings.md(不在docs/**) ⇒ T21 无法就地加注(写集硬边界 = 只改docs/**)⇒ 本表即该句的 durable 更正(已在报告里点名)。② 懒侧基线的精确性质(T21 本轮读
scripts/lazyBudget.json逐值复核)
lazyTotalGzipBytesMax636,243 → 637,501(+1,258 B / +0.20%)·lazyChunkCountMax37 → 37(不变) · 族数 37 → 38(新增lowConfidence-= 100 B)·generatedFrom的真值:950afd5a(T12 重冻树) —— 谱系 =cd800d63(T9 批次中段) →950afd5a(T12) →c0bff722(T22)(原写90bb5f6a与提交顺序不符,已由 T22 修正)。- 🔴 闭合性质(T21 复核):各族实测之和 = 637,501 =
lazy.totalBytes=totalMaxBytes(逐字节相等 —— 重冻后日志里totalBytes与totalMaxBytes同为 637501);而Σ gzipBytesMax= 638,029(比总量高 528 B)=shift-族的 212 B 死预算(该族chunkCount = 0、实测 0、上限 212)+ 其它族保留的 316 B 正 slack。- 🔴 结论逐字:除 64 B 容差外零余量 ⇒ 不得读成「还有空间」;🔴
shift-的 212 B 死预算登记为批 8 清理项。vendor-*五族上限一字未动(canvas58,784 ·editor208,585 ·gsap41,161 ·katex79,915 ·md50,622;T21 逐值复核一致),实测 +2 / 0 / +1 / 0 / +1(全部落在 64 B 容差内)⇒ 非回潮(§C46.4 条件⑤ 的 STOP 未触发)。- 🔴 逐族上限的陈旧度披露(2026-09-13 · T21 补轮;独立全批复核提出、控制方独立复现、T21 逐族逐字节复算):重冻后的真构建读数(
tmp/t22/logs/refreeze/g5-realbuild-post-refreeze.json的lazyBudget.families)显示 —— 🔴 有 18 个族的实测已超各自上限,合计 +203 B:ActionPage-+25 ·AiConversationDock-+39 ·CaptureFloatPanel-+2 ·CaptureOverlayPanel-+2 ·ChatPage-+39 ·RefineLaunchDialog-+2 ·RefineStrategyPicker-+16 ·SessionCardFlowView-+5 ·SessionProofView-+2 ·SessionScreenCard-+3 ·SessionTriTrackView-+35 ·SettingsPage-+3 ·ViewSwitcher-+3 ·colorPalette-+2 ·registry-+21 ·vendor-canvas-+2 ·vendor-gsap-+1 ·vendor-md-+1。 · 🔴 性质:均在 64 B/族容差内 ⇒ 未判红(闸的判定是对的、终态仍是绿)—— 本条披露的是逐族上限对这 18 个族已经陈旧,🔴 不是「闸有问题」。 · 🔴 登记为批 8 的逐族重冻输入(按 §C32.3 的「同提交可登记重冻」;🔴 总量上限不得抬高)。⚠️ 其中含 3 个vendor-*族(canvas+2 /gsap+1 /md+1)⇒ 上一行的「五族上限一字未动」(非回潮)与本条的「实测已在其上限之上 1–2 B(容差内)」是两件事,两句都要读。③ 三条诚实纠错(逐条落账;🔴 全部归到计划卡 / 台账,不是实施者)
- 卡
V3的「LOST = 0」与「以开工基线为锚」不自洽(§C59.4):T3 的合法删除就在锚区间内,逐文件对拍必然计入 LOST ⇒ 🔴 正确表述 =LOST = 1(components/structuredBlocks.test.ts,T35cda5bdb经计划预授权的合法删除)·SHRUNK = 0· 「LOST = 0」应读作「无未归因的丢失」。用例对账:开工基线681e73c6221 文件 / 2132(passed 2129 / pending 3,与 §C6.2 逐字吻合)→ 终态 229 / 2225;净 +93 = 新增 9 文件 Σ81 + 增长 7 文件 Σ20。- 台账 cargo
2348 passedvs 实测2354 passed(差 +6)(§C59.10 第 3 条)⇒ 🔴 逐字保留「成因未判定」,不许猜。第 ⑧ 闸实测:2360 run / 2354 passed / 0 failed / 6 ignored(exit 0)。- 🔴 §C49.4 的「统一放宽
W1/W2/P1的 1 s 等待上限」⇒ 作废(N = 0)(§C59.5):T22 实测一个都没放宽 ⇒ 🔴 批 7 不声称放宽过任何等待上限;该项从批 7 待办移除,登记为批 8 输入(若批 8 仍要动,必须先补 T17 之前的对照证据)。④ 其余终态读数(T21 未独立复跑者逐条标明来源;§C42.3 M-2/M-3 的纪律)
- 第 ①②③ 闸在本轮由 T21 自己的提交前实测复核:
line-limits --full0(121/121) ·docs-check0(281/181) · registry 0(311/311/0) ⇒ 逐字一致。- 第 ④ 闸
bundle-eager-graph0(111 文件 / 7 包) · 第 ⑥ 闸tsc --noEmit0 · 第 ⑦ 闸 vitest 冷 1 / 热 1 / 第 3 次 0(229 文件 / 2225 用例,红集 = W1)· 第 ⑧ 闸 cargo 0(2360 / 2354 / 0 / 6) —— 引自 §C59.2 /task-22-report.md,T21 未独立复跑(需真构建与全量跑)。- 漂移红集(§C59.7):JS 5 成员(
SessionDetailPanelW1/W2 ·NoteReadingColumn.viewsF2 ·SessionViewHostH4b ·registryResolutionA1 ·KnowledgeGraphView)+ Rustffmpeg::…large_output(10 s 墙钟签名);🔴 只有 W1 三件齐(冷红 / 热红 / 第 3 次绿;红时该用例 1146 ms ≳ 1 s 上限、绿时 401–415 ms)⇒ 判负载敏感红;其余 5 个一律「未判定」;成员会漂移。⇒ 本节「诚实代价」里的红点集合段据此不变。- ✅
90bb5f6a(T19 的 U2 提交)补评:通过(§C59.8):「生效档 ≠ 本地映射档」构造成功(talking-head → 本地lowvs 后端记忆rich):CONTROL 8/8 绿 ⇒ 自造变异体 7/8 / exit 1 / 红在具名断言;DOM 逐字节复核 = 两处且仅两处声明差异成立 ⇒ T18–T23 无第三次漂移。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
§10 批 7 行:structuredBlocks 的「接线或删除二选一」由控制方按逐导出裁决(第三条路)执行 ⇒ 明文授权入规格 + 「12 条补 UI 实做 10 条」+ registry 净值 311 + 撤下 3 条的形态 |
规格 §10 批 7 行后整块加注 |
§11-7:registry 313 → 311 · 前端零引用 24 → 11(口径 + 仪器 + 正控 68 / 负控 0)· 差价分解 −10 / −3 · 新命令不计入 · 残留 update_fragment_group |
规格 §11-7 批 1 进度注后加注 |
§12「3 套 markdown 渲染器归一」的去向终态:已完成归一(markdownLine + ChatMessageMarkdown 并入)· 终态 2 套活 · 🔴 逐字「归一 = 逻辑归一;观感统一未做,归批 8」· 🔴 补登规格加注漏点(第 4 套活渲染器 NotePreviewView.tsx:40 renderMarkdown) |
规格 §12 批 5 加注后加注 |
§9 表内三处状态更正:#14 kb_search(批 3 已交付)· #30 video_profile_spec_by_kind(角色变更登记)· #46 update_fragment_group(记录同步批 1 已做;T21 实测「接线」那一半未做) |
规格 §9 表末(#47 行之后;块引用会截断表格 ⇒ 只能整表之后就地在注,注文逐条点名行号) |
§9「删除的通用影响面:仅 lib.rs 的 generate_handler!」:注册清单已搬到 app/src-tauri/src/app_commands.rs(批 0-C3),lib.rs 已无 generate_handler! |
规格 §9 该句后就地更正 |
贴边件清单(本批 10 条,见「诚实代价」)· 门禁盲区(末尾换行 / countLines 不可见)· pr-check.yml 的 paths-filter 缺口 + 懒侧守卫的执行者缺口 · 豁免表的「连带落库」机制记录 |
line-limit-exemptions.md + performance.md(各自就地加注) |
| 规格 §4.3 的「审校模式」定义 + §7.4「带证据三轨」规格章 | 规格 §4.3 / §7.4(T20 的 fb73e313) |
🔻 上表三条的收口更正(2026-09-13 · T21 追加轮;上表原文一字未改):
- §10 批 7 行:上表写的「实做 10 条」⇒ 🔴 收口为 11 条(口径见本节「交付」段的收口更正:§C9.1 的 10 是计数口径,逐个列名 11 个;T23 补完第 11 个)。规格原文的「12」仍不改(差额 =
kb_search,批 3 已交付)。- §11-7 行:前端零引用 24 → 11 ⇒ 🔴 收口为 24 → 10(口径不变:§9 那 47 条中仍在 registry 者 22 条里的前端生产零引用数;
update_fragment_group由 T23 接线后离开该集合)⇒ 有引用数 11 → 12;🔴 残留 1 条 → 残留 0 条。- §9 #46 行:上表写的「T21 实测「接线」那一半未做」⇒ ✅ 已在批 7 内由 T23 补做并交付(
125eec85+5f662811+5d59e332)。🔴 原读数保留为 T21 首轮的过程记录 —— 它促成了这次补做;处置由「批 8 输入」改为「已交付」(rulings.md§C56.2:这是批 7 的交付缺口,不是有意的延期)。落点形态与判据见规格 §9 表末该行的收口更正。
过程中纠正的计划错误(第 1–12 例,逐条带出处与落位)
口径:这是控制方对计划编制单元的错误计数(与「控制方自己的第 N 例」是两条序列,勿混)。第 7–11 例由 T12 落账(§C46.6),第 1–6 与第 12 例由 T21 落账(本节 + 规格加注)。计划自身的勘误表 = 计划文件
### 表 6b的 E-1–E-30。
① 行号锚系统性错误 + 一处不实归属(§C12;计划方第 1 例):### 表 6 的 X2/X3 行号锚错,且 X2 把自己的读数冒充成「与控制方实测一致」(不实归属)。根因 = 编制期仪器 tmp/plan-writer/sites.mjs 的 stripComments 整段删除块注释 ⇒ 打印的是「剥注释后行号」(T2 定位)⇒ 全计划判错锚 24 条(E-1–E-22 行号类 + E-25/E-26)。落位:E1 的全量重推(367559ff 等 4 个提交)· 表 6b E-1–E-30 · 该「不实归属」句已删。② 表 5 的 Y2 行判错(§C13.3;E-24):把 toastMigration.test.tsx:146 判为「不改」,而 durationMs={3500} 在 AiToast 定义体内 ⇒ 搬迁后必红。落位:表 6b E-24 + 计划改为勘误(保留原文 + 写真值)。③ T3 卡依赖不存在的产物(表 6b E-27;计划方第 3 例):卡要求「lowConfidenceClass 用例已由 T2 搬到 utils/lowConfidence.test.ts」,而 T2 卡没有该文件、T2 也(正确地)没建它 ⇒ 控制方授权 T3 自建。④ 把「改文件」与「补豁免表行数」拆给不同单元(§C14.1;E-28;计划方第 4 例):line-limits --full 的 (e) 是逐文件判据、husky 扫工作树 ⇒ 每个中间提交都必然撞钩子(T2 与 T8 各自独立撞上)⇒ 裁决:行数列改由「改文件的单元」同批更新 + --no-verify 条件式授权。⑤ T4 卡预测 3 条 allow(dead_code)(§C15.1;E-29;计划方第 5 例):实测 4 条(第 4 条是传递受害的私有 helper normalize_source)⇒ 只加 3 处会留 1 条新告警 ⇒ clippy 集合差异非空。⑥ 计划的提交纪律与 §C18.2 矛盾(progress.md:124;E-30;计划方第 6 例):原 :188 强制 git commit --only -- <paths>(正是 fa45caf1 连带落库事故的机理),且把 --no-verify 列进「禁止」清单、与同段的 §C14 条件式授权自相矛盾 ⇒ E1 返工 4292dee2。⑦ T6 的台账实为四处,卡里只点名三处(§C22.5;计划方第 7 例)⇒ 已令 T6 逐张棘轮表搬家。⑧ T13 新件预算写 ≤170、实测 273(§C33.4 I-1;计划方第 8 例)⇒ 低估 103。⑨ 计划 V2 的 <Surface data-foo="1"/> 在 TS 下不报错(§C35.4;计划方第 9 例):带连字符的属性被豁免 ⇒ 该变异体无牙,改用 bar / onClick(R-8 独立复现)。⑩ 表 5 的 Y8 前提不成立(§C38.3;计划方第 10 例):假定 utils/html.test.ts 的 5 条 renderTimestampAnchors 用例「必须改写」,T15 逐条实跑证明一条都不红 ⇒ 实际处置是纯加宽(比机械改写更好)。⑪ 计划给的「预授权文本」本身编译不过(§C39.3;计划方第 11 例):**393**/114 里的 **/ 含 */ ⇒ 在 TS 块注释里提前闭合注释(25:72: Expected ";" but found ";";T10 实际被 vitest 挡下一次)⇒ 立为陷阱 P22/P23。⑫ H7 的指针错(§C54.3;计划方第 12 例):计划把 H7 指向 docs/tech-debt/…,而该文件里 H7 字面 0 命中(对照非 0);原文在 docs/Foresight/ux-market-convention-audit.md:109 ⇒ T20 只做属于 get_decision 详情面的那一片,其余 5 项逐字登记批 8;未触发 STOP(按「锚不符」条款处置)。出处:rulings.md §C12 / §C13.3 / §C35.4 / §C15.1 / progress.md:124 / §C22.5 / §C33.4 / §C38.3 / §C39.3 / §C54.3。
🔻 补登计划方第 13 例(2026-09-13 · T21 追加轮;上段的第 1–12 例原文一字未改) —— ⑬ 计划写的 IPC 载荷键名与 Rust 真身不符(§C56.3;计划方第 13 例):计划
:2299与:532写的是invoke("update_fragment_group", { **id**, groupId }),而 Rust 真身(app/src-tauri/src/commands_fragments.rs:141-145)是update_fragment_group(state, **fragment_id**: i64, **group_id**: Option<i64>)⇒ Tauri 2 是 camelCase ⇒ 🔴 JS 侧必须是{ fragmentId, groupId }。先例:app/src/components/FeedFragmentList.tsx里既有的delete_fragment调用(同族形态)。⇒ 实际落库形态:FragmentGroupAction.tsx:92逐字invoke("update_fragment_group", { fragmentId, groupId: target })(T21 追加轮实测)。
- 🔴 教训(§C56.3 逐字):计划里凡出现 IPC 载荷的键名,都必须在计划期用「既有同族调用点」对拍一次 —— 本批第 11 例(
**393**/114编译不过)与第 13 例同属「计划文本自身没被编译 / 执行过」这一类。- ⇒ 口径更新:本段标题的「第 1–12 例」按本注读作 13 例(规格 §11-7 与本节其余处若仍写「12」,按本加注读)。
🔻 另登记一条「控制方序列」的教训(勿混入上段的计划方序列) —— 控制方派单缺陷(§C57.2;控制方引述/派单类错误在本批的第 14 例):
- 事实:控制方的派单措辞要求「复用同文件既有形态」,把
FeedFragmentList.tsx:109的同文件注释(「目标=笔记容器组(feed 地形是碎片容器——不是笔记去向)」)当作先例,指定候选组取containerGroups(container 地形)。🔴 那句是promote_fragment_to_note(升为笔记)的去向语义,与update_fragment_group(碎片归组)不是同一件事。- 由 T23 质疑并成立(它按派发书实现后自己提出:「
capture_fragment真实自动归入的是 feed 主题组(resolve_feed_topic_group)⇒ 是否改判 feed?」)⇒ 控制方取证后改判(Rust 侧决定性证据:commands_groups.rs:36的terrain文档注释 +:44的container/feed白名单 ⇒feed是一等公民地形;commands_fragments.rs:344-366的resolve_feed_topic_group显式写terrain: "feed")⇒ T23 以5d59e332返工。- 🔴 纪律(§C57.2 逐字):「复用同文件既有形态」这个派单措辞,必须附带「该形态服务于哪个流程」的说明 —— 同一文件里的两个流程可以有不同的语义前提;不附说明的「照它做」会把一个正确先例误用成错误先例。
⚠️ 「§C57.2 属控制方序列、不属计划方序列」这一点必须写明(上段的①②…⑬是计划编制单元的错误计数;本条是控制方派单的错误)⇒ 引用时不得把它写成「计划方第 14 例」。
诚实代价(不许省略)
-
🔴 真机 / WebView2 冒烟由用户裁决跳过(§C6.4)⇒ 像素 / 观感 / 手感类一律未测(归批 8)。不得出现「已真机确认」类表述。
-
🔴
[[ts:ms]]的残余以实测为准:串渲染链(NotePreviewView/RefineWorkbench)与 React 链(noteMarkdownComponents.tsx)两侧芯片均已可点(T17 落data-ts-ms+ 容器侧委托)⇒ §C10.2 期望的「RefineWorkbench侧不再算残余」成立;🔴 但两处页内 seek 未接(AiRefineCard/NoteAiDialog)—— 那是另一条线(工作台/对话框内部跳转),无任何批次登记 ⇒ §C49.3 判为范围蔓延,登记批 8。不得声称「[[ts:ms]]全链已通」。 -
🔴
structuredBlocks裁决的形态代价:删除三个死导出必然改SessionRawView.test.tsx/env.test.ts的既有断言 —— 授权出处 = §C4.3 的追认 + §C10.1 的预授权(清单外),每条都给了逐字 before/after 与「是删除导致的必需改动」的论证;未顺手放宽。用例净 −7 = 8 删 − 1 迁(非 LOST)。 -
🔴 归一的代价(§C11.1 逐字):归一 = 逻辑归一;观感统一未做,归批 8。 两条链的可见输出零变化(两模式逐字保留原样式;91/91 行级夹具 + 14/14 夹具逐字节对拍)—— 换来的代价是两套模式常量长期并存,不是「观感已统一」。
-
🔴 D 的六条展示面是「设计决定」而非裁决(§C54.6 逐字):T20 补齐的
analyze_session_command/delete_session_images_all/finish_session/get_decision/refine_session/update_knowledge_system六条命令的展示面形态(面板位置 / 布局 / 文案 / 交互)全部是实施者定的,规格只给了「重新分析」「批量删」「结束会话」这类意图 ⇒ T21/T22 不得把它写成"按规格实现";充分性由控制方判。 -
🔴
get_decision的审计 H7 = 只做了详情面那一片(§C11.7 / §C54.3):授权只读docs/tech-debt/review-2026-09-11.md取 H7 原文(只读,不是处置 —— 该文件是用户所有,§C7.3 的「不处置」不变);在那里H7字面 0 命中 ⇒ 真原文在docs/Foresight/ux-market-convention-audit.md:109;T20 只做属于get_decision详情面的那一项(「日志只读 ellipsis 无展开」),其余 5 项逐字登记为批 8 输入(只写「H7」+ 必要片段,未整段搬运审计原文入库)。 -
🔴 C7「重启后卡录制」的覆盖面(§C54.5⑤):本批未覆盖该命令的完整触发面 —— 其触发口径有偏离(该命令无心跳字段)⇒ 登记批 8,不得读成「C7 已完整接线」。
-
🔴 音频两条 = 待产品裁决(§C7.3,
v0.22:689逐字「产品裁决」):AudioStoragePanel的死 UI(AudioStoreConfig构造点全仓 10 处、无 JSON/env 通道 ⇒status.enabled恒 true)· 删会话不删音频(commands_session.rs与commands_session_delete.rs零 audio 引用)⇒ 不在批 7 实施,登记为「待产品裁决」,不留成无主事项。 -
🔴
docs/tech-debt/的归因(§C7.3 逐字):docs/tech-debt/(唯一成员review-2026-09-11.md,191,980 B)是用户所有的决定(git status --porcelain=?? docs/tech-debt/;git check-ignore -vexit 1 = 未被忽略)⇒ 批 7 不处置它、也不因此不开工;归档 / 删除 / 留着三条都改变用户的资料形态,不是控制方可以单方面处置的。⚠️ docs-check的 1 个差 = 它:工作树 281/181 ↔ 提交树/导出树 280/180(差额必须逐字归因到本文件,不得当成本批的缺陷)。本节不得声称「本文档由本批创建」。 -
🔴 懒侧门禁的余量很薄(§C47.3 逐字,必须进 T22):重冻后总量上限 == 实测值,只靠 +64 B 容差(本机两次独立真构建实测 0 B 漂移)⇒ 不得读成「还有 1.9 kB 空间」;且 🔴 本重冻是 §C46.4 明文授权的收口动作,不是守卫放宽(证据 =
vendor-*五族逐族零增长:canvas58,784 ·editor208,585 ·gsap41,161 ·katex79,915 ·md50,622,逐字节不变)。 -
🔴 本批 10 个贴边件(余量 ≤5)—— 任何后续编辑必须先拆件(T21 于落库时逐条
countLines()实测,10/10 与台账一致;§C26.5 + §C46.5② + §C49.5① + §C54.5①):文件 行数 / 上限 余量 app/src/ui/primitives/dialogMigration.e.test.ts300 / 300 0 scripts/check-bundle-budget.mjs300 / 300 0 app/src/hooks/useLiveCaptureControl.tsx300 / 300 0 app/src/components/notes/NotesReadingColumn.tsx300 / 300 0 app/src/views/session/SessionTriTrackView.tsx300 / 300 0 app/src/components/KnowledgeDetailPanel.tsx300 / 300 0 app/src/ui/primitives/textBaseline.ts299 / 300 1 app/src/ui/primitives/style-seams.test.ts299 / 300 1 app/src/ui/primitives/style-contract.test.ts298 / 300 2 app/src/ui/primitives/emptyStateRatchet.test.ts296 / 300 4 🔴 并且:
app/src/views/note/NotesReadingColumn.tsx不是真实路径 —— 实测路径 =app/src/components/notes/NotesReadingColumn.tsx(views/note/下无该文件)。rulings.md§C49.5① 与派发语均写错路径 ⇒ T21 于落库时就地更正,后续引用一律用components/notes/。 🔴 「恰 300(余 0)」的 6 个文件里,dialogMigration.e.test.ts与check-bundle-budget.mjs是本批之前/本批新建的判据件:加一行就红,且dialogMigration.e.test.ts的CROSS_LINE_34判据改不动(§C48.5② 的「潜在陷阱」)。 🔴 范围声明(2026-09-13 · T21 追加轮;§C55.3 的裁决)—— 上面那张表是「本批触碰过的件」,不是全树:它的取值范围 = 本批(T6/T7/T9/T16/T17/T18/T19/T20/T23)实际改过、且在改动当时余量 ≤5 的件 ∪ 两个判据件。🔴 它一律不得作为判据输入。- 🔴 全树机器扫描(唯一来源;口径
countLines(),域app/src/**/*.{ts,tsx}):T21 于追加轮重跑(T23 的三条提交已改动行数,故不抄上游读数)⇒ 共 579 个文件 · ≥300 = 35 条 · 295–299 = 21 条 · 合计 56 条。⚠️ 对拍上游(§C55.3 的 578 文件 / ≥300 = 35 / 295–299 = 20 / 合计 55):差 1 个文件 + 1 条 295–299,逐条归因 = T23 的两处改动 —— ① 新件app/src/components/FragmentGroupAction.tsx(155 行)⇒ 文件数 578 → 579;②app/src/components/FeedFragmentList.test.tsx由 297 长到 299(T23 的125eec85+ 再返工5d59e332)⇒ 295–299 档 20 → 21。≥300 档不变(35)。 - 🔴 逐字纪律(§C55.3):「手列清单一律不得作为判据输入;以全树脚本扫描为唯一来源」。上游那份手列清单已两次失真(前几轮转述为「10 条」),它漏掉的 45 条里有两个恰 300/300(余 0):
app/src/components/notes/NotesReadingColumn.views.test.tsx= 300(同时是漂移红集成员 F2)·app/src/components/KnowledgeDetailPanel.tsx= 300;另有 T20 本批新建的app/src/components/session-detail/useRevealChoreography.test.tsx= 298。⇒ 🔴 T22 必须给完整两张表(≥300 / 295–299,逐条路径 + 实测行数 + 是否本批新增或被改过),并逐字写「任何后续编辑必须先拆件」。 - 🔴 同一口径已同步进
line-limit-exemptions.md(行数治理的真源表)⇒ 本条与那张表必须并读。 - 🔻 更正(2026-09-13 · T21 追加轮二次;上两行的「有两个」是控制方引述错误**,经 T21 实测异议 + 控制方独立复跑确认 ⇒ 本行更正,上两行原文保留)**:
· 🔴 「有两个恰 300/300」→「有一个恰 300/300」。逐字证据:本节「诚实代价」段那份 10 条手列清单 已含 6 条恰 300 中的 5 条 —— 含上一行点名的
KnowledgeDetailPanel.tsx(它在该表第 6 行逐字 =| \app/src/components/KnowledgeDetailPanel.tsx` | 300 / 300 | 0 |)⇒ 🔴 **唯一漏项 =app/src/components/notes/NotesReadingColumn.views.test.tsx**(**同时是漂移红集成员 F2**)。**恰 300 的完整 6 条**见line-limit-exemptions.md文末的逐条名单。 · 🔴 **归到「控制方序列」(不得写成计划方错误)**:该句出自 **§C55.3(控制方实测纠错第 13 例)的细节**;T21 于追加轮**实测异议**、控制方**独立复跑确认**并更正 ⇒ 属引述/派单类错误在本批的**控制方序列**。🔴 **并且必须留痕一条事实**:**该错文已由 T21 首轮的落账逐字抄进入库文档**(即本块上面那一行)—— 「**控制方引述错误在入库文档里被传染**」这件事本身登记在案;**line-limit-exemptions.md文末那一处未受传染**(T21 首轮已按实测写成「真正漏掉的域内 300/300 是 **1 条**」)⇒ **入库文档里被传染处 = 唯一这一处,本行即其更正**。 · **「数字带时点」的历史链(两个数都留、各带时点,不得只留一个)**:**上游 §C55.3 时点 = 578 文件 / ≥300 = 35 / 295–299 = 20 / 合计 55** → **T21 追加轮实测(当前树)= 579 / 35 / 21 / 56 · 恰 300 = 6 条**;**差 1 文件 + 1 条**的归因**保留在上一行**(新件FragmentGroupAction.tsx155 行 ⇒ 文件 +1;FeedFragmentList.test.tsx297 → 299 ⇒ 该档 +1;🔴 **≥300 档不变 = 35**)。 · 🔴 **张力裁决落账(K,常设)**:本批**文档回写的唯一合法形态 = 「原文 + 就地加注」** ⇒ 派单里凡出现「**删掉 / 移除 / 改成**」这类**字面删改**措辞,**一律按「加注作废 / 加注更正」执行**,并在报告里指出该措辞与 **V2(−列必须为 0)**的冲突;🔴 **不要为迁就措辞去破 V2**。控制方已自陈该要求**自相矛盾**并登记为**控制方错误**(其派单原文自称「第 16 例」);🔴 **T21 按加注执行的处置被登记为正例**。该通则已写进 [docs/standards/documentation.md`](../standards/documentation.md)(第四部分之后新增小节)。
- 🔴 全树机器扫描(唯一来源;口径
-
🔴 负载敏感红的「集合」是一组会漂移的成员,不是固定名单(§C43.3 / §C48.4 / §C50.4 / §C51.5;T22 的诚实边界不得简化成「只有 W1/A4」): JS 侧
SessionDetailPanel(W1 / W2)·components/notes/NotesReadingColumn.views(F2)·SessionViewHost(H4b)·views/registryResolution.test.ts(A1)· 以及 T15 冷跑见过的KnowledgeGraphView; Rust 侧ffmpeg::tests::run_captured_handles_large_output(签名 = 10 s 墙钟超时 +Io("cmd.exe 执行超时(10s)已终止"),裸跑 1.9–42.7 s)。 🔴 成员会随运行漂移(同一棵树上红点成员会换);未取得「≥3 次重复 + 与某可观测量相关 + 该文件不在写集内」三条者,一律登记为「未判定」,不得称为 flake。 -
🔴
node_modules环境级事故(§C23.5 逐字要求进 T22):本批发生过一次app/node_modules被清空事故(fs.rmSync穿透导出树里的 junction)——是环境级事故、不是代码缺陷 ⇒ 不计入任何实施单元;已npm ci恢复(316 包)并复验tsc与 vitest;期间若干单元的复跑被阻断,其读数按「环境阻断」或恢复后重跑登记。 -
🔴
fa45caf1/f7ac5d0f两棵树在line-limits --full的 (e) 判据上不自洽(§C16.2):机理 =git commit --only -- <paths>只按路径取工作树内容、不看暂存区 ⇒ 跨单元连带落库;最终树自洽。🔴 不得声称「7a 段每个中间提交都过 (e) 判据」。 -
🔴 两处代价数字:① 首屏 gzip 103.60 → 104.12 kB(T12 逐块归因到逐字节闭合:T6 拆件的模块边界成本 +557 原始字节 + 级联 −2 ⇒ Σ = +555 = chunk 原始差;残差 26 B 如实写「未能逐块归因」);② katex 字节账用一次真实构建结清:
vendor-katex-*1 chunk / 266,732 原始 / 79,915 gzip、marker 1/3/7,对拍批 6 的2/6/14+ 494,590 B ⇒ −227,858 原始 / −64,497 gzip,全 39 chunk 扫描0.18.4= 0 /0.16.47= 1 ⇒ 顶层那份已从产物消失(manualChunks.ts:56的解释成立)。「删structuredBlocks确实省掉整整一份 katex 副本」= 实测事实。 -
行数 / 结构代价:
App.tsx549(599 → 537 → 549,余 51)·NotePreviewView.tsx364(开工 346)·RefineWorkbench.tsx497 ·SessionsPage.tsx355 ·SessionDetailPanel.tsx222 ·LiveActivityPanel.tsx513 → 242 ·NoteMarkdown.tsx104 → 203 ·noteMarkdownComponents.tsx277 ·NotesReadingColumn.tsx294 → 300 · 新件PageSlot.tsx31 /aiToast.tsx41 /focusRouting.ts32 /lowConfidence.ts32 /markdownLine.ts100 /noteMarkdownComponents.tsx273 /TranscriptRow.tsx201 /NoteCardFlowWithSeek.tsx46 /NoteTagsEditor.tsx165 / 六条展示面 68–115。豁免表 121 条(T6 整行移除 1 条、T19 4 行数值 + 散文 311)。 -
流程代价:本批共发生 4 次「往被跟踪目录写临时产物」(P21,每次都有实际损害 —— 其中一次直接挡住了 T13 的带钩提交)· 1 次「连带回退」事故(
bed72919用陈旧私有索引整段回退 T18 的 5 个文件,已用带旧值守卫的update-ref原子重写为81d62964)· 1 次「连带落库」事故(T20 的4e074ed0带走 T19 未完成的 I1 修复,已授权重写为3d493429)。三次事故均已逐字披露 + 强制自证 + 核验别人内容俱在,并就地立为纪律(「提交后强制自证」/「提交前看git status --porcelain首列」/「历史重写的唯一例外」/「私有索引提交后必须重新对齐真实索引」)。
未做(登记,逐条带归属批次)
- 🔴 归一 = 逻辑归一;观感统一未做 → 批 8(§C11.1)。
- 🔴 规格两章的实现:「带证据三轨」实现(含它的两条红线裁决:段级身份 / 新 command)→ 批 8 · 「审校模式」实现(
ink-4保持 0 生产调用点;§4.3 条件 ③ 的前置定义本批已交)→ 批 8。 - 🔴 R4.1 的「5 个粘滞字段形态」 → 批 8(批 6 登记的 follow-up,本批未承接)。
- 🔴 两处页内 seek(
AiRefineCard/NoteAiDialog)→ 批 8(§C49.3)。 - 🔴
update_fragment_group(#46) 的「接线」那一半(T21 实测前端命中 0)→ 批 8。🔻 收口更正(2026-09-13 · T21 追加轮;上一行原文一字未改)—— 本行从「未做」清单撤回,移入「交付」:
update_fragment_group(#46) 已在批 7 内由 T23 补做(125eec85 feat(components): 片段行补上移动到组入口+5f662811+5d59e332 fix(components): 碎片归组候选改用 feed 地形组;T21 独立复测 PROD 0 → 1,落点app/src/components/FragmentGroupAction.tsx:92)⇒ 🔴 「→ 批 8」的处置作废(依据rulings.md§C56.2:规格处置栏逐字「补 UI(本批)」,计划:532/:2299/:2309三处指派一致 ⇒ 这是批 7 的交付缺口,不是有意的延期)。- 🔴 逐字登记本条的完整来历(供 T22 的二分清单收录):① 计划侧正确且预警过 ——
:2304自陈「数一数是 11 个名字」、:2305裁决「按名字列全 11 个,不删任何一个」;② 漏做 —— T20 的计数口径「6 + T18/T19 的 4 = 10」恰好吞掉了被删减的那一个名字;③ 发现 —— 由 T21 的仪器在收口回写时发现(前端app/src/**含测试 0 命中,而它仍在 registry);④ 裁决 —— 控制方 §C56.2 判定为批 7 的交付缺口并派 T23 补做;⑤ 补做 —— T23 三条提交(含一次由 T23 自己质疑、控制方取证后改判的 feed 地形返工);⑥ 更正 —— T21 于追加轮更正规格 §9 与本节。⇒ 缺口成因 = 实做方的计数口径,不是计划缺陷。
- 🔴 逐字登记本条的完整来历(供 T22 的二分清单收录):① 计划侧正确且预警过 ——
- 🔴 C7「重启后卡录制」的完整覆盖面(触发口径偏离:该命令无心跳字段)→ 批 8(§C54.5⑤)。
- 🔴
get_decision详情面之外的审计 H7 其余 5 项 → 批 8(§C11.7 / §C54.3)。 - 🔴
SURFACE_TAG_REGISTRY对 legacy 文件没有「新增<Surface>调用点」的合法路径(机制缺陷,不是本批失误)→ 批 8 修(§C35.2):legacy 行的count只许降、file键唯一、legacy 和锁又禁止腾挪 ⇒ 任何 legacy 文件内的容器都无法再迁入<Surface>。本批的处置 = 接受 19/21,余 2 处(LiveImageStrip:109/VersionPanel:135)按新类别legacy-registry-frozen留档、转批 8(不授权抬高 legacy 面)。 - 🔴 技术债(逐条带出处;本批一律不改):
·
pr-check.yml的 paths-filter 缺口 + 懒侧守卫的执行者缺口(§C14.5 / §C25.5②):pr-check.yml的 paths-filter 根本没有scripts/**glob(T8 实测缺scripts/lib/**,T11 实测缺口形态未变、逃逸文件集合 +1)⇒ 只改scripts/**的 PR 不被任何被过滤的 job 看见;且scripts/check-bundle-budget.mjs(首屏 + 懒侧的唯一守卫)在pr-check.yml/.husky/pre-commit/scripts/validate-all.mjs三处都没有执行者 ⇒ 这道门禁的牙只在有人手工跑时才存在。裁决:本批不改.github/workflows/(AGENTS.md §10 + 发布自动化连带面 + 非本批登记项)⇒ 落账位置 =docs/standards/performance.md的懒侧门禁节。修复形态 = 补 glob + 给守卫接一个执行者。 ·scripts/check-exemption-prose.mjs登记为「批 8 的候选闸」(§C11.8 ③):T11 新建的散文对拍探针(112 行)必须入库(否则批 8 无法复用)但 不纳入八闸 / CI / husky(理由:八闸的集合是批 8 治理收口的对账基线,本批扩闸会让逐字对账漂移;散文数字天然易漂 ⇒ 硬门禁会频繁假红)。T11 已自跑三条自动面(validate-all.mjs/ husky /pr-check.yml)⇒ 三者都不捡它,无需换名或排除。该文件同时进入 paths-filter 缺口名单(§C41.4 U2)。 ·@types/katex是否仍为未使用的 devDependency(§C20.3):待查项 = 「rehype-katex是否仍需要它」。🔴 本批任何单元都不许动package.json(依赖与构建配置变更 = 超范围 + 撞 AGENTS.md §10 类边界)⇒ 不在批 7 删 → 批 8。 · Rust 回填trim()与前端parseTags/allTags不 trim 的不一致(§C48.5①):带空白的标签会有色行但 UI 查不到(现网无影响 —— 唯一写端已 trim)⇒ 潜在不一致,本批不改(改前端解析会动读端语义)→ 批 8 技术债。 · 新件头注含position:"fixed"字面量 = 潜在陷阱(§C48.5②):该新件若日后加上inset:0⇒ 会新进CROSS_LINE_34⇒ 而dialogMigration.e.test.ts恰 300 行、改不动 ⇒ 直接红且无合法处置路径(现无守卫受影响,dialogMigration.e15/15 绿)。批 8 注意。 · 「commands_video.rs末尾换行被吞而countLines不变」= 门禁盲区(§C51.7①):末尾换行的增删不改变countLines()⇒ 门禁看不见。这是「门禁盲区」的又一例(与line-limit-exemptions.md的口径节同源)⇒ 落账位置 = 该表。 · 「subject ≤50」当前没有机器判据(§C42.3 M-1):commitlint的header-max-length = 100⇒ 钩子对此无牙(T14 的 subject 实测 54 字符未被拦下)。是否收紧属批 8 治理(本批不改commitlint配置)。 · 音频两条(AudioStoragePanel死 UI · 删会话不删音频)→ 产品裁决(§C7.3)。 ·docs/tech-debt/→ 用户裁决(§C7.3;本批不处置、不阻塞)。 - 本批不重跑的五闸(
tsc/ vitest /bundle-budget/bundle-eager-graph/cargo)→ T22(八闸终态)·90bb5f6a(T19 的 U2 提交)尚未被独立评审 ⇒ 并入 T22 的全批收口评审(§C51.6)。
提交清单(59 个,681e73c6..f0f2998c;归组依据 = 逐提交 git show --name-only 的改动面 + subject)
| 归属 | 提交数 | sha(按时间序) |
|---|---|---|
计划勘误与裁决落位(docs(plan),E1) |
4 | 367559ff · c0818e23 · dab62eab · 4292dee2 |
T1 App.tsx 拆件 + 深链 ms 载体(+真空真修正) |
4 | fa45caf1 · f7ac5d0f · 58a1cdb6 · d334ebd3 |
T2 析出 lowConfidenceClass |
1 | 2ed5c836 |
T3 删 structuredBlocks 死导出(+自建判据件) |
1 | 5cda5bdb |
| T4 撤下三条低级写原语命令 | 1 | 39f74e4f |
| T5 登记核对(证据型、零提交) | 0 | (全在 gitignored 报告) |
T6 拆 LiveActivityPanel |
1 | 1bce07d1 |
T7 Surface 受控槽 + 落点迁入 |
4 | 9755d475 · 8fc87190 · 6f1311cb · 473f11b9 |
T8 拆 bundleMeasure 度量模块 |
1 | c29a1b86 |
| T9 懒侧字节门禁(+口径/容差/顶层 pass 三轮) | 4 | 80b1eabc · cd800d63 · e4ceffbf · d138760f |
| T10 注释/散文清扫(11 位点,6 提交) | 6 | 709b41da · 04fce5f7 · bc41861c · e3cefbc0 · 8af217fa · 950afd5a |
| T11 豁免表探针入库 | 1 | 81d62964 |
| T12 7a 段收口 + 懒侧重冻 | 2 | a38585d8 · 0a503cc8 |
T13 拆 NoteMarkdown |
1 | 2c3aa607 |
| T14 聊天 markdown 并入 + 站点断言 | 2 | 9dcd49bd · cb924c06 |
| T15 两支手写链归一 + 芯片毫秒 | 2 | 08862061 · 4fb441af |
T16 NotePreviewView 表征测试 |
1 | 6509e04c |
| T17 深链毫秒链 / 三链芯片 / 死芯片 / 页内 seek | 8 | beca954f · edb6009c · 02c32baa · 42708604 · 47e73dbd · 08717e84 · 4f84831c · 279fb76a |
| T18 标签线(验收一) | 4 | 58a34009 · 8cd96e25 · 78bf8aec · ac202c9c |
| T19 档位通道(验收二)+ I1 修复 | 4 | c6a4cb7c · 5d4bd4a7 · 90bb5f6a · 17d33095 |
| T20 最后一块内容(低置信 ≥2 / 逐段显影 / 规格两章 / 补 UI 6 条) | 5 | 3d493429 · 747cd8c6 · 5d54f1ab · fb73e313 · b72d4709 |
| 并行单元尾随(T10 的 §C54.5④ 路由闭合) | 1 | 36475641 |
| T21 本节回写(规格面) | 1 | f0f2998c |
| 合计 | 59 | —— |
注:
⚠️ T21 的 v0.22 /docs(standards)两个提交不在上表内(自引用,见本节开头的口径)⇒ 全批终态提交数与最终清单由 T22 出。🔴 「59」只在 T21 的规格提交上成立;此后任何单元落库都会改变它。
提交数口径(本文档既定规矩:一律「含左端点」
A^..B):批 8 的开工 HEAD =711ad639(批 7 已收口并推送)⇒ T21 于 2026-09-13T17:32+08:00 实测git rev-parse --short 5852cdc4^=711ad639、git rev-list --count 711ad639..HEAD=git rev-list --count 5852cdc4^..396b5e5c= 63。 🔴 这不是全批终态:T22(全批收口) 与 T23(独立复核) 的提交、以及本节所在的提交均不计入(自引用)。全批终态读数与最终提交清单由 T22 出。 🔴 读数正本 =.superpowers/sdd/2026-09-13-frontend-redesign-batch8/(台账controller-rulings.md§0–§40 ·user-decisions.md· 各task-N-report.md),全部 gitignored。本节数字一律标明来源:凡未由 T21 亲测者,逐字写「引自 §xx / Txx 报告,未独立复核」。T21 亲测的每一条都带命令 + 口径 + 时点(时点 = 2026-09-13 17:32–17:41 +08:00;开工git status --porcelain为空)。
交付
- 段 8a · 地基与治理(T1–T5 + E8/E8b,零生产代码):
scripts/line-limits.mjs拆成 CLI +scripts/lib/lineScan.mjs(T1547ffa1f,模块导出面 7 名逐字不变;countLines的 re-export 全仓 0 importer = 潜在契约非现存契约)· 🔴 末尾换行判据 (f) 并进--full(T2aa93655c,执行者天然存在 ——.husky/pre-commit与 CI 的无条件 job 都在跑它)+ 10 个源文件末尾换行归一(f1742399;正确判据 =git diff -w --numstat为空 +countLines()前后相等 + 逐文件字节证明,不是「−列为 0」)· 批 7 残留 5 处入库文档更正(T3:c5b5a8ec·50fde7bf·4966d9ee·0c299fc7)· E8 的机器期望系统扫描(ea2d0762/02ca571f/7c1fcc41/72b07a91/527c11ef:167 条机器期望逐条分流 = 已跑 95 / 当场真跑 69 / 改「待测」3,不得由推理替代)· 8a 段八闸自证(T5,零提交 / 0 生产代码)。 - 段 8b · 主线一:两条「规格已交、实现未做」的能力(T6–T11) —— 🔴 两条都走零新 IPC / 零 schema / 零 Rust(控制方 §2 A1/A2;
get_session_detail的segments+ocr_blocks本来就在既有命令里)。带证据三轨:模型层纯函数(T6de1f43aa,views/note/noteEvidenceModel.ts202 +noteEvidenceModel.test.ts237 +noteEvidence.fixtures.ts168,T21 实测行数)+ 规格 §7.4 §D 就地加注(T6433c614a,三轨口径 = 笔记段落轨 + 转写段轨session_segments.id+ OCR 块轨session_ocr_blocks.id)+ 视图片(T88cc627de,views/note/NoteEvidenceTrackView.tsx178 +.test.tsx202)+ 注册表第三项(T808b1afda:views/registry.ts:141的FROZEN_VIEW_KEYS.note由 2 键变 3 键["raw","cardflow","evidence"])+ 容器取数(T10e493eac8,hooks/useNoteEvidence.ts157 +components/notes/NotesReadingColumn.evidence.test.tsx178)。审校模式:模式位通道(T9f673bef7,shell/proofreadMode.ts63 +proofreadMode.test.ts216 +proofreadMode.dom.test.tsx85)+ 纯 CSS 覆盖(T93abe4cfc,新建ui/proofread.css12 行;属性名逐字data-proofread-mode,不得用data-proofread—— 后者已被 LLM 文本校对占用)+ 入口(T110916d126顶栏按钮;b077d530回写ui-ux-system.md/theme.md的审校模式并加注落点与命名;ffb7e28a更正入口落地状态)。贴边件拆件三件(T7521a8487/6dfbfa72/e0335072)。 - 段 8c · 主线二:观感/像素面「收编,不立项」(T12–T16):批 3 的仪器搬出 gitignored
tmp/入库并参数化(T12e430ad9b,scripts/viewport-probe.mjs298 行,一字节未改仪器内核)+ 盲区随仪器登记(T12c19418e7):验的是 WebView2 引擎不是 IPC/窗口层 · headless 默认prefers-reduced-motion: reduce(可覆写)· headless 滚动条占位0· 必须用Emulation.setDeviceMetricsOverride·--dump-dom抓不到 · 🔴 profile 必须落$env:TEMP,绝不许落仓内。读数任务 T13 / T14 / T15 全部零提交、零生产代码;T14 落地三条登记(4041eab5:--dist假绿 · 18 族逐族上限陈旧度 ·shift-的 212 B 死预算);T16 落地三件(b7c34351·bbd41795·cc08c95f)。按需入口(段 8f 的 U4):app/package.json:11新增"check:visual": "node ../scripts/viewport-probe.mjs --width 1024 --height 640"(T24ff181f99)+ 触发条件写死(T24cb4686d1);🔴 不接 husky、不进 CI(用户未选 U4-b/c)。 - 段 8d · 主线三:治理余项(T17–T20):CI 挂载(G2)—— 脚本域门禁挂进
pr-check.yml的无条件 job(T1701913605;:197Line limits·:202Command registry consistency),包体闸移入已构建的前端 job(T175b692792;:71首屏,--no-build,懒侧不判);🔴 不补scripts/**glob(控制方 G2 逐字)⇒ 该缺口仍在、列为技术债。散文探针转正(G6)——check-exemption-prose.mjs只作 CI 单列 step(:211Exemption table prose check),🔴 不进八闸集合(保持批 7 定的对账基线)。化石处置(G3)——scripts/validate-all.mjs删除 + 改路由(T1881304d52,git rm形态+3/−65;T21 实测Test-Path scripts/validate-all.mjs= False)+ 两条后继更正(T18110d980d·0ffb46fd)。登记制(G4)——SURFACE_TAG_REGISTRY的键由file改成(file, tier)(T190eae531f+ 判据分档aa93ceea+ 纯注释更正58829aec);不变量改前/改后逐字段差异 0(<Surface>47 · 命中文件 29 · 登记行 29 · Σ 47 · legacy 9 行和 14)。提交信息牙 ——commitlint.config.js:16装上'subject-max-length': [2, 'always', 50](T202da0b14d)。 - 段 8f · 用户裁决项落地(T24–T28 + T29):U1 = a 都修 ⇒
audio_store_config.rs212(新,照同域先例audio_preproc_config.rs的「JSON 原子写 + 损坏降级 + env 覆盖」形态)·AudioStoragePanel的假开关变真通道 ·session_audio_config_set+1 条 IPC ⇒ 🔴 本批第一次抬高命令注册表:311 → 312(依据 = §29.6 用户裁决 A,授权恰 1 条;312 = 新基线,后续不得再抬高)· 删会话两级联清音频(T28b0508d91+ 边界测试47e2b56e,新件session_audio_purge.rs117 +session_audio_purge_tests.rs248)。U2 = c 删除(仅代码路径):移除"default"作为合法凭据槽的读写路径(T25a054ec73+ 具名红点收紧ae3bba3e)。U3 = a 归档:docs/tech-debt/归档到docs/archive/2026-09-13/(T26335a6155+ 路径引用更正630d2bfa)⇒ 批 7 全程占着git status的摩擦源正式关闭。T29(计划外微单元):两处过期自述更正(9d011ade·9b1e8aa8)。 - 段 8e · 收口(T21–T23):本节即其第一件;T22 = 全批八闸(含真构建 ⇒ 懒侧这一次必须判)+ 三条验收 + 二分清单 + 收口评审;T23 = 未参与交付者的独立复核。T31 / T32 是收口前的两个补正单元(
5018c7ab·01a381cb·291b7111·396b5e5c)。
验收(三条主线的兑现度 + T21 落库时的八闸读数)
🔴 「三条验收」的口径:批 8 的「三条验收」= 三条主线的验收(计划
## Global Constraints 二逐字写死:「本批的「三条验收」= 三条主线的验收……不是规格 §11 的 11 条整册验收 —— 那 11 条逐条登记去向」)。⇒ 规格 §10 批 8 行的「11 条验收全达标」一律按加注读,不得声称「11 条全达标」(规格 §10 / §14 的就地加注见下「规格漂移纠正」段)。
| # | 主线 | 判据(计划逐字) | T21 落库时的机器读数 | 兑现度 |
|---|---|---|---|---|
| 一 | 两条「规格已交、实现未做」的能力 | 「带证据三轨」有实现(模型 + 视图 + 容器取数,E1/E2/E3 三条口径各有机器判据)且「审校模式」有实现(模式位 + 纯 CSS 覆盖 + 三出口) | 四个新件的专属判据件全部在盘且入全量:noteEvidenceModel.test.ts · NoteEvidenceTrackView.test.tsx · NotesReadingColumn.evidence.test.tsx · proofreadMode.test.ts + proofreadMode.dom.test.tsx;🔴 注册表第三项:views/registry.ts:141 逐字 note: ["raw", "cardflow", "evidence"](T21 逐行直读);全量 vitest 235 文件 / 2300 passed / 0 failed / 0 pending(T21 亲测,命令 npx vitest run --reporter=json --outputFile=<绝对路径>,cwd = app/,时点 17:34:02+08:00) |
✅ 成立 |
| 二 | 观感/像素面收编 | 「观感仪器已入库且可复跑」,且 14 条观感欠账逐条有读数或具名归属(「有读数」≠「已统一 / 已修好」) | 仪器:scripts/viewport-probe.mjs 在盘、298 行(T21 实测 countLines())、app/package.json:11 的 check:visual 入口在盘;仪器自检 9/9 ✅(innerWidth===--width · dpr · 500px 定块 · 文本哨兵 90 · 阳性对照 1 · 阴性对照每次现造随机串 = 0 · emulatedMedia 实测 == --reduced-motion · --probe canary 16px · fonts.status=loaded)引自 task-13-report.md §3.2,T21 未独立复跑仪器;两套独立读法交叉对拍 28 个属性格 ⇒ 不一致 = 0(引自同报告 §3.3)。14 条逐条落位见下「14 条观感欠账的逐条落位」表 |
✅ 成立(含「有读数 ≠ 已统一」的限定) |
| 三 | 治理余项 | 「四条治理余项各自落地或明确关账(CI 挂载 · validate-all.mjs · SURFACE_TAG_REGISTRY (file,tier) · subject ≤50 · 散文探针转正)」 |
四条 4/4 落地:① CI 挂载(G2 脚本域两闸 + G6 散文探针单列 step)⇒ pr-check.yml:197 / :202 / :211(T21 逐行直读)② validate-all.mjs ⇒ 已删(Test-Path = False)③ (file, tier) ⇒ 键已改(surfaceResidual.ts 逐字含 键 = \${file} |
${tier}`),不变量差异 0 ④ **subject ≤50** ⇒ commitlint.config.js:16` 逐字在盘。 |
| 另计 | 段 8f 的四项用户裁决(不并入三条主线,但必须单列兑现度) | U1 音频两条 · U2 凭据槽代码路径 · U3 docs/tech-debt/ 归档 · U4 观感按需入口 |
U1 = a 都修 ✅(配置通道 + 面板真开关 + 会话结束清理同源 + 删会话两条路径级联清音频;注册表 311 → 312 经用户裁决 A 授权)· U2 = c 删除 ✅(只移除代码路径;已存密钥数据保留)· U3 = a 归档 ✅(夹内 README.md 5,839 B · review-2026-09-11.md 191,980 B · tech-debt.md 26,374 B;归档件 sha256 d185caff… / HEAD blob 52ad1d01… 三口径同值 —— 引自 §25.1)· U4 = d 入库 + 按需入口 + 写死触发条件 ✅(且不接 husky / 不进 CI)· U5 = 沿用「跳过」 🔴 ⇒ 7 条真机类继续登记、不假装完成 |
✅ 4/4 成立;U5 明示未覆盖 |
🔴 规格 §11「11 条整册验收」与本批的关系(逐条登记去向,不得合并):§11-1(4 个 >600 行 → 0;>300 行 100% 在豁免表内)⇒ 本批只读:
line-limits --full0 / 121 / 121(T21 亲测)· §11-6 ⇒ 🔴 本批把它从 2 推进到 3(见下就地加注)· §11-7(47 条逐个有结论)⇒ 本批只读(registry 312/312/0 是唯一相关读数)· §11-8 ⇒ 本批零改动(见下就地加注)· §11-11(tsc0 错 ·vitest全绿 ·cargo test全绿)⇒ T21 亲测三条全绿(见八闸与附闸)· 其余 6 条(§11-2/3/4/5/9/10)本批未触碰、未复跑 ⇒ 不进本批的兑现度声明。
14 条观感欠账的逐条落位(主线二的兑现面;「有读数」≠「已统一 / 已修好」)
| # | 欠账 | 批 8 的读数 / 归属 | 来源 |
|---|---|---|---|
| 1 | 两套模式常量并存(「归一 = 逻辑归一;观感统一未做」) | 读到读数:用户裁决 D1/D2/D3/D5 = 保持现状 ⇒ 预览 13px / 工作台 12px 并存 | §23.1 |
| 2 | 两条链 7 档里 6 档不同、唯 li 相同 |
复现;🔴 限定:属性级有 5 格实际相同 ⇒ 「6 档不同」是档级结论 | task-13-report.md §2.3 / §4 |
| 3 | markdownLine.ts 含 6 个原始 hex 且在颜色守卫域外 |
登记 + 具名归属(cc08c95f)· 域外机制证据 = 守卫只覆盖 ui/primitives/*.css |
§23.2 立案 B · task-13-report.md §6 |
| 4 | Surface 逐处迁移的可见变化 |
读到读数(表值):圆角就地 6→8 9 处 · 边框 #e5e7eb → --ed-border 14 处 · 近白底 8 处 · boxShadow 20 处(含 1 处有损)· 遮罩 1 处 · 墨度 2.54:1 → 5.13:1(186 处) |
task-14-report.md §四③ |
| 5 | 批 7 的七条展示面零观感验收、零同名测试 | 出图:主轮 17 组 PNG + JSON 一一配对;补轮 tmp/t15/ 57 文件 / 2,645,258 B(PNG/JSON 配对、孤儿 0) |
§30.1 / §32.7 |
| 6 | D 组六条展示面「设计决定」而非裁决(充分性未判) | 机器不可判 ⇒ 只能出图 + 人判(几何读数逐条在 §30.1) | §30.1 · 本段「诚实代价」 |
| 7 | 🔴 掉地项:AiConversationDock 的方向性投影登记给批 5,而批 5 已收口 |
T16 本批认领 + 明确归属(bbd41795)⇒ 不再掉一次 |
§24.1 |
| 8 | Text 字号越界存量(551 / 123) |
读到读数:常量 == Σ 表 · 文件数 == 键数 · 锚条目数 == 冻结文件数 —— 三连通全 true |
task-14-report.md §四③ |
| 9 | 弱化灰存量(63 / 43) | 读到读数:同上三连通全 true |
同上 |
| 10 | 圆角 26 / 5 / 4 三档不在任何棘轮内 |
登记 + 具名归属 | §24.1 · task-16-report.md |
| 11 | 暗档 data-theme 实际生效(今天只有定义、无写入方) |
登记;🔴 仪器不可达(全入库域 0 处设该属性) | §23.2 立案 B |
| 12 | 真实帧率 / Flip 几何位移 / 切视图卡顿 | 登记(只登记、不编造弱判据) | motion.md 的不可判清单 |
| 13 | 三档「看起来不一样」 | 登记(同上) | 同上 |
| 14 | 真机 1280×800 / 最小尺寸夹取 | 🔴 U5 沿用「跳过」 ⇒ 只登记、7 条不假装完成 | §30.4 |
🔴 三条验收里凡涉及真机的部分:真机 / WebView2 冒烟由用户裁决跳过(U5) ⇒ 上表 #5 / #6 / #14 的「端到端」全部止于 jsdom / Rust 单测 / headless Edge 层;「有读数」≠「已统一」≠「已真机验证」。
八闸(T21 落库时在工作树上串行实测,逐条给命令 + exit + 读数 + 时点;🔴 不是全批终态,终态由 T22 出)
八闸的集合 = 计划
### 表 1的 8 条(line-limits --full·check-command-registry·docs-check·tsc --noEmit·check-bundle-budget·bundle-eager-graph·check-exemption-prose(批 8 T17 起为 CI step,仍不进八闸对账) ·git status --porcelain+ HEAD)。🔴check-exemption-prose是「附闸」,不是八闸成员(G6 逐字)。 公共口径:树 = 工作树(git status --porcelain为空)· HEAD =396b5e5c· 分支dev· 时点 = 2026-09-13T17:32–17:34 +08:00 · 🔴app/distmtime = 2026-09-13T15:55:56+08:00`(T24 的真实构建产物;T21 未重建 dist ⇒ 第 ⑤ 闸的懒侧判定本就不成立,见下)。
| # | 闸 | 命令 | exit | 读数(逐字) |
|---|---|---|---|---|
| ① | 行数 | node scripts/line-limits.mjs --full |
0 | ✅ line-limits(--full · 数值一致):>600 硬限 0(棘轮内)· 301–600 档 121 · 登记条目 121 |
| ② | 命令注册 | node scripts/check-command-registry.mjs |
0 | ✅ 命令注册一致:定义 312 / 注册 312 / 重复 0 |
| ③ | 文档 | node scripts/docs-check.mjs |
0 | docs-check: 扫描 284 个 Markdown 文件(检查 181 个,archive 快照与豁免清单除外) + 五条 ✅ + ✅ docs-check 通过 |
| ④ | 类型 | cd app; npx tsc --noEmit |
0 | (无输出 = 0 错) |
| ⑤ | 包体 | node scripts/check-bundle-budget.mjs --no-build |
0 | 首屏 106.23 kB(原始 333,231 B;gzip 106,225 B;余量 93.78 kB)· 懒侧 39 chunk / 639,868 B ⇒ 🔴 懒侧预算 ⏭ 未判 |
| ⑥ | eager 图 | node scripts/bundle-eager-graph.mjs |
0 | 首屏静态可达应用源文件:113 · 首屏拉入的 npm 包:7(@gsap/react · @tauri-apps/api · @tauri-apps/plugin-dialog · gsap · react · react-dom · views) |
| ⑦ | 附闸 · 散文探针 | node scripts/check-exemption-prose.mjs |
0 | ✅ 散文「**312 条**」== 门禁「定义 312」(docs/standards/line-limit-exemptions.md:44) · ✅ App.tsx 登记 563 == countLines 563(…:23) · ✅ 散文与真源一致(…批 8 T17 起为 CI 门禁、单列 step,仍不进 husky) |
| ⑧ | 卫生 + 时点 | git status --porcelain / git rev-parse --short HEAD |
0 | 空 / 396b5e5c(分支 dev) |
🔴 第 ⑤ 闸的懒侧为什么是
⏭ 未判(逐字纪律):--no-build的读数按脚本自己的口径不可用于懒侧判据(scripts/lazyBudget.json的scope字段逐字:「🔴 必须在新鲜构建产物上判定……本判据的合格调用 = 不带--no-build」)⇒ 🔴 本节不得写「懒侧已达标」;懒侧的真判定是 T22 的独占窗口那一件事。当前工具只能给出一条旁证:639,868 B这个数与冻结上限逐字节相等(见下「懒侧基线」段)。 🔴app/dist的 mtime 不是时点载体(承 T15 的当场复现,§30.7):内容哈希f490c2bbdabf0c9ded388c194a187589f1566165f6dbf118535a5563c9f22a(108 文件 / 3,427,748 B)在 17/17 + 补轮 10/10 读数中相同,而 mtime 在会话内变过(07:28:38Z → 07:55:56Z,T24 重建)而字节数不变 ⇒ 上表第 ⑤ 闸读的是一个 mtime 已被改写过的 dist;它的内容哈希与 T15 的 27 份读数同表可比。 🔴 八闸的「全绿」不是全绿:W1 那类负载敏感红是「一次读数」判不了的 —— T21 本节只跑一次冷跑(全量 vitest 0 失败)⇒ 🔴 按 R-FLAKE 三条(≥3 次重复 + 与某可观测量相关 + 该文件不在写集内)判,本节这一次跑不足以判定任何 flake 的状态 ⇒ 不得据本节写「flake 已消失」。
附闸 / 非八闸读数(逐条给出命令与来源)
cargo test --test app_lib_tests(T21 亲测,cwd =app/src-tauri,时点 17:34:48+08:00)⇒2378 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 9.27s,exit 0。逐段可查:T25 之前 2360 → T252363→ T27 2371 → T28 2378(引自 §4.1 的控制方台账;T21 只亲测了终值 2378)。- 前端全量 vitest(T21 亲测,
npx vitest run --reporter=json --outputFile=<绝对路径>,cwd =app/,时点 17:34:02+08:00)⇒testResults.length= 235 文件 ·numTotalTests= 2300 ·numPassedTests= 2300 ·numFailedTests= 0 ·numPendingTests= 0 ·success = true· exit 0。🔴 与 T27 时点的235 文件 / 2299 passed差 +1 ⇒ 差额归因 = T31 的291b7111(useViewMemory.test.ts206 → 230 行,补evidence键的记忆持久化覆盖,V2 用例 13 → 14) —— 两个读数都留、各带时点(引自 §35.3 / §39.1;T21 只亲测了 HEAD 时点的 2300)。🔴 仪器口径:numTotalTestFiles字段不存在(批 5 起即如此)⇒ 文件数一律读testResults.length。 cargo clippy -- -D warnings(= CI 的原样命令,pr-check.yml:136-144)(T21 亲测,cwd =app/src-tauri,时点 17:35:10+08:00)⇒ 🔴 exit 101 ·error: could not compile entropydecrease (lib) due to 15 previous errors·warning侧只有 1 条既有 cargo 警告(lib.rs同时属于lib与integration-test两个 target,非 clippy error)。🔴 T21 逐条复算落在 10 个文件(ai_proofread.rs·asr_confusion.rs·asr_pass2.rs×2 ·commands_asr_confusion.rs·commands_proofread.rs×4 ·commands_session_note.rs·commands_web_inbox.rs×2 ·db_completion.rs·db_migrations.rs·db_task_index.rs)⇒ 🔴 台账 §36.4 第 2 条写「散在 9 个文件」与实测不符:真值 = 10 个文件(其 §36.2 表自身也是 10 个文件;差额 1、成因 = 计数口径;台账原文保留)。git ls-files域(T21 亲测,时点 17:33+08:00)⇒ 1,639(计划期 1,616;T24 时点 1,634 ⇒ T25+1· T27+2· T28+2= 1,639,域计数闭合)。⚠️ 凡上表未亲测的读数,本节一律标明「引自」:cargo test的逐段中间值(2360/2363/2371)· clippy 的「批 8 净贡献 = 0 条新诊断 / 集合差 EMPTY」·git ls-files的逐段增量 · 归因链的中间树读数。🔴 T21 未在711ad639树上重跑 clippy(需要在旧树上重建)⇒ 「净贡献 0」是引用口径,不是本单元的自证。
懒侧基线的两个时点(🔴 本节最有价值的一条读数)
| 时点 | 冻结值 | 归属 / 授权 |
|---|---|---|
| 批 7 T12 的 7a 段收口 | limit 636,243 · chunk 37 · 族 37 | 0a503cc8(引自 lazyBudget.json 的 semantics 字段) |
| 批 7 T22 全批收口重冻 | limit 637,501 · chunk 37 · 族 38 | 55f502fa(🔥 这就是「批 7 收口 637,501」的由来;🔴 它不是「批 8 的基线」 —— generatedFrom 里那句曾被写成「批 8 的基线」,已按 lazyBudget.json 现文更正) |
| 批 8 第 1 次重冻 = T8(8b 段收口) | 族 38 → 40 · 总量 637,501 → 639,314 · chunk 37 → 39 | 08b1afda(T21 亲测:该提交在 git log -- scripts/lazyBudget.json 内)· 🔴 依据 §C46.4「每收口一次、重冻一次」+ 控制方的逐次授权(§21.1:§C32.3 ② 的「总上限只许降」被逐次授权解除,附六条硬条件,含 vendor-* 五族零增长) |
| 🔴 批 8 第 2 次重冻 = T10(容器片收口) | NotesPage- 48,693 → 49,219(+526)· 总量 639,314 → 639,868(+554)· chunk 39 → 39(不变) |
73348055(T21 亲测在 git log -- scripts/lazyBudget.json 内)· 授权同 §C46.4 逐次授权 · 机制:EVIDENCE_LOAD 是 NoteEvidenceTrackView.tsx 的唯一静态导入点 ⇒ 该视图 + 模型层并入宿主 NotesPage- 族(不合并则 chunk 数 39 → 40 ⇒ 换一条判据红 —— 这是设计取舍,不是随手抬预算) |
🔴 现冻结值(T21 于 2026-09-13T17:33+08:00 直读
scripts/lazyBudget.json逐值复核):族数 = 40 ·lazyTotalGzipBytesMax= 639,868 ·lazyChunkCountMax= 39 ·Σ 逐族 gzipBytesMax= 640,941(比总量高 1,073 B)。vendor-*五族上限逐字为vendor-canvas-58,784 ·vendor-editor-208,585 ·vendor-gsap-41,161 ·vendor-katex-79,915 ·vendor-md-50,622;shift-族上限 212(chunkCount = 0 的死预算,承批 7 的登记,本批仍未清)。 🔴🔴 结构性发现(必须逐字进下一批的输入清单):重冻后的总量上限 == 实测值 —— 第 ⑤ 闸--no-build读到的懒侧合计 639,868 B 与lazyTotalGzipBytesMax639,868 逐字节相等 ⇒ 🔴 除 64 B 容差外零余量 ⇒ 任何新增懒侧字节必然判红。⚠️ 但这不是「懒侧已达标」(第 ⑤ 闸仍是⏭ 未判——--no-build的读数不可用于该判据),而是「预算余量政策缺失」这一结构性问题:⇒ 🔴 下一批需要一条「预算余量政策」(例如:重冻时保留固定 slack,或把shift-的 212 B 死预算回收为共享余量)—— 登记为本批输出的下一批输入 #8。 🔴 逐族上限的陈旧度披露(承批 7 的登记,本批只读):批 7 的重冻后读数显示有 18 个族的实测已超各自上限、合计 +203 B(均在 64 B/族容差内 ⇒ 未判红)⇒ 登记为下一批的逐族重冻输入(总量上限不得抬高)。🔴 本批:T8 / T10 两次重冻只动 2 + 2 个族(恰 2 新增 + 恰 2 重冻 + 0 删除),其余族一字未动;vendor-*五族逐族零增长(§21.2 / §21.1 的六条硬条件全部满足,STOP 未触发)。
规格漂移纠正(逐处,原文保留 + 就地加注)
| 漂移 | 落点 |
|---|---|
§10 批 8 行的「11 条验收全达标」= §11 的 11 条整册验收,不是批 8 的行内验收 ⇒ 批 8 只兑现与三条主线直接相关的部分;且该行的「新增动效规范章节」已在批 6 落地(docs/standards/motion.md,bffed928) |
规格 §10 批 8 行之后整块加注(§10 加注块 A) |
| §11-6(会话与笔记各 ≥2 种):「带证据三轨」的实现已于批 8 交付 ⇒ 笔记 2 → 3 种;🔴 但「≥2」这条验收本身不因此改口径(2 ≥ 2 早已成立),且真机面仍未覆盖 | 规格 §11-6 的批 7 加注块之后就地加注(§11 加注块 B) |
| §11-8(标签能写进去 / 档位选完真生效且跨会话记住):批 8 对该条零改动;批 7 的代理判据结论仍然成立 ⇒ 🔴 不得把它读成「批 8 重新验证过」,也不得把批 8 的 U1 音频两条算进这一条 | 规格 §11-8 该行之后就地加注(§11 加注块 C) |
§14 的文档清单行:docs/versions/v0.21.md(或 v0.20.14)行的实际落点 = docs/versions/v0.22.md,批 8 节已落;docs/standards/ 行的「新增动效规范章节」批 6 已落(批 8 只留 ui-ux-system.md / theme.md 的四层动效 / 三档强度回写,🔴 本批仍未做);ADR-034/035 与 ADR-010 两行的批 8 动作 |
规格 §14 的批 6 加注块之后就地加注(§14 加注块 D) |
🔴 §12 的 :979(旧凭据槽 "default") |
规格 §12 表内该行之后就地加注(§12 加注块 E) |
🔴 本节删改措辞的处置声明(承
docs/standards/documentation.md:116-125):本单元的一切规格改动只有+行、−列为 0;派单里凡出现「删掉 / 移除 / 改成」这类字面删改措辞,一律按「加注作废 / 加注更正」执行,并在报告里指出该措辞与「−列为 0」的冲突 —— 不为迁就措辞去破该判据(T21 实测:本任务的派单措辞已按该纪律写成「终态加注」,未出现冲突;对照批 7 的 §C59.5 曾出现过一次)。
过程中纠正的计划错误(E8 序列,逐条带出处与落位)
口径:这是控制方对计划编制单元的错误计数(与「控制方自己的错误序列」是两条序列,勿混)。批 8 的计划勘误编号 = E8-1 … E8-25(承接批 7 的
### 表 6bE-1–E-30)。E8-1 … E8-16 由 E8 单元与各实施单元落账(计划## E8节 +task-e8-report.md/task-e8b-report.md),E8-17 … E8-25 由控制方在 §20.5 / §26.6 / §29.5 / §29.7 / §31 / §35.5 落账。🔴 共同根因一条:「卡片写下的机器断言从未真跑过」(§10.2 逐字称之为本批最重要的过程发现)。逐条摘录(全文见台账,本节只列根因各异者):① E8-1 / E8-3 / E8-4 三连(§5 · §10):「期望红点」凭空推断(Task 1 的 M2/M3)· 「期望行号锚」偏 4 行(
:236实为:232)· 🔴 「期望 diff 形态」在数学上不可达(给末尾无换行的文件补换行,git 必然重写末行 ⇒ 任何正确实现都拿不到−0)⇒ 判据换成实质判据(git diff -w --numstat为空 +countLines()相等 + 空白行 Δ = 0 + 逐文件字节证明)。同源教训 = 批 7 的「锚点由变异体裁定,不由推理裁定」。 ② E8-2(§5):卡片的 re-export 指令不完整(只点名countLines)⇒ 照做会静默收窄另外 6 个导出名;T1 自行修正为「导出面 7 名逐字不变」,登记为正例。 ③ E8-5 / E8-6 / E8-7(§14.2 / §14.3 · §14.3):卡片事实主张错且 E8 的系统扫描漏了它 · 卡片的变异体格自相矛盾 · 「三件恰 300 的脚本」已过时(T1 拆件后line-limits.mjs= 204 ·lib/lineScan.mjs= 122)⇒ 触发 E8b 针对性补扫。 ④ E8-11 / E8-12(§25 · §31.2):docs-check的基线读数过期(281/181→282/182→284/181,最后一步由 T26 归档造成、已逐字登记在docs/archive/2026-09-13/README.md:32与docs/archive/README.md:115)。 ⑤ E8-13 / E8-14 / E8-15 / E8-16 / E8-18(§20.5):Files:与Interfaces自相矛盾 · 保护表写「豁免表 = 无人·全批零改动」而未预见 T11 需要App.tsx增长 · 卡面已被 T3 落库 · 写成「本任务追加」而父版本已含 · T24 目标③ ×Files:禁令互斥(处置 = 禁令优先)。 ⑥ E8-17 / E8-19 / E8-20 / E8-21 / E8-22 / E8-23 / E8-24 / E8-25(§22.4 / §28 / §29.5 / §29.7 / §31 / §35.5):Step 3与卡片自己的V3互斥(裁定 = 判据面优先)· 🔴 保护表把豁免表登记为「无人(全批零改动)」且直接卡住 T28 · 🔴🔴 E8-20:T27 卡片的前提错 ——「面板上的开关」根本不存在(由此触发用户裁决 A)· E8-21:「AudioStoreConfig全仓 10 处构造点」是标识符命中数、不是构造点(真值 = 3 处生产构造点)· E8-22:T22 收口卡的lazyBudget.json冻结读数已过期(卡片写 37 / 637,501,真值 40 族 / 639,868 / chunk 39)· E8-23:### 表 1的两条读数亦已过期(App.tsx卡片 549、实测 563)· E8-24:T27 卡片的「先例」指错了一个更近的先例(audio_preproc_config.rs)· 🔴 E8-25:卡片口径与门禁冲突(「净增 ≤ +5 可不同步」vsline-limits.mjs:167-172的 (e) 精确相等)⇒ 口径写死:「凡在豁免表里登记了的文件,其行数的任何变化(含 ±1)都必须在同一次提交里原地同步该行数值」。 ⑦ 🔴 本序列的计数有两处口径必须并读:(a) §31.1 称 E8-22 为「本类错误第 21 处」、§35.5 称 E8-25 为「卡片勘误第 22 处」⇒ 「E8-N」与「卡片勘误第 M 处」是两条编号(后者含非 E8 编号的卡片勘误);(b) E8 序列里没有 E8-7 之外的跳号(台账 §14.3 有 E8-7)⇒ 1–25 连续。
诚实代价(不许省略)
- 🔴 真机 / WebView2 冒烟由用户裁决跳过(U5) ⇒ 三条验收的「端到端」全部止于 jsdom / Rust 单测 / headless Edge 层;7 条真机类继续登记、不假装完成。不得出现「已真机确认」类表述。
- 🔴 观感 / 像素面机器不可判 ⇒ 一切「有读数」≠「已统一」(主线二的判据逐字如此)。D 组六条展示面的「设计充分性」是人的决定(T15 只出图 + 几何读数;几何读数 ≠ 充分性判定)。headless Edge ≠ WebView2:仪器验的是 WebView2 引擎的渲染结果,不覆盖 IPC 壳 / 窗口层。
- 🔴 一切「未判定」不得写成「全绿」:懒侧预算那一闸 =
⏭ 未判(本节八闸跑的是--no-build)⇒ 不得写「懒侧已达标」。 - 🔴 观感读数的两个适用边界(必须并读):① 夹具数据 vs 真实数据 —— T15 的受控三臂(
natural元素 203 /M1空体 19 /fixture263)证明夹具形状决定可达面,故凡「element count」类读数必须声明臂;② headless Edge vs WebView2 —— 见上。 - 🔴 T15 / T15b 的两条实测边界(逐字登记,本批不下结论):
finish_session恢复条的自毁边界 = 测得区间(5020, 5497] ms(7 点采样,页面内performance.now(),非--wait参数;跨边界元素数 263 → 224)· 🔴 出图是在 1.5 s 内取的 ⇒ 图与「稳态」不是同一个东西(§30.4 U1 逐字要求 T21 记录本条)。update_knowledge_system编辑面板横向溢出 16 px(scrollW 178 / clientW 162)· 🔴 三臂 0 px 差 ⇒ 结构性、不是夹具产物(F-long / F-short / F-empty 同为 178/162)· 根因 =KnowledgeSystemEditPanel.tsx:24的INPUT对象缺boxSizing:"border-box"(content-box下width:100%= 内容 162 + padding 12 + border 4 = 178)· 引入者 = 批 7 的b72d4709(git merge-base --is-ancestor b72d4709 711ad639成立 ⇒ 批 7 引入的回归,不是历史存量)· 🔴 本批不修(理由逐条见 §32.3:范围冻结 / 它落在零余量的KnowledgePage-族 / 判据形态留作下一批模板)。
- 🔴 漂移红集的成员会漂移,不是固定名单(JS 侧 ≥5 个:
SessionDetailPanel(W1 / W2)·components/notes/NotesReadingColumn.views·SessionViewHost·views/registryResolution.test.ts·KnowledgeGraphView;Rust 侧ffmpeg::tests::run_captured_handles_large_output)—— 🔴 只有 W1 三件齐(冷红 / 热红 / 第 3 次绿);其余一律「未判定」,不得称为 flake。🔴SessionDetailPanel的 W1 与批 7 是同一条(§33.5 裁定)。 - 🔴
[[ts:ms]]的RefineWorkbench侧仍不可点 —— 与批 7 的「两侧芯片均已可点」两句必须并读(T21 用机器证据把两句分开):组件级已接线(RefineWorkbench.tsx:334-337的openChip容器侧委托 +:450/:469/:483三处onClick;判据件RefineWorkbench.test.tsx:280-294,断言失败语逐字「工作台侧芯片仍不可点(C10.2「不再算残余」未兑现)」)⇒ 批 7 那句说的是组件能力。🔴 而生产可达性分三种(T21 于 2026-09-13T17:5x+08:00 逐处直读):VersionPanel.tsx:215转交onOpenSessionAt(由components/notes/NotesReadingColumn.parts.tsx:87供值)⇒ 可点;AiRefineCard.tsx:225不传onOpenSessionAt⇒ 不可点;NoteAiDialog.tsx:200不传且sessionId={undefined}⇒ 不可点(openChip同时要求sessionId与onOpenSessionAt)⇒ 🔴 派单那句「RefineWorkbench侧仍不可点」成立,且它说的正是批 7 登记的「两处页内 seek」(AiRefineCard/NoteAiDialog)。🔴 本批零改动这两处 ⇒ 登记为下一批输入。不得声称「[[ts:ms]]全链已通」,也不得声称「批 7 的加注被推翻」。 - 🔴
setTimeout(…, 0)为负载敏感性观察项:T10 在hooks/useNoteEvidence.ts:88把「成功 / 失败的唯一出口」推迟到宏任务(setTimeout(…, 0))⇒ 用户可见结果不变(引自task-10-report.md:187),但 🔴 宏任务延后在并发 / 负载下可能抖(本批已有红点集合漂移史)⇒ 控制方裁定双登记:① 进诚实边界 ② 列为「负载敏感性观察项」,并声称「若后续NotesPage/NotesReadingColumn相关件出现漂移红,第一嫌疑 = 它」(引自task-10-report.md:285)。🔴 它不是缺陷、也不是 flake 判定;本批未做任何稳定性加固。 - 🔴 本批的「全量绿」从来不是全绿:本批有已知 flake(W1 一族),且并行窗口内的瞬时红是一类现象、不是固定名单。T21 本节的一次冷跑 0 失败不构成任何 flake 的状态判定。
- 🔴
app/dist的 mtime 不是时点载体(T15 当场复现:mtime 变而内容哈希不变)⇒ 一切「dist 时点」必须用内容哈希,不得用 mtime。 - 🔴 CI 的 clippy step 长期为红(独立债务,不在批 8 内):
pr-check.yml:136-144的原样命令cargo clippy -- -D warnings⇒ exit 101 · 15 errors,逐条git blame全部落在 2026-09-06 前后(1 条 2026-08-20),无一由批 8 引入(引自 §36.2 / §37.2;T21 亲测了 exit 101 与 15 errors,未独立复跑 blame 与两侧集合)。🔴 批 8 的净贡献 = 0 条新诊断(集合差 EMPTY —— 引自 §37.1,T21 未独立复核集合)。🔴 根因:本项目一直用--all-targets(不带-D warnings) 取「clippy 基线」,而 CI 用的是-D warnings⇒ 同一个门禁两个口径,基线永远「绿」而门禁永远「红」。⇒ 🔴 应报用户并决定是否另排一批。 - 🔴 两次重冻 = 两次「总上限授权解除」,全部有据(§C46.4 逐次授权 + 六条硬条件)⇒ 🔴 本重冻不是守卫放宽;但 🔴 重冻后总量 == 实测 ⇒ 零余量(见「懒侧基线」段)⇒ 任何后续新增懒侧字节必红。
- 🔴 一处本单元独立发现的台账偏差(如实登记):§36.4 第 2 条写 15 条 error「散在 9 个文件」⇒ T21 实测 = 10 个文件(§36.2 表自身也是 10 个文件)。差额 1、成因 = 计数口径;台账原文保留,此处即其更正。
- 🔴 一处引述纪律(承
documentation.md:125):本节的2378 / 2360 / 2363 / 2371四个 cargo 读数里,只有2378是 T21 亲测,其余三个是引自控制方台账 §4.1;235 文件 / 2299 passed是引自 T27 报告,T21 亲测的是 HEAD 时点的235 / 2300。⇒ 引用时必须带时点,不得把两个数当成同一个。
未做(登记,逐条带归属批次)
🔴 口径:本节只收「本批该做而未做」与「下一批的具名输入」两类的并集,逐条带归属批次;不允许有「谁都没认领」的条目(承 §34 的欠账闸门扫描:46 命中逐条分流)。
A · 下一批输入(9 条,逐条带全部要素;出处 = 台账 §34.4)
- 🔴 16 px 横向溢出(真实观感缺陷) → 下一批:位点
app/src/components/KnowledgeSystemEditPanel.tsx:24· 根因INPUT缺boxSizing:"border-box"· 实测scrollW 178 / clientW 162 / diff 16(三臂 0 px 差)· 引入b72d4709(批 7)· 判据 = 探针复测scrollW == clientW· 附带跑一次真构建确认KnowledgePage-族与懒侧总量仍在 +64 B 容差内。 - 🔴
finish_session恢复条 5 s 自毁(观感 / 可达性) → 下一批:测得区间(5020, 5497] ms· 跨边界元素 263 → 224 · 🔴 出图是在 1.5 s 内取的 ⇒ 图与「稳态」不同。 - 🔴
get_decision越出 900 px 折叠线 98 px → 下一批:实测几何290 × 215,bottom 1005 > 900⇒ 🔴 设计充分性机器不可判,留人判。 - 🔴 旧凭据数据在应用内永久不可达且不可清理 → 下一批(需新用户裁决):U2 的 (ii) 不做边界(无迁移即销毁不可逆)⇒ 本批只移除代码路径。
- 🔴 批 0d 的 browser profile 残留 → 下一批清理:
.superpowers/sdd/2026-09-11-frontend-redesign-batch0d-primitives/tmp/{probe-chrome-profile,probe-prof-fix,probe-prof-plain,probe-prof-postfix}= 4 目录 / 695 文件 / 18,360,765 B(18.36 MB 十进制) · 🔴 纪律:收尾清 profile;确需留证的落.superpowers/**并登记大小。 - 🔴 T21(批 7)的
.md剥注释口径未复现 → 低优先,留作口径核对(批 8 T3 如实登记「未复现」,评为正确的诚实边界)。 - 🔴 D4 / D6 两条单独立案 → 下一批:D4 = 两条链的 markdown 标记前缀泄漏(唯一改「用户读到的字」的一条:预览链把
### 三级标题带井号显示、工作台链把> 引用一行带大于号显示;不是回归 —— 迁移前就有的行为)· D6 = 6 个写死色值 / 颜色守卫域(没有任何现有 token 的亮档值等于这 6 个 hex;暗档今天不可达;守卫只覆盖ui/primitives/*.css)。 - 🔴 懒侧预算余量政策 → 下一批:重冻后总量 == 实测 ⇒ 零余量 ⇒ 任何新增懒侧字节必红(详见本节「懒侧基线」段的结构性发现)。
- 🔴 观感仪器盲区 6 的自动检测 → 下一批:「陈旧 dist」本批做成硬纪律(跑前真构建),不做自动检测;🔴 懒侧守卫的执行者缺口仍未闭合(前置「跨构建环境字节漂移受控实测」至今未做 ⇒ 该技术债从批 7 继承到批 8 后仍为
open)。本批不新增门禁成员(计划:162逐字:八闸集合不变)⇒ 建常设探针不在本批范围。
B · 其他未做项(逐条带归属批次)
- 🔴 §7.4「带证据三轨」的真机 / 像素面验证** → U5 未覆盖(实现已交付、端到端止于 jsdom / Rust 单测)。
- 🔴 §4.3「审校模式」的实现已交付,但观感一致性未验证(U5)· 且它与
ProofreadPanel一族的命名消歧只在规格加注与常量里(data-proofread-mode),没有产品文档级的说明。 - 🔴 两处页内 seek(
AiRefineCard/NoteAiDialog)→ 下一批(本批未做;批 7 已登记)。 - 🔴
docs/product/ui-ux-system.md/theme.md的四层动效 / 三档强度回写 → 下一批(批 6 登记、批 8 仍未做;批 8 只回写了审校模式那一节)。 - 🔴 孤儿 sidecar(
audio_store::cleanup只按.wav过滤 ⇒1.wav.meta.json永不被清理,:253的统计同样不计 sidecar)→ 下一批(T28 自己的删除面已两件全清;具名归属audio_store::cleanup)。 - 🔴
audio_store.rs:162的let _ = std::fs::write(...)(忽略错误,与 AGENTS.md §4「空 catch / 忽略错误」相邻)→ 下一批(已点名、未改、未复制)。 - 🔴 删除失败上报前端不可见(只到 stderr + 内部结构,不经 IPC)→ 下一批(产品面:要让用户看见需改 IPC 线格式 + 前端类型 ⇒ 另立单元)。
- 🔴 保留期 / 预算目前无 UI 通道(JSON 可写)→ 下一批(配置通道已真,但只暴露
enabled一个字段;判据形态已现成 = 照面板开关的三段式:落盘 → 回读 → 死分支复活)。 - 🔴 删会话不删音频的「另一条链」5 处调用点(
commands_photo:83/166/188·commands_web:120·commands_web_inbox:358直呼db.delete_session)→ 观察项,不扩面(这些类型从不写音频;SessionAudioWriter::create唯一生产调用点 =live_session.rs)。 - 🔴
pr-check.yml的 paths-filter 缺口(根本没有scripts/**glob)→ 下一批治理(T17 有意不补;控制方 G2 逐字「不补 glob」)。 - 🔴
line-limits的扫描域未扩(scripts/**/*.mjs与app/vite.config.ts仍在域外)→ 下一批(扩域 = 独立的门禁政策变更)。 - 🔴
SURFACE_TAG_REGISTRY的两处 legacy 残值未迁(LiveImageStrip:109/VersionPanel:135,登记为legacy-registry-frozen)→ 下一批(T19 只开路、不迁移;🔴 不授权抬高 legacy 面)。 - 🔴
@types/katex是否仍为未使用的 devDependency → 下一批(侦察结论:它在dependencies且是rehype-katex@7.0.1的硬传递依赖 ⇒ 「未使用的 devDependency」这个前提不成立;本批未动package.json的依赖段)。 - 🔴 Rust 回填
trim()与前端parseTags/allTags不 trim 的不一致 → 下一批技术债(现网无影响 —— 唯一写端已 trim)。 - 🔴 「subject ≤50」的牙齿口径:本批已装上(
commitlint.config.js:16),🔴 但计数是String.length(UTF-16 单元)⇒ emoji 算 2(对中文成立、对 emoji 偏严);且不追溯历史提交。 - 🔴
docs/tech-debt/→ 已由用户裁决 U3 归档(不再是未决项);所有权仍属用户。 - 🔴 U5 的 7 条真机类 → 继续登记、不假装完成。
C · 归 T22 / T23 的条目(收口链自己认领,出处 = 台账 §34.5)
| # | 条目 | 落点 |
|---|---|---|
| 1 | 🔴 D 组 6 条展示面的「设计充分性」把关:这 6 条是本计划新造的设计决定,不是裁决 | 🔴 T22 的收口评审件必须逐条给出这 6 条的处置(把关 or 逐字写明「机器不可判、留人判」),不得只写「已交付」 |
| 2 | 全量 vitest 的 W1 负载敏感 flake(SessionDetailPanel.test.tsx) |
🔴 T22 的冷 + 热两次必须按 R-FLAKE 三条判;缺一 ⇒ 只写「未判定」 |
| 3 | 八闸集合 × CI job 集合的交集与差集 | 🔴 T22 报告必须列交集与差集,不得只写计数 |
| 4 | 漂移红集成员会漂移(≥5 个,只有 W1 三件齐) | 🔴 T21 的 v0.22 批 8 节(本段即其落地)+ T22 报告都要逐字保留这条诚实边界 |
| 5 | 懒侧真预算判据(需真构建) | 🔴 归 T22(它的独占窗口 + 真构建那一次)—— 本节第 ⑤ 闸据此写 ⏭ 未判 |
提交清单(63 个,5852cdc4^..396b5e5c;归组依据 = §段边界 + 逐提交 git show --name-only 的改动面 + subject)
| 归属 | 提交数 | sha(按时间序) |
|---|---|---|
| 8a · 地基与治理(计划 + T1–T5 + E8/E8b) | 14 | 5852cdc4 · 7c1fcc41 · 50fde7bf · 547ffa1f · c5b5a8ec · 4966d9ee · 0c299fc7 · f1742399 · aa93655c · 42d53366 · 02ca571f · ea2d0762 · 72b07a91 · 527c11ef |
| 8b · 主线一:两条能力(T6–T11) | 14 | f673bef7 · 3abe4cfc · 521a8487 · 6dfbfa72 · e0335072 · de1f43aa · 433c614a · b077d530 · 0916d126 · ffb7e28a · 8cc627de · 08b1afda · e493eac8 · 73348055 |
| 8c · 主线二:观感收编(T12–T16) | 6 | e430ad9b · c19418e7 · 4041eab5 · b7c34351 · bbd41795 · cc08c95f |
| 8d · 主线三:治理余项(T17–T20) | 9 | 01913605 · 5b692792 · 2da0b14d · 81304d52 · 0eae531f · aa93ceea · 110d980d · 0ffb46fd · 58829aec |
| 8f · 用户裁决项落地(T24–T28 + T29) | 16 | 335a6155 · 630d2bfa · ff181f99 · cb4686d1 · 9d011ade · 9b1e8aa8 · a054ec73 · ae3bba3e · af47f2e1 · 36128090 · bb080765 · 7df0d480 · 32942fb9 · 5a2170b0 · b0508d91 · 47e2b56e |
| 8e · 收口(T31 · T32;不含 T21/T22/T23) | 4 | 5018c7ab · 01a381cb · 291b7111 · 396b5e5c |
| 合计 | 63 | —— |
注:
⚠️ T21(本节)与 T22 / T23 的提交不在上表内(自引用,见本节开头的口径)⇒ 全批终态提交数与最终清单由 T22 出。🔴 「63」只在 T21 的落库时点成立;此后任何单元落库都会改变它。 ✅ 归组的机器自证:上表 63 个 sha 两两不重复,且与git log --reverse --format=%h 711ad639..HEAD的 63 项逐项相等(T21 于 2026-09-13T17:41+08:00 用脚本对拍;无遗漏、无多余)。⚠️ e493eac8/73348055的段归属:两者都属段 8b(T10 的容器片 + 它的重冻),不是段 8c —— 判据 =lazyBudget.json的generatedFrom逐字把第 4 次重冻归给「T10(容器片)」。
🔻 批 8 的真终态与三条入库边界(2026-09-13 加注 · 执行单元 T34;本节正文一字未改)
为什么有这一段:本节正文的读数全部是 T21 落库时点(
git status --porcelain为空 · HEAD396b5e5c· 2026-09-13T17:32–17:41 +08:00)的值;本节:966/:1142/:1154逐字把「全批终态读数与最终提交清单由 T22 出」,而 T22 之后的两个回写提交(9ef6a432·7af07891)与 T22b 的第 3 次重冻(923657f3)再次改写了终态,其终态却只住在 gitignored 的.superpowers/sdd/2026-09-13-frontend-redesign-batch8/task-22-report.md/closing-review.md⇒ 🔴 新鲜克隆的读者从入库面看到的懒侧状态(639,868/⏭ 未判/Σ640,941/ 「零余量」/「63 提交」)与入库真源scripts/lazyBudget.json(640,072/Σ641,173/ 66 提交)不一致,且入库面原本没有任何一句说明以哪个为准(独立复核 T23 的 Blocker B-0)。控制方裁定:必须回写(「以lazyBudget.json为准」这种口头约定本身也得写进入库面)。 🔴 以哪个为准(本加注唯一的效力条款):凡本节正文与scripts/lazyBudget.json冲突者,一律以scripts/lazyBudget.json为准 —— 它是机器可读的入库真源,scripts/check-bundle-budget.mjs直接读它判据;本节正文的旧数字一律保留为「T21 落库时点读数」,不得因其过期而删除(承docs/standards/documentation.md:121的「原文 + 就地加注」)。 口径声明:本段是纯追加(git diff --numstat的删除列 = 0)· 不新增文件 · 一切「取代 / 更正」一律以加注表达。下文凡未标「引自」者 = T34 于 2026-09-13T18:14–18:16 +08:00 亲测(工作树 · 分支dev· 开工与收工git status --porcelain均为空);凡标「引自」者 = T34 未独立复跑。
一 · 批 8 的真终态(本节的「63 提交」与「懒侧 ⏭ 未判」两处按本段读)
| # | 事实 | 读数 | 口径 / 来源 |
|---|---|---|---|
| 1 | 批 8 最终提交数 | 66 | git rev-list --count 711ad639..HEAD(T34 亲测 · HEAD = 923657f3 · 分支 dev)· 与本节 :965 的 63(T21 落库时点读数)不矛盾:63 + T21 的两条回写(9ef6a432 · 7af07891)+ T22b 的第 3 次重冻(923657f3)= 66 |
| 2 | 懒侧第 3 次重冻 = 923657f3 |
lazyTotalGzipBytesMax 639,868 → 640,072 · SettingsPage- 17,760 → 17,992 · Σ逐族 640,941 → 641,173 · lazyChunkCountMax 39 未动 · 族数 40 未动 |
控制方按 §C32.3 ② / §C46.4 逐次授权(授权来源 = 控制方对 T22 的 STOP S1 的裁定)· T34 直读 scripts/lazyBudget.json 复核:40 族 · 总量 640,072 · chunk 39 · Σ 641,173(Σ 比总量高 1,101 B;上一时点为 1,073 B) |
| 3 | 🔴 懒侧真判(本批唯一一次 · 真构建)= exit 0 |
judged = true · pass = true · 总量 640,072 == 上限 640,072 · unlisted = [](0 个)· fails = [] · 超容差族 = 0(逐族红 0) · 首屏 106.22 kB |
命令 node scripts/check-bundle-budget.mjs(不带 --no-build · cwd = 仓根)· 读数存档 .superpowers/sdd/2026-09-13-frontend-redesign-batch8/tmp/t22/t22b-v1-refreeze.json / t22b-v1-refreeze.txt / t22b-v1-verdict.md(均为 gitignored;T34 只读该存档、未独立复跑真构建)⇒ 🔴 本条取代本节 :1023 与 :1028 的「懒侧 ⏭ 未判」:⏭ 未判 是 T21 用 --no-build 跑出来的(脚本 scope 字段逐字禁止该调用用于懒侧判据),不是懒侧的真实结论 |
| 4 | 🔴 「零余量」的结构性结论仍然成立 | 重冻后 总量上限 == 实测值(640,072) | 承本节 :1050 的结构性发现 ⇒ 下一批需要一条「预算余量政策」(本节 :1109 的下一批输入 #8 不因本次重冻而消解)—— 🔴 本次是「如实对齐实测」,不是放宽守卫,也不是给出余量(除 64 B 容差外仍零余量) |
| 5 | 推高者 = 7df0d480(T27 的音频面板真开关 · 用户裁决 A) |
受控对照(bb080765 = 7df0d480^ 的导出树 git archive + node_modules junction 真构建)把旧冻结总量逐字节复现为 639,868 ⇒ 🔴 本批确有新增字节,不是跨构建环境 / 工具链漂移 |
引自 .superpowers/sdd/2026-09-13-frontend-redesign-batch8/tmp/t22/ctl-vs-mine.md(MINE = 7af07891 真构建 ⇒ 640,072 / 17,992;逐族 Δ 之和 +204 == 总量 Δ,自洽)· T34 未复跑该对照构建 |
二 · SettingsPage- 那半的归属拆分(独立复核 T23 的 Important-1 · 必须与上表第 2 行并读)
🔴
scripts/lazyBudget.json的generatedFrom现文逐字写「① 重冻 1 族 ——SettingsPage-17,760 → 17,992(+232,== T22 真构建实测值)」;🔴 但该「+232」是「本次实测值 − 旧上限」的差,不是「本次实测值 − 改动前实测值」的差:受控对照实测 CONTROL = 17,767、旧上限 = 17,760 ⇒ 真实新增 = +225(T27 的必然后果),另 7 B 是改动前的既有溢出(bb080765树上SettingsPage-已经 17,767 > 上限 17,760 ⇒ 超 7 B,在 64 B 容差内故当时不红)—— 🔴 那 7 B 不是 T27 的必然后果(引自tmp/t22/ctl-vs-mine.md:37与t22b-v1-verdict.md;T34 未复跑该对照)。 🔴 逐字写明:「🔴 上限 == 本次实测这一条在逐族层含 7 B 的既有溢出;§C32.3 的条件④(『是该次改动的必然后果』)在SettingsPage-上只对 +225 成立」。 ⇒ 本重冻的授权依据不受影响(授权针对的是「懒侧真判首次执行即红、须如实对齐实测」这一整体),但 🔴 「+232」不得再被引用为「T27 的增量」:T27 的增量 = +225。
三 · 「本地绿 ≠ CI 绿」边界(独立复核 T23 的 Important-4 · 本批此前完全没有这一句)
🔴 逐字写明:「本批一切『全绿』全部是本地读数;🔴 CI 第一次运行尚未发生。」 事实:本批未 push ——
git rev-parse origin/dev=cb4686d1(T34 亲测;它是段 8f 内的一个提交),git rev-list --count origin/dev..HEAD= 19 ⇒cb4686d1之后的 19 个提交(含 T21 / T22b 的全部回写与重冻)在 CI 上零运行。🔴 本批反而新增了 CI 挂载(.github/workflows/pr-check.yml::197-198Line limits·:202-203Command registry consistency·:211-212Exemption table prose check,均由 T1701913605挂上)⇒ 新增的守卫本身也一次都没在 CI 上跑过。 🔴 已有的四条症状保留(不因本次加注而消解):① clippy 在 CI 恒红(pr-check.yml:136-144的原样命令cargo clippy -- -D warnings⇒ 本机复跑 exit 101 · 15 errors,见本节:1036/:1091)② 懒侧在 CI 不判(:71-72的包体闸是--no-build· 首屏 only ⇒ CI 里永远打⏭ 未判)③ cargo 命令不同(CI 是:135的cargo test -- --skip …三条 skip,本地门禁口径是cargo test --test app_lib_tests⇒ 同一门禁两个口径,与本节:1091记的 clippy 那条同族)④ eager 闸无 CI 执行者(scripts/bundle-eager-graph.mjs在.github/下零命中 —— T34 实测)。
四 · 46 条 open 债务的分流去向(独立复核 T23 的 Important-2)
🔴 事实:本节
:1098逐字承诺「不允许有『谁都没认领』的条目(承 §34 的欠账闸门扫描:46 命中逐条分流)」,🔴 但分流表只住在 gitignored 的批 8 台账里 ⇒ 本节(:963–:1158,196 行)命中的 TD-ID = 0(T34 实测:本节内 TD-ID 正则命中 0 处)⇒ 对外部读者与漏登等价。 ① 🔴 权威清单 =docs/archive/2026-09-13/tech-debt.md(滚动权威 · 入库;其夹内README.md逐字「本清单为当前唯一权威债务清单,归档日滚动更新」)—— 本节的分流若与该清单不一致,以该清单为准。 ② 批 8 的分流判据与逐条处置记在批 8 台账.superpowers/sdd/2026-09-13-frontend-redesign-batch8/controller-rulings.md(§34)—— 🔴 它是 gitignored 的工作记录(.gitignore:29的.superpowers/),不是入库契约:本机读者可复核,新鲜克隆的读者读不到 ⇒ 🔴 该条缺口本身仍是open(本段只是把它写进入库面,不等于已闭合)。 ③ 真实状态分布(T34 独立解析docs/archive/2026-09-13/tech-debt.md的「状态」列;countLines= 91 行 · 表格数据行 = 59):
| 状态(只取括号前的主状态词) | 条数 |
|---|---|
open(含 open(部分兑现) 1 + open(子项部分兑现) 1) |
46 |
closed(含 closed(部分兑现) 2) |
10 |
carried(含 carried(实测余 2 处) 1) |
3 |
| 合计 | 59 |
同一次解析的交叉核对:类型列 = 无意 27 / 有意 16 / 腐化 13 / 环境变化 2 / 预存 1;优先级列 = P2 24 / P3 18 / P1 13 / P0 4。
⚠️ 两个「46」不是同一个测量,不得合并:本节:1098的 46 = 批 8 §34 欠账闸门扫描的命中数;上表的 46 = 权威清单里状态仍为open的数据行数(T34 独立解析)。两者今日同为 46 是巧合,不是同一集合 —— T34 未做两者的逐条对拍 ⇒ 🔴 不得据此声称「分流已闭合」或「欠账已清零」。⚠️ 顺带如实登记(T23 的「入库面命中 = 0」在本文档全文范围内需限定):docs/versions/v0.22.md全文另有 1 处 TD-ID(TD-2026-09-11-H,:68,在批 8 节之外)⇒ 🔴 准确口径是「批 8 节内命中 = 0」,不是「本文档命中 = 0」。T34 未复核 T23 的其余 8 条 Minor。
规格 §10 的批 0 还包含:ADR-033~035(当前 docs/adr/ 最高为 ADR-032)· 豁免表纠偏 · 拆 4 个 >600 行文件 · 原语三层。这些不在 0-A / 0-B 范围内,后续子批次另行立计划。
陷阱 1 · 行数 —— Get-Content 会少算
本机 harness 的 pwsh 实为 Windows PowerShell 5.1(ANSI 码页 gb2312),Get-Content 会按 GBK 解码 UTF-8 文件并吞掉换行、把行数少算(实测:index.ts 19→12、paths.test.ts 130→112、NoteListView.tsx 654→609;全量 868 文件实测最大少算 56 行:live_session_pause.rs 353→297 —— 足以把越 300 红线的文件读成达标)。
文档域可远超此量级(2026-09-11 批 0-C1 补测):本批台账(.superpowers/sdd/2026-09-11-frontend-redesign-batch0c1-line-limits/progress.md,该目录不进 git)实测 真实 385 行 / Get-Content 报 247 行 —— 少算 138 行(36%),因为少算幅度随中文密度放大;Task 5 复测同一文件(已增至真实 494 行)时 Get-Content 报 356 行,两次差值同为 138 行 ⇒ 该偏差不随文件增长而收敛。⇒ 「禁用 Get-Content 数行」不是只对源码域成立。
⇒ AGENTS.md §3 的「≤300 / >600」以 [System.IO.File]::ReadAllLines(path, UTF8).Count 为唯一口径(即 node scripts/line-limits.mjs);禁用 Get-Content、Measure-Object -Line(只数非空行)与字节 0x0A 计数(对末尾无换行的文件会少算 1,本仓实测 8 个这样的源文件)。该失真已造成一次真实险情(据此误判 IconName 未导出)。
治理侧(口径未定义、15 个 >600 硬限违规、豁免表数值过期)见 docs/tech-debt/review-2026-09-11.md;工具侧见批 0-B 台账。
⚠️ 上句故意不写成 Markdown 链接:该文件目前未入 git(docs/tech-debt/整个目录 0 tracked)。写成链接会让新克隆断链、并让docs-check在别人机器上变红 —— 而在本机因文件存在而通过(这类"本地绿、别处红"的掩盖正是本批要消灭的缺陷类)。该文件入库后可改回链接。🔻 2026-09-13 加注(T26 归档后补记):该目录已于批 8 归档到docs/archive/2026-09-13/⇒ 「未入 git」已不成立,链接现可安全写为 review-2026-09-11.md;本行理由在当时成立,原文保留。
陷阱 2 · 退出码 —— 2>&1 | … 会把成功的原生命令报成失败
cargo(及任何往 stderr 写 warning 的原生命令)在 2>&1 | … 或管道下,其 stderr 会被 PowerShell 5.1 包装成 NativeCommandError,使整个管道以非零结束 —— 即使命令本身完全成功。
实测:cargo test 2>&1 | Select-Object -Last 40 报 exit 1,而同一次运行的单元测试是 2337 passed; 0 failed; 6 ignored、cargo test --doc 亦全绿;改用 2>file 重定向后 真实 exit = 0。
⇒ 判定这类命令的结果必须用 2>file 重定向,或直接读 $LASTEXITCODE,绝不要用 2>&1 | …。 否则会把绿的门禁误报成失败(批 0 收尾时差点如此)。
顺带记两条预存 cargo warning(非批 0 引入):lib.rs 同时属于 lib target app_lib 与 integration-test target app_lib_tests(正是它触发了上述假象);src/db_task_index_tests.rs:6 的 unused import: super::*。
陷阱 3 · cargo test --lib 的测试二进制在本机启动即崩(2026-09-11 发现,非本系列引入)
实测:cargo test --lib 报 error: test failed, to rerun pass --lib,原因是进程尚未进入 main 就以 0xc0000139(STATUS_ENTRYPOINT_NOT_FOUND)退出——即原生 DLL 加载期失败,与 Rust 代码无关。
本机 DLL 现状(三处同名不同版本):C:\Windows\system32\onnxruntime.dll = 1.17(2026-09-09 出现)· ort/onnxruntime-win-x64-gpu_cuda12-1.28.0/lib/onnxruntime.dll = 1.27.1(但其 onnxruntime.lib 来自 1.28.0,import lib 与 DLL 版本不一致)· ort/onnxruntime-win-x64-1.28.0/lib/onnxruntime.dll = 1.28.0。
⇒ 门禁请用 cargo test --test app_lib_tests:同一源码同一时刻该 target 可正常执行——2026-09-11 实测(空载机器)2357 passed / 0 failed / 6 ignored,exit 0,覆盖全部 #[cfg(test)] 模块(都是 #[path] 挂载到 lib.rs,与 lib target 同一份测试集)。
注意一项装载敏感的偶发失败:
ffmpeg::tests::run_captured_handles_large_output内含 10s 墙钟超时,同时跑cargo build+vitest时被拖超时失败,单独重跑 8.55s 通过 ⇒ 判定门禁时须串行执行(或单独复跑该用例再下结论)。 ⇒ 治本方向(未执行,留给依赖治理):把ort/下的 DLL 与其 import lib 对齐到同一版本,并消除 system32 的同名抢占。本次 DeepSeek 修复的验证全程走--test app_lib_tests,不受该问题影响。
陷阱 4 · 批 4 收口新增的五条仪器陷阱(2026-09-12,收口评审 M-7 + 收口修复单元实测;台账已入册 #36–#38)
- 🔴
--outputFile的相对路径按 UI 根(app/)解析 ⇒ 断言器读不到 JSON 却仍exit 0:在app/下跑node node_modules/vitest/vitest.mjs run --reporter=json --outputFile=<相对路径>,vitest 把结果写到app/<相对路径>,断言器读进程 cwd 的<相对路径>时 ENOENT,若只打印不抛错就变成**「无证据的绿」(修复单元两次踩到,靠 harness 的 ENOENT 才暴露;它在app/下误建的.superpowers/**已删除)。⇒ 纪律:--outputFile一律传绝对路径;harness 在「JSON 不可读」时必须非零退出**。 - 🔴 本机没有
pwsh:只有 Windows PowerShell 5.1(pwsh -NoProfile -File x.ps1⇒CommandNotFoundException,连-File都不可用)。⇒ 长脚本一律写成.mjs用node跑(比陷阱 1 的「吞换行」更强的一条;与台账 #34/#37 同源)。 - 🔴 「改用共享仪器」必须显式验证,否则只是把风险从两份变成一份看不见的:
loadingRatchet.test.ts原来逐字重写了一份stripComments,含同一个</x>坏点,只因它的扫描域里恰好没有「两个闭合标签之间夹加载文案」的形态才没暴露;并入共享实现(sliceScan)时才发现 —— 因此必须同时补夹具(textRatchet⑥ +loadingScan.isHandwritten的两条夹具)。残余风险(本单元实测,未修,仅登记):app/src/ui/primitives/nativeButton.ratchet.test.ts:53+至今仍带一份私有stripComments,其isRegexStart仍是旧版(白名单含<、无</x>判定收紧),未被ed07d491覆盖;本单元实测该差异对<button计数今日无影响(两仪器在 HEAD /f6dd012f/42e88740三棵树上读数逐字相同:393/115 · 394/114 · 510/121),但属于同一类假阴的活样本,动它的单元须按本条纪律「两跑对拍」。 - 🟡
git commit --only -- <paths>会提交未暂存的改动(与git add --的直觉不同):提交前必须git status --porcelain确认工作树里只有要提交的那些文件(记录形态,不是缺陷)。 - 🟡
core.autocrlf=true下新写文件的 LF 警告不影响行数:warning: LF will be replaced by CRLF the next time Git touches it;实测提交 blob 与工作树都是 0 个 CRLF(git show HEAD:<path>的\r\n计数 = 0),行数读数不受影响。
陷阱 5 · 批 7 收口新增的三条提交/仪器陷阱(2026-09-13,T22 实测 + 控制方采信;台账入册 P-31 / P-32 / P-33)
- 🔴 P-31:vitest
--outputFile是异步写盘 ⇒ 读到的可能是上一跑的读数:T22 首版因此误读,自查后加 mtime 守卫 ⇒ 🎯 登记为正例(自查 + 修复 + 上报)。🔴 **与既有「陷阱 4 第 1 条」(P17:--outputFile的相对路径按app/解析 ⇒ 断言器 ENOENT 却仍exit 0)配套使用:⇒ 纪律 = 读任何--outputFile产物前先查 mtime;路径一律绝对;JSON 不可读必须非零退出。两条合起来才封住「无证据的绿」。 - 🔴 P-32:PowerShell 5.1 的
Set-Content -Encoding UTF8会写出 BOM ⇒ commitlint 把它读成subject may not be empty并拒绝提交。⇒ 纪律:写提交信息一律用 nodefs.writeFileSync(p, s, "utf8")(或git commit -F读 node 写出的无 BOM 文件),不要用Set-Content/Out-File -Encoding UTF8。 - 🔴🔴 P-33:
update-ref必须从独立脚本执行、且必须查退出码 —— T22 实测:PowerShell 传参把update-ref静默搞失败,而它没有查$LASTEXITCODE⇒ 表面成功、ref 未动(最危险的一类:自证看起来通过、提交其实不存在)。⇒ 纪律:一切 ref 移动走 node / 文件脚本,断言退出码,成功后立即git rev-parse HEAD回读验证。(与「陷阱 4 第 4 条」git commit --only的形态同族 —— 都是原生命令的静默失败面。)
陷阱 6 · 「扫描即快照」的推断会系统性误报在飞单元(2026-09-13,批 7 收口;控制方驳回一次 STOP 后登记)
事实:批 7 的一个侦察单元主张「T22 的收口件(task-22-report.md / closing-review.md)不在盘上 ⇒ T22 跑过但报告从未落盘」,并据此提出 STOP。
控制方实测(决定性):扫描当时 tmp/t22/ 已含 lib/ logs/ trees/ 三目录、mtime 2026-09-13T03:53 ⇒ T22 仍在运行;两件随后于 04:04:39 / 04:05:27 落盘 ✅ ⇒ 🔴 不是「从未落盘」,是「尚未落盘」(该判定与其派生项一并作废)。T21 于终态回写时实测两件均在盘(109,327 B / 693 行 与 41,469 B / 323 行)。
🔴 纪律:对「某产物不存在」的判定,必须排除「该产物正在被生成中」这一可能 —— 至少查同名目录 / 同名文件的 mtime,或该单元是否仍在飞。本仓并行度很高,「扫描即快照」的推断会系统性误报在飞单元(本条与「诚实边界」里那句「未判定 ≠ 不存在」同族)。
工具链真相 1 · 本地提交门禁此前从未武装(2026-09-11,批 0-C1 Task 4 发现,已修正)
本克隆此前从未安装 husky —— core.hooksPath 为空、无 .git/hooks/pre-commit、无 node_modules ⇒ .husky/pre-commit(lint-staged)与 .husky/commit-msg(commitlint)在本机对所有提交都是静默失效的:不只是某个批次,而是历史上每一次提交,包括批 0-A / 0-B / 0-C1 的全部交付提交(旁证:控制方在本会话提交 40+ 次,从未见过任何 lint-staged / commitlint 输出)。⇒ 新克隆若未 npm install,门禁默认失效且无任何提示(不报错、不警告,提交照常成功)。
现状:已武装(npm install + npm run prepare)—— node_modules/ 与 .git/config 的 core.hooksPath=.husky/_ 两项环境变更都不进 git;此后提交会真被 pre-commit 与 commitlint 拦(★ 二轮后 pre-commit 跑的是 line-limits --full && docs-check,不再是 lint-staged —— 见下一段)(已取得实测拦截证据:(c) 超过 300 行但未登记:app/src/__probe-lines.ts(320 行)、husky - pre-commit script failed、HEAD 未动)。
同一轮还补了门禁自身的覆盖,并在终局评审后把接线方式整体换掉(2026-09-11 二轮,31b59239):.husky/pre-commit 现在不再经 lint-staged,而是每次提交都直跑 node scripts/line-limits.mjs --full && node scripts/docs-check.mjs(&& 串联,任一失败即以非零退出、husky 拦下提交)。package.json 的 lint-staged 块随之删除(devDependencies 里的 lint-staged 保留,留给将来的文件级任务)。
换法的三条理由:① 两个检查都是全树只读扫描、且忽略传入的文件参数(line-limits.mjs 只认 --write / --full)⇒ lint-staged「把暂存文件列表交给命令」的语义对它们零贡献,却带回 stash / git reset --hard / hide / auto-stage / .git/lint-staged_unstaged.patch 一整类风险(见「工具链真相 2」);② 用 --full 是为本地与 CI 同口径守 (e)「登记值 == 实测值」,而 --full 只读(写登记表只走 --write)⇒ 不会逼人每次提交重生成表;③ 门禁每次都跑全树,不再依赖 package.json 的 glob。
⇒ 本文档此前那句「lint-staged 增加 {package.json,…} → --full 条目」不要读成「(e) 已在本地全时生效」:旧接线只在暂存到 {package.json, scripts/line-limits.mjs, docs/standards/line-limit-exemptions.md} 三者之一时才跑 --full,其余情况只跑默认模式(不守 (e))。实测:只暂存一个改动过的源文件时该段 0 files / [SKIPPED] ⇒ 同一暂存态下旧门禁 npx lint-staged exit 0,而新 hook exit 1 并报 (e) 行数不一致:app/src-tauri/src/lib.rs 声明 1025 / 实测 1026。另一处同类问题是 glob 假覆盖:app/**/*.{ts,tsx,rs} 命中 872 个 tracked 文件,而脚本扫描域只有 868 个 ⇒ 差 4 个(app/src-tauri/build.rs、app/src-tauri/examples/capture_ocr_diag.rs、app/vite.config.ts、app/vitest.config.ts)「命令跑了、文件却没被看见」。直跑全树消掉的是「命令跑了却看不见」这层假覆盖本身(glob 不再决定门禁视野),不是这 4 个文件:它们仍在 SCAN_DIRS(app/src + app/src-tauri/src)之外、长到 700 行本地仍绿 —— 改直跑后门禁依然看不到它们(扩域须另立批次,见计划「未做(登记)」)。(评审记录为 870 / 差 2 个,那是以 git ls-files 'app/**/*.ts' … 数的 —— git pathspec 的 ** 比 micromatch 少算 app/*.config.ts 两个文件;按 lint-staged 实际使用的 micromatch 复核是 872 / 差 4 个。)
CI 兜底在修好前不成立(如实登记;2026-09-11 实地复核并更正根因):CI 从未跑过本批 —— 最近一次 PR Quality Check 运行停在 2026-09-09(run 34361436068,headSha 2089042b = origin/dev 的尖端),此后 dev 上的提交全部落在 CI 覆盖之外(截至 ac7dd15b 实测 78 个:git rev-list --count origin/dev..ac7dd15b —— 该值是移动值:31b59239 时 76、dd130dff 时 77 ⇒ 引用须带锚点,勿当现状)。该次运行的真实结果(gh run view 34361436068):changes = success、docs = failure、app-frontend / app-rust / website 三个 job 全部 skipped(改动只落 docs/**)、line-limits job 当时尚未存在(它由本批 7476fd0b 才加入);失败停在 docs job 的 Docs check 步骤 —— 该提交干净树上 docs-check 本身就是 exit 1(扫描 257 个 Markdown 文件,报「失效相对链接 20 处」,另有 5 个文件未收录索引的警告)。⇒ 本文档初稿的根因归因「继承来的 workflow 引用本仓不存在的路径(旧 job 为 client / ai-gateway / sync-service)」不成立,已更正:pr-check.yml 全部 15 个历史版本里都没有这些 job,那次运行的 changes 过滤路径也真实存在(唯一对不上的是写成仓根的 .docscheckignore,实际路径为 docs/.docscheckignore;该条 glob 惰性失效,且 docs/** 已覆盖同一批文件)。那套 client/ / ai-gateway / sync-service 的描述属于 scripts/validate-all.mjs(重构前遗留,步骤指向本仓不存在的 client/、server/ai-gateway、server/sync-service)—— 计划 L842 记对了,是本文档张冠李戴。「最近 5 次全 failure」属实,但要分清两层真实根因:更早 4 次(7b432c1e / 4fe09e08 / 02aba9a2 / 68bf43a1)失败在 app-rust job 的 Lint (clippy) 步骤(同次 cargo test 是 2334 passed / 0 failed),最近一次(2089042b)才失败在 docs。⇒ 推送后 CI 是否绿,本批未经实测:本地树当前 docs-check(267 文件 / 167 检查)与 line-limits --full 都 exit 0,但那次运行里 app-frontend / app-rust / website 全是 skipped ⇒ 这三个 job 推送后能否跑绿没有证据;本机以 CI 同一条命令复跑 cargo clippy -- -D warnings(clippy 0.1.96)仍 exit 101、15 个 error(manual_contains / needless_lifetimes / collapsible_if / too_many_arguments / type_complexity / unwrap_or_default / let_and_return / cloned_ref_to_slice_refs / manual_flatten)⇒ app-rust 大概率仍会红。故此处既不写「CI 恒红」、也不写「兜底已就位」。⇒ 在 CI 能真正跑绿之前,本地直跑 --full 是唯一生效的 (e) 守卫。
工具链真相 2 · 门禁的失败路径曾是破坏性的(lint-staged@15.5.0,2026-09-11 实测并加固)
lint-staged@15.5.0 默认 stash:true + hidePartiallyStaged:true,其失败路径是「先毁工作树,再赌一次还原」:git stash create + stash store 备份 → 跑任务 → 失败则 git reset --hard HEAD(清掉整个工作树)→ git stash apply --quiet --index <备份> 重建 → cleanup 把备份 stash drop(实现见 node_modules/lint-staged/lib/gitWorkflow.js 与 runAll.js)。
⇒ 实测曾使未暂存改动当场消失:暂存一个故意越线的探针文件、同时在 docs/standards/README.md 留一处纯未暂存改动,提交 [FAILED] 后那处改动从工作树消失,且 git stash list 为空(只剩悬空 commit c85e00a1);git diff HEAD c85e00a1 证明备份里确实含该改动 ⇒ 还原那一半没兑现。复跑同一实验时内容侥幸还在,但整个文件被重写(LF→CRLF、sha256 变化)—— 「内容还在」是那次 apply 恰好成功,不是设计保证。
⇒ 加固:.husky/pre-commit 改为 npx lint-staged --no-stash --no-hide-partially-staged(上游 --no-stash 本就 imply 关掉 hide;第二个 flag 仍写死,防将来 imply 变化后悄悄退回「藏了未暂存部分却没有备份可还原」—— 那条路失败时必丢)。加固后 lint-staged 在任何路径都不碰工作树与索引(不 stash create、不 reset --hard、不 checkout --force、不 stash drop),而拦截力不变(实测 [FAILED] + exit=1、husky - pre-commit script failed (code 1)、HEAD 未动、未暂存改动 sha256 前后相同)。
代价(须知):① 门禁看到的是工作树态,不再是「隐去未暂存部分的索引态」—— 本仓两个检查都是全树只读扫描,看工作树反而口径单一,故可接受;② 落在受管 glob 上的部分暂存文件会在跑完时被整文件 git add ⇒ 不丢内容,但抹掉「只提交一半」的意图(提交前看 git status,MM 会变成 M );③ 部分暂存时会残留 .git/lint-staged_unstaged.patch(没有步骤再删它)。
补救(失败后怀疑丢了改动):备份是一个 WIP on <分支>: <HEAD> 的悬空 commit —— git stash list 为空不代表它不存在:git fsck --dangling 列出悬空 commit → git diff --name-status HEAD <备份ID> 先确认确实含你的改动 → git stash apply --index <备份ID> 整份还原(索引 + 工作树),或 git checkout <备份ID> -- <path> 只取回单个文件。
git gc --prune=now:这些悬空 commit 是万一丢失改动时的唯一找回途径(控制方那次丢失的改动,就是从 c85e00a1 找回来的)。
★ 二轮后(2026-09-11,31b59239):上述整类风险已从路径上消失 —— .husky/pre-commit 不再调用 lint-staged(见「工具链真相 1」),故上面写死的 --no-stash / --no-hide-partially-staged 与本节「代价」的 ②「MM 跑完被整文件 git add」③「残留 .git/lint-staged_unstaged.patch」都不再适用(实测:部分暂存文件跑完仍是 MM、文件 sha256 前后相同)。本节「补救」一条仍然有效(历史悬空 commit 依旧存在,找回方式不变;git gc --prune=now 依旧禁止)。
- 不写「自动替你决定」的能力;AI 一律默认关、可降级、须授权
- 不为了动效牺牲可及性:三档强度 + 系统 reduced-motion 优先 + 环境层幅度上限 2%
- 不为「活」而活:每个动效必须能归入四层纲领之一(响应 / 环境 / 编排 / 生长)