状态:设计已批准(2026-09-11 用户逐项裁决)· 待实施 定位:一次覆盖全站的前端重设计。回答用户的三个要求 —— ① 重新设计组件类型(是否有更好的组件负责已有功能)② 重新布局设计 ③ 为各组件添加动效 —— 并补齐用户未提到的基座、治理、未接线落地三类任务。 方法:三层只读侦察(未接线命令 / 组件与布局清单 / 动效与规格审计,证据均带
文件:行)+ 14 屏用户逐项裁决。 关联:长期优化清单 · UX 市场惯例审计 · 需求池 · ADR-010 · v0.20 原则:本地优先不破(数据不出本机、云端能力默认关闭且有本地降级)· 不引入路由库 · 不砍任何已接线功能 · 每批可编译可测试可回滚。
把「一份内容只有一种样子」的产品,改造成「一份内容有多种样子 + 会呼吸、会生长、会显影的纸」—— 在此之前先补上它从未有过的地基:token 层、原语层、视图层。
| # | 分叉 | 裁决 |
|---|---|---|
| 1 | 基座路线 | C 全部从代码:回写 ui-ux-system.md / theme.md 为目标态,壳层与视觉自由重设计 |
| 2 | 视觉方向 | C 活页(纸色 + 中文衬线正文 + 印章状态 + 到期刻度) |
| 3 | 材质语言 | D 显影(四档墨度 = 确定度;未确认档 3.22:1 + 三条升档规则) |
| 4 | 来源标记 | ① 剪报底纹,默认开启;②边注线不做;③套准角标不做 |
| 5 | 图标语言 | A 自绘线性图标集(约 44 个 / 1.75px / 小圆角 / 零依赖) |
| # | 分叉 | 裁决 |
|---|---|---|
| 6 | 收敛范围 | 10 类原语(Modal / z-index 标尺 / EmptyState / Loading / StatusLine / Toast / ConfirmDialog / Button / Surface / Text) |
| 7 | 删除哲学 | 甲 两档分级:低危可逆 → 撤销 toast 10s;高危不可逆 → 确认框并列明级联;级联不给撤销 |
| 8 | 软删/回收站 | 不做(需 schema 迁移),登记为独立技术债 |
| 9 | 拆件顺序 | NotesPage → NoteListView → SessionDetailPanel → ClassroomPage(行为等价) |
| 10 | ADR | ADR-032 / 033 / 034 / 035 四条 + 修订 ADR-010 |
| 11 | 原语消息通道 | 保留「探针」与「骨架屏微光」两条旧规格(分工:骨架=已知结构,探针=时长未知) |
| # | 分叉 | 裁决 |
|---|---|---|
| 12 | 导航形态 | A′ 顶部 Tab(8 项:7 域 + AI 对话;设置下沉右上齿轮)+ ⌘K 命令入口 |
| 13 | 域数纪律 | 新增能力进域内页签,不再升格为域(v0.20.5 已写下但未执行到底的原则) |
| 14 | 顶栏溢出 | 两级:≥1180 图标+文字;1024–1180 仅图标+悬浮名;<1024 由最小窗兜底 |
| 15 | 相变壳层 | 两态:采集态(LIVE 仪表 + 域导航隐藏)· 复习态(零 chrome)。不做四态 |
| 16 | 列契约 | 三列上限 + 单一注册表 ColumnSpec + 断点 1024/1100/1180 + --nav-h 变量 |
| 17 | 窗口 | 默认 1280×800,最小 1024×640;补 html,body,#root reset;滚动条 6px |
| 18 | AI 对话 Tab | 保守保留为第 8 项 —— dock 是否承载 ChatPage 全部能力尚未核实,先核对再删 |
| # | 分叉 | 裁决 |
|---|---|---|
| 19 | 视图层四部件 | ViewSpec · viewRegistry · ViewSwitcher 原语 · 依赖方向 领域→视图→容器→原语 |
| 20 | 本批视图 | 会话 4(三轨 / 印样 / 原文 / 卡片流)· 笔记 3(原文 / 卡片流 / 带证据三轨)=新增 5 个组件 |
| 21 | 范围纪律 | 其余域的视图登记不排期 |
| 22 | 三条硬约束 | 原文永远保留 · 非默认视图惰性挂载 · 编辑态切视图先 flushSave(失败则阻断) |
| 23 | 视图记忆 | 按对象类型记(view:default:{objectType}),不按单个对象 |
| # | 分叉 | 裁决 |
|---|---|---|
| 24 | 引擎 | GSAP(core + Flip + ScrollTo + CustomEase)+ @gsap/react/useGSAP |
| 25 | 纲领 | 「活的纸」四层:响应 / 环境 / 编排 / 生长。统一语法而非限制数量 |
| 26 | 基调 | 丙 双基调:凡有「读数」的界面用精密仪器,凡有「文字」的界面用纸墨 |
| 27 | 强度档 | 三档(节能 / 标准 / 丰富),系统 prefers-reduced-motion 优先于档位 |
| 28 | 「不做」清单 | 从 7 条降至 3 条(3D 翻转/粒子 · 夸张响应 · 页面转场滑动),且降级为材质判断而非设计原则 |
| 29 | 用户纲领 | 用户明确要求:「充满动效、充满创新设计、充满生命力,而不是呆板死板」 —— 本节为准绳 |
| # | 分叉 | 裁决 |
|---|---|---|
| 30 | A 桶 | 能接入 UI 的尽量接入(15 条 → 本批 12 条 + 登记不排期) |
| 31 | B 桶 | 4 条接入 UI;3 条从 IPC 撤下但保留内部函数 |
| 32 | C 桶 | 除视频档案四连外删去 |
| 33 | 视频档案四连 | 删 3(video_profile_by_kind / video_profile_spec_by_kind / remember_video_profile)· 留 video_profile_memory(诊断)· 留 video_profile_for_spec(档位读端) |
| 34 | 档位通道 | A 做完整:start_live_session 加 tier + 记忆加 tier 字段 + 新 remember_video_profile_tier 命令 |
| 35 | 标签线 | A 补完:标签可写 + 标签色成对 + tag_colors 补种子/迁移 |
| 36 | AI 补缝三连 | C 全删 + 连带模块 + 修订 ADR-010 为退役 |
| 维度 | 实测 |
|---|---|
| 壳层 | 无路由;useState<Page> + 9 个顶部 Tab;9 页全部常驻挂载(display:none);13 个窗口级状态,其中 9 个是手写「带参路由」focus* 字段 |
| 组件 | 131 个非测试组件,0 死组件;25 个 >300 行;4 个 >600 行硬限违规(ClassroomPage 724 / SessionDetailPanel 656 / NoteListView 609 / NotesPage 602) |
| 样式 | 2,256 处内联 style / 仅 3 处 className / 0 个 CSS 变量 / 88 个不同 hex / 2,533 处 hex 字面量;App.css 是未 import 的死文件且非合法 UTF-8 |
| 弹层 | 20 个手写全屏弹层 · 17 个各不相同 z-index · createPortal 0 · role="dialog" 0 · 焦点陷阱 0 · 无退出动画机制 |
| 重复实现 | 空态 44 · 加载态 85 · 错误行 196 处 / 76 文件 · 弱化文本 251 · 卡片边框 180 · toast 4 套 · 确认框 2 套(21 处) · markdown 渲染器 3 套 |
| 布局 | useColumnLayout 只被 4/9 页采用;ChatPage 硬编码 240、GoalsPage 硬编码 380;calc(100vh - 56px) 复制进 7 个文件 |
| 动效 | 0 个 @keyframes;5 条存活 transition;1 条坏动画(ChatMessageList.tsx:147 引用不存在的 chatBlink);prefers-reduced-motion 0 处;无动效库 |
| 包体 | JS 2,093.85 kB / gzip 651.25 kB(单个 chunk,零代码分割);performance.md 预算为 <200KB gzip → 超标 3.26 倍 |
| 未接线 | 334 个 Tauri 命令中 47 个前端从未调用;其中 30 个连 Rust 内部也无调用方 |
2026-09-12 批 2 回写(原文一律保留):上表「包体」行的 651.25 kB 是批 2 开工前的过期快照 ——
dev@f12aba6d实测 2,106.46 kB 原始 / gzip 654.72 kB(+12.61 原始 / +3.47 gzip),故「超标 3.26 倍」应作 3.27×。 批 2 已收口(2026-09-12,e46e0e82..9921767c):首屏 JS gzip 654.72 → 92.79 kB(−85.83%)⇒ ✅ 达标(预算来源docs/standards/performance.md:28的 < 200 kB gzip,守卫scripts/check-bundle-budget.mjsexit 0,余量 107.21 kB)。 诚实代价(不许省略):全部 JS gzip +12.91 kB(+1.97%)·>500 kB警告仍在(vendor-editor208.59 kB,懒 chunk)·dist总量只降 4,415 B(−0.14%),59 个 KaTeX 字体 1,072,948 B 一字节未动 ⇒ 磁盘与安装包不因此变小。 包体瓶颈清单、逐条复现命令与 follow-ups 见 批 2 实施计划 §收口回写(批 3+ 计划的前置输入就是该清单)。
2026-09-12 批 3 回写(原文一律保留,只加注)—— 本表 4 处已漂移(D1–D7 中的 D1/D2/D7 + D3/D6 见 §6.2) D1 · 「壳层」行逐字写「9 个顶部 Tab」——不完整:批 3 开工时顶栏的真实形态是 9 个 Tab(含「⚙ 设置」)+ 对话面板钮 + 采集徽标 + AI toast(
App.tsx:286-380,四项同在一行)。批 3 后:8 个域 Tab + ⌘K + 采集徽标 + 齿轮(设置下沉为齿轮),AI toast 移出导航行(进 fixed 覆盖层)⇒ 本行是开工前快照,今日形态以 §6.1 与其回写注为准。 D2 · 「布局」行逐字写「useColumnLayout只被 4/9 页采用」——页数一致、处数不同:实测 4 页 / 7 处(NotesPage一页 3 处)。批 3 后:9/9 页的目的地都在shell/columnRegistry.ts里,执行仍由该 hook(7 处旧调用点 + 4 处新接入)。 D7 · 「壳层」行逐字写「9 个是手写『带参路由』focus*字段」——实测 10 个(多focusChatId)。批 3 一个字段未删(只做入口收敛,状态机归批 5)。 D4 · 审计侧(不在本表):审计 J1-8 写「56px 魔数硬编码三处」,实测 10 处 / 9 文件(App.tsxheight +AiConversationDocktop + 8 个页面的calc(100vh - 56px),其中ReviewPage占 2 处)——批 3 T2/T3 已把这 10 处全部改为消费--ed-nav-h。审计文档本身未改(归批 8 的文档 pass)。 D5 · 审计侧(不在本表):审计落点NotesPage:395/App:225因批 0-C2 拆件已过期(行号不再指向原处)——只登记,同归批 8 的文档 pass。
⚠️ [DEAD]标记有污染:原侦察的「有无内部调用方」判定被测试文件引用污染(例:set_tag_color实际零调用,因被自己单测引用而被误判为「有内部调用方」)。实施删命令时必须逐条重新确认一次调用方。
红线(不得触碰)
- 本地优先:数据不出本机;云端能力默认关闭、须用户授权,且必须有本地降级路径。
- 不引入路由库:延续「页面保活挂载」模式;导航形态可改,技术底座不换。
- 不砍任何已接线功能:所有视图切换都是「+1 种形式」,不是「换掉原来的」。
- 每步可验证:每批结束
npx tsc --noEmit0 错 ·npx vitest run全绿 ·cargo test全绿。 - 行数红线:新原语必须是独立小文件;不往 4 个超限文件里加代码,先拆再加。
- 后端数据模型零改动 —— 除下列两处经批准的例外。
经批准的两处例外(各自需登记原因 / 影响面 / 回滚方式)
| # | 例外 | 原因 | 影响面 | 回滚 |
|---|---|---|---|---|
| E1 | MemoryEntry 增加 tier 字段 |
档案记忆库根本没有 tier 轴,导致「画面档位选完不生效、也不跨会话记住」 | video_profile_memory.json 序列化结构 + lookup/apply 路径 |
旧 JSON 无该字段时按 None 读取(向后兼容读,无需迁移) |
| E2 | tag_colors 补种子/迁移写入 |
表建了但永远没有数据,导致前端色板第三档恒不生效 | 一条迁移 + 标签色写入路径 | 迁移可空跑;标签色本身是可逆 UI 状态 |
🔻 批 6 收口就地加注 · 红线 6 的第三处例外 E3 / E4 / E5(R0.1 第 1 条①② · R5.4 / R5.5 / R5.5-b;2026-09-13,上面原文一字未改): 上面
:127的「除下列两处经批准的例外」与:129的「经批准的两处例外(各自需登记原因 / 影响面 / 回滚方式)」按本加注读作三处;上表两行原文保留,新增三行逐列如下(依据 = 用户 2026-09-13 裁决「批 6 范围 = B · 连承载面一起建」⇒ 三条硬后果第 1 条)。三条共同约束(逐条适用):只读 / 不新增表 / 不改既有字段与既有 SQL 文本的语义 / 零迁移(flashcards建表后零ALTER TABLE;CARD_COLUMNS不动);都不触碰 AGENTS.md §10 的「SQLite schema / 迁移」面。
# 例外 原因 影响面 回滚 E3 Flashcard+= 只读字段intervalDays(camelCase;Rust 4 文件 / 5 处 + 前端可选字段)真实间隔前端今天拿不到,但后端已经算出来了( scheduler.rs:69的interval_days: f32与:99的max(1.0)),而review_card的返回只给state_json/due_at、写库只有UPDATE flashcards SET state_json = ?1, due_at = ?2⇒ DB 无 interval 列;而stateJson的契约是「后端调度契约,前端透传不解析」⇒ 前端不得用dueAt差分或字符数自造「真实间隔」Flashcard是 6 条命令的共享返回类型 ⇒ 字段会同时出现在list_due_cards/review_card/quiz_group_cards/create_model_card/list_group_cards/model_card_from_note的返回里(本批只消费前两处,其余四处如实登记为「顺带变化」)。前端app/src/types/notes.ts加可选intervalDays?: number(零夹具改动)。🔴 两个精度域必须在类型注释里显式声明:review_card路径 = 精确值(当场覆写 ——⚠️ 陷阱:该函数用..card结构体更新语法,不覆写会漏出旧值);行派生路径 = 整天粒度(row_to_card由dueAt − stateJson.lastReviewMs反推max(round(…),1))删字段 + 还原 5 处( types_note.rs·db_flashcards.rs×2 ·commands_flashcards.rs·types_contract_tests.rs的追加行)+ 删前端可选字段。零迁移、零 SQL 变更 ⇒ 不影响任何已落库数据E4 新增只读 IPC session_audio_path(命令注册 312 → 313)音频真的落盘且已接线,但前端拿不到路径: audio_store.rs写{data_dir}/session-audio/{session_id}.wav(16 kHz 单声道 PCM16,44 字节 RIFF 头,~115 MB/小时);播放三件套已现成(tauri.conf.json:24的 CSP 已含media-src … asset:、:25-28的assetProtocol.enable=true+ scope 覆盖app_data_dir)⇒ 🔴 本批零tauri.conf.json改动(AGENTS.md §10 该审查面不触发)本批唯一的新增 IPC:入参 session_id: i64;出参Option<SessionAudioRef>(字段只许path/aligned/durationMs——aligned自证量必须到 UI,Option<String>装不下);计数 312 → 313。🔴 安全三条:① 必须校验入参 ② 路径必须限定在应用数据目录内(不许把任意路径透传给 asset protocol)③ 不许前端fetch()整取音频 ⇒ 只许<audio src>。⚠️ 适用范围硬边界:只有实时采集会话有音频;导入会话恒Ok(None)删命令 + 删注册行 ⇒ 计数回 312;前端删调用点即回到「只读时间轨、无音频播放」。零依赖变更、零 tauri.conf.json改动E5 WAV 轴 ≡ 会话轴:写块路径按 chunk.timestamp_ms的空档等长补静音 + 失效安全 +aligned自证量今天 segments[].start_ms / 1000不能当audio.currentTime:start_ms是会话纪元墙钟 −total_paused_ms,而 WAV 轴 = 已写样本数 ÷ 16000、纯追加、无任何静音填充。⚠️ 暂停本身不产生偏移(端点Stop↔ 时间戳冻结严格抵消);间隙来自静默窗根本不产包 ⇒ 偏差 D2 最危险且无上界(大量静默的课程录音可达分钟级)。「只暴露first_sample_ms + samples_written」的最小方案只修 D1、会交付一个「看起来对、实际会漂」的播放头live_session*.rs(AGENTS.md §10 名单内 ⇒ 该任务必须显式执行 §10 审查记录)·audio_store.rs(write_chunk加timestamp_ms入参 + 对齐簿记 +finalize写 sidecar)·live_session_loop.rs一个调用点 · 新纯函数audio_align.rs+ 测试 ·audio_store_tests.rs的既有调用点改签名(必要连带,只改调用形态、不改任何期望值)· ADR-013 就地加注。失效安全语义:时间戳缺失 / 非单调 / 超大空档(>MAX_GAP_MS= 10 分钟)⇒ 退回纯追加并置aligned = false(绝不静默分歧),不丢样本、不阻断会话主链路。🔴 历史录音必须如实区分:本修复之前的 WAV 不保证对齐 ⇒ UI 对无基准的录音不得假装精确;禁止用恒为true的字段充当该标记还原 1 个签名 + 1 个调用点 + 删 2 个新文件 + 停写 sidecar(补静音只影响新录音,既有 WAV 一字不动); aligned随命令一同删除。零新增依赖、零迁移、零新数据面① 🔴
cargo test --test app_lib_tests本批真跑(R0.1 第 1 条③,不得把「未跑」写成「已跑」):running 2335 tests→test result: ok. 2329 passed; 0 failed; 6 ignored,exit 0(读数出处:task-34-report.md§3)。② 例外 E4 的落地实测:注册表 313 / 313 / 0(定义 313 / 注册 313 / 重复 0)。③ 逐条细则与「①域(精确值)不落库」的完整口径见ADR-035的「后端契约例外」节(本批定稿)。
| 变量 | 亮(主) | 暗(夜读) | 用途 / 约束 |
|---|---|---|---|
--bg-sunken |
#F1EEE7 |
#100F0E |
输入槽 / 骨架 / 内嵌 |
--bg-canvas |
#FBFAF8 |
#141312 |
窗口底(纸) |
--bg-surface |
#FFFFFF |
#1C1A18 |
卡片 / 列 / 阅读面 |
--bg-raised |
#FFFFFF + --shadow-1 |
#24211E |
弹层 / 菜单 / 浮窗 |
--border |
#EAE7E0 |
#2E2A26 |
横格 / 分隔 |
--border-strong |
#C9C4B8 |
#423C36 |
输入框 / 刻度底 / 引线 |
--ink-4 未确认 |
#909088 |
#6E6A62 |
3.08 纸 / 3.22 面(暗 3.45 / 3.22)—— 过渡态,见 4.3 |
--ink-3 已重打分 |
#6E6E68 |
#9A958B |
4.92 / 5.13(暗 6.23 / 5.82) |
--ink-2 已确认 |
#3A3A36 |
#D6D1C8 |
10.95 / 11.42(暗 12.21 / 11.41)—— 正文基准 |
--ink-1 已改写 |
#1A1A1A |
#F5F1E8 |
16.68 / 17.40(暗 16.46 / 15.39);唯一使用字重 +1 档的档位 |
--mark-clip |
#F4F1E9 |
#221F1B |
剪报底纹(默认开) |
--stamp |
#B3271E |
#E0604F |
唯一非中性色,只用于状态戳 |
--ok 掌握 |
#2F7A4F |
#4FAE74 |
掌握 / 已毕业 |
--due 到期 |
#9F5E10 |
#E0A44B |
4.93 / 5.14(暗 8.47 / 7.92)· 剪报底 4.56(第二次修正,见下)· 到期刻度 / 低置信点线 / 记忆语义文字 |
--link |
#1F5FBF |
#6E9BE8 |
链接 / 时间码 / 引用 |
--overlay |
#1A1A1A(配 --ed-overlay-alpha: 0.34) |
同左 | 弹层遮罩基色 —— 两档同值:遮罩是叠加在内容之上的中性压暗,不随主题翻转 |
变量前缀:上表为可读性省略了前缀,实际变量名一律带
--ed-(如--ed-bg-canvas、--ed-ink-2)。前缀沿用theme.md既有意图,并避免与第三方 CSS(katex /@xyflow/react)的变量碰撞。
两组 token 的交付形态(防止批 4 迁移时重新硬编码): ① z-index 六档标尺以 TS 模块交付(
app/src/ui/zIndex.ts,见 §5.1 与批 0-A 计划 Task 4),不作为 CSS 变量 —— 组件以zIndex("modal")消费它;写成 CSS 变量反而会重新打开「谁都能随手写个数字」的口子。§4.2 表中列 z-index 只为集中陈述档位值,不代表它是 CSS 变量。 ②--ed-shadow-1/--ed-shadow-2已定值(2026-09-11,用户裁决「纸感双层暖墨」;批 0-D 落地):
- 亮档低层
--ed-shadow-1(菜单 / 浮层 / 小卡)=0 1px 2px rgba(28,25,23,.06), 0 4px 12px rgba(28,25,23,.08)- 亮档高层
--ed-shadow-2(Modal / 浮窗)=0 2px 4px rgba(28,25,23,.06), 0 12px 32px rgba(28,25,23,.14)- 暗档不用投影,改白色反相描边
0 0 0 1px rgba(255,255,255,.06)(沿用docs/product/ui-ux-system.md:204的既有做法)- 定值依据:全仓
boxShadow实测 38 文件各写一份、18 个互不相同的值且天然聚成两档(低0 4px 12px .12×6;高0 8px 24px .14×5 /0 10px 40px .15×4 /0 12px 40px .2×3)—— 用户选的是纸感方向而非照抄这两簇。批 4 迁移时不得临时硬编码阴影。- 命名关系:
ui-ux-system.md:186原有的--ed-shadow-card(亮/暗各一)被--ed-shadow-1取代,批 0-D 在该文档注明并给出新值(该文档属 AGENTS.md §10,文档与代码同提交)。
对比度纪律:亮档强调色不可照搬暗档 —— 同一
#17C3B2在暗底 8.6:1、在白底仅 2.2:1(实测 2.21)。故两档各给一值。表中数字均为实测(WCAG 2.1 公式,「纸」=
--bg-canvas、「面」=--bg-surface)。两张底不同:正文实际坐在面上,故正文类断言以面为基准。上一版规格写的是估算值(11.6 / 5.0 / 3.1 / 11.5),与实测有 4 处出入,已按实测修正 —— 这也是为什么 token 层必须配对比度测试(见批 0-A 计划 Task 2/3)。
--due亮档从#B26A12改为#A05F10(第一次修正):原值对纸底仅 4.06:1、对面 4.23:1,低于正文 4.5:1 线,而它要承载「记忆语义」文字(如「3 天后」)。新值 4.86 / 5.07 达标。
--due亮档第二次对比度修正(2026-09-11,批 0-D Task 1 落地):#A05F10→#9F5E10。触发底是剪报底纹(--ed-mark-clip #F4F1E9)这第三种底:#A05F10在其上仅 4.4950:1,低于正文线。求解规则 = 保持色相、RGB 三通道按同一系数f缩放(hex(round(ch × f))),取满足「① 纸#FBFAF8≥4.5 且 ② 面#FFFFFF≥4.5 且 ③ 剪报底#F4F1E9≥4.55」的最小加深量 ⇒f = 0.994(余量 0.05 是硬要求:#A05F10正是「卡在 4.4950」的反例,hex 量化与将来底色微调都会吃掉没有余量的值)。实测:剪报底 4.5571 / 纸 4.9309 / 面 5.1436。暗档#E0A44B不动(剪报底 7.4863 本就达标)。旧值#A05F10在剪报底上 <4.5 的反例守门落在app/src/ui/contrast.test.ts。
| 组 | 值 |
|---|---|
| 正文字体 | "Source Han Serif SC", "Songti SC", SimSun, serif · 15.5px / 行高 1.9(= 29.5px) · 只随包 400 / 600 两个字重(子集 3–4MB) |
| 界面字体 | "Inter", "Segoe UI Variable", "Microsoft YaHei UI", system-ui, sans-serif(标题/按钮/标签用黑体;system-ui 为最终回落槽) |
| 等宽字体 | "JetBrains Mono", Consolas, ui-monospace, monospace + tabular-nums(时间码 / 元数据;monospace 为最终回落槽) |
| 字阶 | 25/34·600 · 17/24·600 · 15.5/29.5·400 · 13/20·400 · 12/18·500 · 11.5/16·500 mono(下界 12px 约束正文与界面文字;11.5/16 mono 是唯一被点名的例外 —— 等宽用于时间码与元数据,11.5px 等宽的可读性高于同尺寸黑体。10px / 11px 一律消灭) |
| 间距 | 4 · 8 · 12 · 16 · 24 · 32 · 48 |
| 圆角 | 3 印章 · 5 控件与卡 · 8 面板 · 10 浮层 |
| 图标 | 24 网格 · 描边 1.75 · 尺寸 16/20/24 · currentColor · 小圆角 |
| z-index | t1=10 吸顶 · t2=100 常驻面板/dock · t3=200 锚定弹层/菜单 · t4=300 Modal+遮罩 · t5=400 Modal 内嵌 · t6=500 Toast |
字重与随包字体的关系:上表「正文字体」行的「只随包 400 / 600 两个字重」仅约束衬线正文字体(思源宋体子集);
500两档(12/18、11.5/16)属界面字体体系,由系统字体栈提供 —— Inter 与 Segoe UI Variable 有 500;微软雅黑只有 400/700,故在无 500 的系统上回落为 400,这是可接受的降级(小字标签用 400 亦成立),不因此增包第三个字重。字阶的 CSS 交付形态(批 0-D Task 1 落地):字阶除人读串
SCALE_TOKENS.typeScale外,另以 6 档 × 3 属性 = 18 个 CSS 变量交付 ——--ed-type-<n>-size/--ed-type-<n>-line/--ed-type-<n>-weight(n= 生成器TYPE_SCALE下标 + 1,自 1 起)。第 3 档的无单位行高1.9统一为29.5px(15.5 × 1.9 = 29.45,按可用精度取一位小数 0.5px;差 0.05px 不影响任何排版判定,且比 29px 更接近真实行高)—— 无单位与 px 两种写法并存会让 CSS 无法统一消费。人读串由同一份结构化真源派生(TYPE_SCALE.map(...)),不允许各写一份。
🔻 批 4 收口就地加注(2026-09-12,§4.2 上表「圆角」行原文逐字保留**:
| 圆角 | 3 印章 · 5 控件与卡 · 8 面板 · 10 浮层 |)—— 批 4 新增第 5 档pill:上表是四档、今日实盘是五档:
- 实测处数 = 3(域 =
app/src/**的.ts/.tsx减*.test.ts(x)减ui/primitives/**,先剥注释;切片内处数同为 3):components/AiConversationDock.tsx:52·components/RefineWorkbench.tsx:405·:410。- 判定依据:控制方 B17 第 2 条逐字「切片内实测处数 ≥3 ⇒ 回来给原语加一档
radius="pill"」⇒ 3 ≥ 3 ⇒ 加档;落 T17-A 的2360c3d9(feat(ui): add pill radius tier to surface,5 个文件 =Surface.{tsx,css}+Surface.test.tsx+style-contract.test.ts+style-seams.test.ts)。- 代价(必须一并读):① 本表没有
pill档,token 真源SCALE_TOKENS.radiusScale与app/src/ui/tokens.drift.test.ts:52的toEqual([3,5,8,10])今日仍是 4 档 ⇒ 原语走var(--ed-radius-pill, 999px)兜底(同Text.css的数值兜底范式);补 token 档要动四处(app/scripts/gen-tokens.mjs·ui/tokens.gen.ts·ui/tokens.css·ui/tokens.drift.test.ts:52)—— 归批 5/6;② 出处更正:本行是「四档圆角」的唯一原文出处(docs/product/ui-ux-system.md无「四档圆角」字样,其圆角表述是 2026-08-24 旧目标态、§十一 自陈「待批 8 统一回写」⇒ 批 4 不动它);③ T17-B 没有落点用到pill(3 处药丸落点按 B20 第 3 条属控件/徽标形态 ⇒ 不迁,登记在案)。⚠️ 一并登记的守卫性质:ui/primitives/style-seams.test.ts的SURFACE_CLASSES与toHaveLength(13)实测是自计数式守卫(变异 MS1b:拿掉pill且同步把 13 改回 12 ⇒ 绿);完整性方向的牙在style-contract.test.ts的Record<SurfaceRadius, string>(缺键 = TS2739)。是否升级为真判据 ⇒ follow-up(批 4 计划 §收口回写 §七)。
四档墨度在浏览态下(「面对」= --bg-surface,正文实际所在的底):已确认 11.42:1 · 已重打分 5.13:1 · 未确认 3.22:1(低于正文 4.5:1 线)。规则:
- 未确认档是过渡态,不得承载唯一关键信息;
- 任何交互(悬停/聚焦/选中)立即升到正文墨度;
- 进入「审校模式」时全部升到 ≥4.5:1 —— 即「你真正开始读它的时候,它一定够黑」。
**🔻 批 4 收口就地加注(2026-09-12,上面三条原文一字未改)—— 条件 ③ 在仓内无实现,这一事实直接决定了批 4 的
Text取值:
- 实测:
审校模式/proofread这一状态在app/src/**里没有任何实现(无该模式的开关、无「全体升到 ≥4.5:1」的墨度切换逻辑)⇒ 条件 ③ 今日不可满足(不是「已满足但没测」,是没有这个模式)。- 后果(T16-B 的保守取值,可逆):
Text迁移的墨度判定按判据原文「三条任一不满足 ⇒ 取ink-3」执行 ⇒ink-4全程 0 使用(tone一律ink-3= 5.13:1),仓内ink-4的生产调用点 = 0。- 去向:批 5/6 补「审校模式」实现之后,
ink-4的 3.22:1 例外才可能被合法使用(这是本行 ③ 的前置条件)。出处:task-16b-report.md§2 · 控制方 2026-09-12 追认。- 不受影响的两条:① 未确认档仍是过渡态、不承载唯一关键信息;② 交互立即升到正文墨度 —— 都在批 4 的
Text档位与interactive语义内有落点。
🔻 批 6 收口就地加注 · 条件 ③ 的去向 + 环境层第 ③ 件的落点归属(R6.2 · R11.3 · R12.4 · R62⑤;2026-09-13,上面原文与批 4 加注一字未改):
- 🔴
ink-4的盘点终态 = 保持 0 生产调用点:上面批 4 加注的结论在批 6 未被推翻(本批零动作、未承接「审校模式」)⇒ 条件 ③ 的去向 = 批 7/8(ADR-035的「登记」节逐字同名一条)。本批不为此新增任何例外。- 🔴 口径更正(R11.3 的落点归属,勿混用):环境层第 ③ 件「未确认段落墨度极缓慢起伏(幅度 2%)」的落点不是
ink-4,而是lowConfidenceClass()+ 类名ed-text--low-confidence(落点app/src/components/structuredBlocks.ts,消费者见下)——ink-4与它没有实现关系。⚠️ 兑现度如实登记:该件的生产调用点终态 = 1 处(components/session-detail/SessionRawView.tsx:137),而 R12.4 要求 ≥2 ⇒ 差 1(T25 / T27 均未补第 2 处;views/session/SessionTriTrackView.tsx只剩 5 行余量)⇒ 本批只登记、不补(这是 R12.4 设计来抓的东西,不许用 T13 的 CSS seam 充数)。- 环境层四件的逐件兑现度(R11.3 逐字「不得把『落 seam 但 0 调用点』算作已交付」):① 探针摆动 =
Loading.css的.ed-probe(既有,批 6 只对齐名单)· ② 采集脉冲 = seam 就绪、承载面未落(LiveBar用波形条阵列,未做脉冲节拍)· ③ 未确认段落墨度起伏 = 1 处调用点(要求 ≥2,差 1) · ④ 到期刻度微光 = 落在DueScale的静态形态上(未做循环微光)。🔴 另:「丰富」档只兑现了频率提高,幅度上限未动(真正依据 = 本规格 §8.6.1 第 1 条逐字「环境层幅度上限不动」,不是「CSS 无原语」——逐档 keyframes 是可行的)。
🔻 批 7 收口就地加注 · 「审校模式」的规格定义**(C9.18;2026-09-13,上面原文与批 4 / 批 6 加注一字未改)—— 🔴 本节只定义,不实现:**
- 🔴 状态逐字:未实现。 本节补的是条件 ③ 的前置定义(「进入审校模式」到底指什么);批 7 不写一行实现代码。⇒ 登记为批 8 输入(§11-7 与批 8 的输入清单里按名登记)。
- ① 入口(哪个面、怎么进):阅读面(
notes对象)的全局开关,载体 =App壳上的一个模式位(<html>上的data-proofread="on")+ 一个可发现的入口按钮(⌘/Ctrl+Shift+R,与既有⌘K/Esc同族的键盘纪律)。不进视图注册表(它不是第四种「视图」,而是所有视图共同的面)⇒ 与 §7.2 的视图计数无关。- ② 作用域:当前阅读面的全部文本节点(含
NotesReadingColumn的每一种视图、卡片流行、印样正文;不含编辑器(RichEditorView)与弹层外的外壳 —— 编辑态已有自己的墨度语义)。作用域随焦点走而不是随路由走:切到别的对象 ⇒ 模式保持(它是「我此刻在审读」的用户意图),但只影响当前挂载的阅读面。- ③ 退出:三条等价出口(都必须能出):再按同一个快捷键 · 点同一个入口按钮 ·
Esc(同Modal的退出纪律);退出后墨度立即回到未进入前的档位(不得留任何中间态)。- ④
data-*形态(照data-motion/data-tone的范式):模式位写在<html>根元素上、不是类名(与 §8.3 的「载体逐字 =data-*属性,禁止用类名区分」同一条纪律)—— · 属性名data-proofread,取值"on" | "off"(缺省 =off,且不落属性——与data-motion的缺省形态一致); · 墨度侧不新增 token:审校模式是档位覆盖(条件 ③ 逐字「全部升到 ≥4.5:1」),不是第五档墨度。- 🔻 批 8 T11 就地加注 · 第 ④ 条的属性名消歧(2026-09-13;上面第 ④ 条的原文一字未改):第 ④ 条原文的
data-proofread与既有的「LLM 文本校对」同名不同物 —— 后者已占用proofread一族(src-tauri/src/commands_proofread.rs·components/ProofreadPanel.tsx·proofread_estimate/proofread_run;T11 实测,域 =git ls-files1,628 文件,时点4041eab5:子串proofread= 250 处 / 38 文件)⇒ 🔴 本模式的属性名取data-proofread-mode(控制方 §2 B2 逐字),不得用data-proofread。⚠️ 第 ④ 条原文出现data-proofread的三处**(本注插入前实测 = 本文件:235/:239/:241,域 = 规格全文)一律按本注改读为data-proofread-mode;取值口径一个字不改(两态"on" | "off",缺省 =off,且不落属性)。 ✅ 已落地的载体(批 8 T9):app/src/shell/proofreadMode.ts的PROOFREAD_MODE_ATTR = "data-proofread-mode";CSS 侧消费形态 =html[data-proofread-mode="on"](app/src/ui/proofread.css,由main.tsx在 token CSS 之后 import)。T11 实测:data-proofread-mode形态全仓 = 46 处 / 6 文件(域 =git ls-files,时点4041eab5)⇒ 名字已统一,没有任何生产代码再写data-proofread。- ⑤ 实现层(一次覆盖,不改调用点):纯 CSS 一层完成 ——
html[data-proofread="on"]下把--ed-ink-4的值指向--ed-ink-3(ui/tokens.css的变量覆盖;.ed-text--ink-4的规则一个字不用改)⇒ 「全部升到 ≥4.5:1」由变量重绑一次兑现,调用点零改动、零逐处判断。- ⑥ 今日实测(本节的两条读数):
tone="ink-4"的生产调用点 = 0 处 / 0 文件(正控tone="ink-3"= 201 处 / 94 文件 ⇒ 非「假 0」;负控zzz_no_such_symbol_zzz= 0);ink-4的任意形态(含类型联合 / token 定义 / 对比度判据 / 注释)在生产侧 = 5 处 / 4 文件,全部是「ink-4是过渡态、不得承载唯一关键信息」这类禁止性表述或定义,没有一处是把ink-4用在元素上。仪器:.superpowers/sdd/2026-09-12-frontend-redesign-batch7-unwired/tmp/t20/probe-spec-readings.mjs(只读;口径 =app/src/**的.ts/.tsx,PROD 排除*.test.*)。- 🔻 补时点(2026-09-13 · T21 补轮;上面那条读数的数不动,只补时点与漂移声明):上面写的正控
tone="ink-3"= 201 处 / 94 文件 是某个时点的读数 —— 🔴 它在fb73e313那棵树上逐字可复现(侦察单元已证),此后b72d4709(T20 的六条展示面)与 T23 又加了文件 ⇒ 数继续变。🔴 T21 于53bd0759用自己的仪器复测(入库域 =git ls-files;口径 =app/src/**的.ts/.tsx内子串tone="ink-3"的出现次数):PROD(排除*.test.*)= 214 处 / 99 文件 · TEST = 2 处 / 1 文件 · 全树app/src= 216 处 / 100 文件。- 🔴 纪律逐字:该数随时点变化,引用必须带时点(并带仪器与域)。
⚠️ 不得把216/100当成「真值」—— 它同样会漂;也不得把201/94当错值 —— 它是时点值。(本轮另见批 7 的「贴边件读数必须带时点」与「数字带时点」两条纪律,同源。)- 🔴 不得合并结案:条件 ③ 是环境层第 ③ 件之外的另一件事 —— 不能用「做了
lowConfidenceClass(未确认段落墨度起伏)」宣称本条已兑现(原文 §4.3 批 6 加注已逐字记载:ink-4与它没有实现关系)。批 7 对lowConfidenceClass的加宽(生产调用点 1 → 2)不改变本条状态:仍是未实现。- 🔻 批 8 T3 就地加注 · 第 ⑤ 条的覆盖落点更正(2026-09-13;上面第 ⑤ 条的原文一字未改):第 ⑤ 条逐字点名的落点
ui/tokens.css是生成物 ⇒ 不得在它里面写这一层覆盖。🔴 T3 实测:app/src/ui/tokens.css:2逐字「由 scripts/gen-tokens.mjs 生成,请勿手改。」·:3逐字「手改会被 src/ui/tokens.drift.test.ts 判失败。」;守卫本体 =app/src/ui/tokens.drift.test.ts:25-28(it("tokens.css 与生成器输出一致(手改即失败)")断expect(normalizeEol(onDisk)).toBe(normalizeEol(renderAll().css)))⇒ 手改必红。- ⇒ 🔴 批 8 的实际落点 = 新建
app/src/ui/proofread.css(控制方 §2 B1 逐字):在根元素模式位下把--ed-ink-4的值重绑到--ed-ink-3,同时不动app/scripts/gen-tokens.mjs与app/src/ui/primitives/Text.css。⚠️ 第 ⑤ 条原文的「ui/tokens.css的变量覆盖」一句按本注改读为「专用 CSS 文件(app/src/ui/proofread.css)的变量覆盖」;本注只改落点、不改机制 —— 第 ⑤ 条的机制仍是「纯 CSS 一层、调用点零改动、零逐处判断」。
底纹依赖「这段文字来自哪一路」。没有来源标记 → 按「无标记」渲染,绝不猜、绝不默认成某一通道;用户手写/改写的段落永远不标底纹。否则会出现「用户手写的句子被标成来自屏幕 OCR」这种事实性错误 —— 而这条底纹的全部价值就在于它可信。
前景裁决(2026-09-11 控制方,批 0-D Task 1 落地):剪报底纹只改背景,文字仍用所在层级的 --ed-ink-*,不新增前景 token。但 §4.3 的四档阈值是按「阅读面」定的 —— 换到剪报底就是换了一个底,故「底 × 墨」必须逐对实测(下列比值实测于 WCAG 2.1 公式,亮档底 --ed-mark-clip #F4F1E9、暗档底 #221F1B):
| 墨 | 亮档 / 剪报底 | 暗档 / 剪报底 | 判定 |
|---|---|---|---|
ink-1 |
15.4197 | 14.5564 | ✅ ≥4.5 |
ink-2 |
10.1204 | 10.7931 | ✅ ≥4.5 |
ink-3 |
4.5454 | 5.5052 | ✅ ≥4.5(亮档余量仅 0.045) |
ink-4 |
2.8489 | 3.0480 | ❌ 亮档连 3:1 过渡态例外都不满足 |
stamp |
5.7679 | 4.6533 | ✅ ≥4.5 |
ok |
4.6310 | 5.9688 | ✅ ≥4.5 |
due |
4.5571(第二次修正后) | 7.4863 | ✅ ≥4.5(修正前 #A05F10 仅 4.4950) |
link |
5.3968 | 5.8732 | ✅ ≥4.5 |
规则(写死):剪报底纹上只用 ink-3 及更深(--ed-ink-3 / --ed-ink-2 / --ed-ink-1);--ed-ink-4 禁止用于剪报底纹 —— 它的 3:1 例外只在阅读面上成立(面对 3.22:1),剪报底上亮档实测 2.8489、暗档 3.0480。反例守门断言落在 app/src/ui/contrast.test.ts(「ink-4 亮档不得用于剪报底纹」toBeLessThan(3)),同一文档规则同步写进 docs/product/ui-ux-system.md §九。
落地状态(批 0-D,2026-09-11):9 类原语已落地(第 10 类 z-index 标尺在批 0-A 已交付,本批只消费)。 目录
app/src/ui/primitives/(42 个文件,逐个 ≤300 行,最大 297),唯一导出面index.ts;契约见 ADR-033。本批不迁移任何调用点 —— §5.1 的现状病灶要到批 4 才收敛, 界面外观零变化是设计意图(§10)。
原语 实际文件(实测行数 · countLines()口径)TextText.tsx89 ·Text.css46 ·Text.test.tsx130SurfaceSurface.tsx97 ·Surface.css73 ·Surface.test.tsx168ButtonButton.tsx132 ·Button.css92 ·Button.test.tsx286ModalModal.tsx188 ·Modal.css81 ·Modal.test.tsx296 ·Modal.exit.test.tsx91ConfirmDialogConfirmDialog.tsx192 ·ConfirmDialog.css58 ·ConfirmDialog.test.tsx297ToastToast.tsx210 ·Toast.css65 ·Toast.test.tsx249 ·Toast.interrupt.test.tsx167 ·Toast.style.test.ts132EmptyStateEmptyState.tsx127 ·EmptyState.css81 ·EmptyState.test.tsx276Loading/Skeleton/ProbeLoading.tsx105 ·Loading.css79 ·Loading.test.tsx238StatusLineStatusLine.tsx94 ·StatusLine.css42 ·StatusLine.test.tsx267共享内核 usePresence.ts200 ·usePresence.test.tsx282 ·usePresence.node.test.ts71 ·useFocusTrap.ts122 ·useFocusTrap.test.tsx236 ·ime.ts18 ·ime.test.ts32接缝 / 导出面 / 守卫 motion.css74 ·index.ts45 ·style-seams.test.ts271 ·style-contract.test.ts214 ·motion-coverage.test.ts147行数口径(唯一有效):
countLines(),即[System.IO.File]::ReadAllLines(path, UTF8).Count—— 含空行的全部行数(禁用Get-Content/Measure-Object -Line/ 数0x0A字节)。 权威来源:逐文件数值以机器生成的 行数豁免登记 为准(node scripts/line-limits.mjs --write生成、--full校验,不要手改其数字);本表只是人读摘要。 注:本表所列原语全部 ≤300 行,在登记表内属人工追加的记录块(--write只重算 >300 行的登记区)⇒ 两份不一致时按上句口径在 HEAD 重新实测,再同步两份。
🔻 批 6 收口就地加注 · 这张 42 文件表的三副本同步**(R33.3 / R63.2 · T16 的二次刷新;2026-09-13,上表与上面
:260-262的原文一字未改): 上面countLines()表与ADR-033§1 的表、行数豁免登记 的人工记录块是同一张 42 文件表的三份副本**;:211的刷新规则要求三副本同步,而三份在批 6 收口时均已漂移 ⇒ 本节按 HEAD 提交树实测(countLines()口径;探针.superpowers/sdd/2026-09-12-frontend-redesign-batch6-motion/tmp/t35/primitives-42.txt,gitignored)逐值重列,三份副本一律按本加注读:
Text119 / 66 / 171 ·Surface98 / 85 / 175 ·Button132 / 100 / 286 ·Modal260 / 81 / 296 +Modal.exit.test.tsx91 ·ConfirmDialog202 / 58 / 297Toast257 / 76 / 249 +Toast.interrupt.test.tsx167 +Toast.style.test.ts134 ·EmptyState170 / 103 / 276 ·Loading105 / 79 / 238 ·StatusLine94 / 42 / 267- 共享内核
usePresence.ts / usePresence.test.tsx / usePresence.node.test.ts / useFocusTrap.ts / useFocusTrap.test.tsx / ime.ts / ime.test.ts= 200 / 282 / 71 / 122 / 236 / 18 / 32- 接缝 / 导出面 / 守卫:
motion.css335 ·index.ts48 ·style-seams.test.ts299 ·style-contract.test.ts296 ·motion-coverage.test.ts186- 与上表逐项漂移:
Text.tsx89→119 ·Text.css46→66 ·Text.test.tsx130→171 ·Surface.tsx97→98 ·Surface.css73→85 ·Surface.test.tsx168→175 ·Button.css92→100 ·Modal.tsx188→260 ·ConfirmDialog.tsx192→202 ·Toast.tsx210→257 ·Toast.css65→76 ·Toast.style.test.ts132→134 ·EmptyState.tsx127→170 ·EmptyState.css81→103 ·motion.css74→335 ·index.ts45→48 ·style-seams.test.ts271→299 ·style-contract.test.ts214→296 ·motion-coverage.test.ts147→186(其余 23 值与上表同)。- 42 个文件全部 ≤300 —— 唯一例外 =
motion.css335(.css不在行数门禁的SOURCE_EXT视野内;源文件最大 = 299)。批 6 给它追加了 6 次(T5 / T6 / T12 / T13 / T19 / T29),已越过 R11.8 的 ≤300 自律线 ⇒ 逐条登记在v0.22.md批 6 节的「诚实代价」。- 🔴 口径缺口(登记,R33.3 第 2 条):
:258的机器锚点<!-- line-count-src: … -->(本节与另两份各有一条)全仓 0 个读者 —— 规格:835/ 豁免表:211所称「门禁按files=重测」今日无实现 ⇒ 三副本同步只能靠人工。锚点保留待将来实现(它刻意不写数值,故它自身不会腐化)。
| 原语 | 吸收 | 现状病灶 |
|---|---|---|
Modal |
20 文件 | role="dialog" 0 · createPortal 0 · 焦点陷阱 0 · 无退出机制 |
| z-index 标尺 | 17 → 6 档 | 32 文件 45 处硬编码,值域 10…1150 两个不相交段 |
EmptyState |
44 处 / 33 文件 | 5 套空态并存,首启路径无主行动按钮 |
Loading / Skeleton / 探针 |
85 处 / 30 文件 | 全站 0 骨架屏,长任务只有一行灰字 |
StatusLine |
196 处 / 76 文件 | 三种红并存;错误常在列表最底部(视觉盲区) |
Toast |
4 套 → 1 | 现状嵌在导航行里,徽标一出现即被裁切 |
ConfirmDialog |
21 处 → 1 | window.confirm 在 WebView2 下可能静默返回 false |
Button |
107 处 / 63 文件 | 每面板重声明一份 btnStyle 常量 |
Surface |
180 处 / 91 文件 | 1px solid #e5e7eb,radius 6/8/10/12 混用 |
Text |
251 处 / 98 文件 | 字号与两个灰手写组合,对比度逐处失控 |
🔻 批 4 收口就地加注 · 五行各给「批 4 实测口径」(2026-09-12,上表原文一字未改)。口径:命令 + 读数 + 出处(
HEAD = 199da54b);「计划数 → 实测数」一律并列,不许只换数字。
原语(上表行) 计划口径 批 4 实测口径(含机器判据) Modal20 文件 20/20 全部只经原语 —— dialogMigration.{a1,a2,b,e}.test.ts逐文件断言「barrel 含Modal∧ 无深导入 ∧ 无自建遮罩 ∧ 无keydown∧ 无裸数字 z-index」;role="dialog"的源码命中只允许出现在ui/primitives/Modal.tsx(恰 1)与已登记例外(shell/CommandPalette.tsx用Modal)。构成 = A14 + B4 + E2 = 20(清单钉死在dialogMigration.e.test.ts的DIALOG_20);另 14 个跨行命中不迁(11 锚定菜单 B1 + 3 覆盖层 B2,见 §11-2)。z-index 标尺 17 → 6 档 裸值 58 处 / 43 文件 / 17 值 → 3 处 / 3 文件 / 3 值( 10/999/1000,全部是 B2 例外且ZINDEX_ACCOUNTS逐条带 >20 字理由);冻结名单 58 → 3(ui/zIndex.guard.test.ts,7 用例,既有 4 条断言一字未改);六档逐字 =raised 10·panel 100·popover 200·modal 300·modalNested 400·toast 500(ui/zIndex.ts的Z_TIER)。⚠️ 有意值收敛(可见观感变化,durable 登记):50/51/60/999/1000/1100/1150 → modal(300)·30–61 → popover(200)·900 → panel(100)—— 出处task-4-report.md:208-212。EmptyState44 处 / 33 文件 B11 切片 = 28 文件(判据 ① 本批已触碰 ∪ ② pages/**∪ ③ 有同名测试)⇒ 切片内非例外命中 = 0(emptyStateRatchet.test.ts②);例外 8 条(逐条锚点 + 非空理由 + 尚未走原语);余量 5 文件冻结(只许减,转「冻结值恰等于实测值」);全仓 ≤44 棘轮 + 新增文件不得命中词表。切片外余量:见批 4 计划 §收口回写 §七(去向批 5/7)。Loading/Skeleton/ 探针85 处 / 30 文件 棘轮域口径 = 可见加载文案 18 行 / 18 文件(裁:本仓「85 处」的读法不可复现 —— 计划写 19/19 是 includes("/ui/primitives/")在 Windows 反斜杠下失效所致,见批 4 陷阱 #26);切片 14 文件 / 余量 4 文件;T14 迁移后收口到 8(FROZEN_LOADING_TEXT_TOTAL = 8 == RESIDUAL 8:4 余量 + 3button-busy+ 1 例外);MIGRATED_FILES10 个文件 0 命中且必须含<Loading/<Skeleton(⑤);冻结表 18 键被「迁移面(0) ∪ 残留面(1)」逐格钉死。StatusLine196 处 / 76 文件 迁移面 49 文件( MIGRATED长度硬断言;原 55 减 6 个 B1/B2 回退文件 —— 那 6 个属NON_MIGRATED_14,守卫禁止其 import 原语层,见 B21);三红字面量冻结 114 处 / 67 文件(剥注释口径;未剥注释是 116,其中 2 处来自注释:ClassroomBanners.tsx:13、utils/refineDiff.ts:13);逐文件下界MIN_CALLS(8 个 >1 的键 + 默认 1)。Toast4 套 → 1 4 套 → 3 套收敛 + 1 套机器可判例外:① App.tsxAI toast(3500ms ·belowNav)②SessionsPage(改useTransientToast(3000),14 个调用点 diff 0 行)③useTransientToast(状态机/API 保留,仅换渲染;档位由popover(200)归toast(500))④ 面板级内联 banner 不迁(带 4 条理由 + 「仍无 fixed/role」+ 变异即红)。判据toastMigration.test.tsx(15 例)+ 原语层Toast.placement.test.tsx(6 例)。ConfirmDialog21 处 → 1 域内 confirm(命中 24 处 = 8 处window.confirm(全部迁移,落 6 个文件) + 16 处非window.confirm(同名本地 helper 等,未迁、登记)⇒ 上表「21 处」与计划 Task 11 的「16 处」两个数都不成立(见「计划错处累计 ⑭」)。判据confirmMigration.test.tsx(10 例,按 DOM 顺序逐段恰等,含总长守卫)。tier走 B6 特殊条款(主判据 ≥3 不成立,实测消费者 0)⇒ 见 ADR-033 后果④ 的更正加注。Button107 处 / 63 文件 口径变化(三个实测口径并列):510 处 / 121 文件(原生 <button>)· 80 行 / 55 文件(const *Btn*常量族)· 103 行 / 37 文件(style={xxxBtn}消费者)。上表的 107/63 不可考(btnStyle标识符全仓 0 命中)⇒ 批 4 走 B4:*Btn*常量族 + 新代码 + 原生按钮棘轮。终态:原生<button>493 → 394 处 / 121 → 114 文件(Δ −99,逐文件 Δ 之和 = −99 对拍成立)·const *Btn*79 → 56 行 / 55 → 44 文件 ·FROZEN_NATIVE_BUTTON_TOTAL510 → 394(且在buttonMigration.test.ts④ 补了FROZEN == sum(entries)与≤ PRE_T12双判据)。余量 ≈407 处(原生按钮口径)→ 登记批 5/7。Surface180 处 / 91 文件 三族实测(域 = app/src/**减测试减ui/primitives/**,先剥注释):① 边框1px solid #e5e7eb(含复合)240 处 / 111 文件 → 226 处 / 108 文件;② 越界圆角6|12|14|999|2270 → 261 处 / 112 → 109 文件;③boxShadow:24 处(值 11 种 → 6 种;20 处换 token,4 处有理由不改);④FROZEN_SURFACE_TAG_TOTAL0 → 14。「180 处卡片边框」高估了迁移面:今日 240 处按属性名分桶 = 整圈border172(真面) · 单向 57(分隔线,bordered只出整圈 ⇒ 表达不了) · 三元条件边框色 11(interactive给不了任意状态色);172 再分 = 控件 96 · NM14 14 · 锚定菜单 4 · 交互 4 · 条件底色 4 · 透明容器 28 · 有底色容器 22 ⇒ 够格 21、实迁 14。6→8计划 254 处 ⇒ 实改 9 处(6 处随<Surface radius="panel">+ 3 处就地改)—— 分区与去向逐条见批 4 计划 §收口回写 §八。Text251 处 / 98 文件 弱化灰 #9ca3af249 = 迁移 186 + 例外 63(44 文件 / 7 类:interactive*35 ·ternary-no-equivalent10 ·nontext6 ·b1-non-migrated9 ·tag1 ·colorMap2 · C 类 2),逐条理由进textBaseline.RESIDUAL(未登记 0 · 僵尸豁免 0);字号越界 558 处 / 120 文件只冻结、一处未动(映射规则已写在tmp/t16a/slice.md,批 5/6 执行);tone一律ink-3(5.13:1),ink-40 使用(§4.3 条件③无实现)。⚠️ 口径教训:T16-A 的行级归属把「同行background:+color:三元」记成 background ⇒ 计划的「24 处非弱化文本」作废,属性级重扫实为 6 处(color241 ·background3 ·border2 · 常量/映射 3 = 249)。本表的读法:上表的「现状病灶」是批 0-D 时点的侦察数(含 180 / 251 / 107 这类计划期估算);终态一律以本加注的实测口径为准,且任何一格都不得被读成「全量已清零」 —— 五类里只有切片内清零,余量各带去向(B11 的中间态,见 §11-3 加注)。
🔻 批 4 收口后更正(2026-09-12 · 收口评审 I-6 + 13 条 Minor + 收口修复单元
ed07d491/531eb93f的 3 处数字变化;上表两行与本节其余加注的原文一字未改,此处只追加):
Button行(上表第 8 行)的「终态 493 → 394 处 / 121 → 114 文件」是f6dd012f时点的读数,不是 HEAD(收口评审 M-11)。收口修复单元531eb93f把nativeButtonBaseline收紧到实测 ⇒ 终态 = 394 → 393 处 / 121 → 115 文件(FROZEN_NATIVE_BUTTON_TOTAL = 393;文件数 +1 来自 T13-b 拆件把components/chat/ChatLaunchMenu.tsx计入,SPLIT_MOVES已登记守恒、守卫未失效)。独立复算(node .superpowers/sdd/2026-09-12-frontend-redesign-batch4-primitives/tmp/docfix/measure.mjs <tree>/app/src;域 =app/src/**减*.test.ts(x)减ui/primitives/**减ui/icons/**,剥注释后整段/<button[\s>]/g):f6dd012f导出树 394 处 / 114 文件 · HEAD 393 处 / 115 文件。Text行的弱化灰例外在收口后由 63 变 64:FROZEN_MUTED_GRAY_TOTAL = 63是旧剥注释仪器的读数;ed07d491修掉sliceScan.stripComments把 JSX 闭合标签</x>的/当正则起点的假阴后,受害行components/NoteRowContextMenu.tsx:175由「被抹掉」变「被数到」⇒FROZEN_MUTED_GRAY_TOTAL = 64、逐文件格components/NoteRowContextMenu.tsx1 → 2(条目数仍 44、文件数仍 44)。物理恒等式 = 250 = 迁移 186 + 例外 64;249 = 186 + 63是旧仪器口径下的恒等式。
- 独立复算(同一探针,HEAD 工作树;三个剥注释实现并列):OLD(
091d1c3d的sliceScan)63 行 / 44 文件 · NEW(HEAD 的sliceScan)64 行 / 44 文件 · NAIVE(朴素/* */+//,不做正则启发式)64 行 / 44 文件;三口径唯一差异文件 =components/NoteRowContextMenu.tsx(OLD 1 / NEW 2 / NAIVE 2)。- 上表
Text行的「7 类」逐类分解两种口径都不对(收口评审 I-6):原文写interactive*35 ·ternary-no-equivalent10 ·nontext6 ·b1-non-migrated9 ·tag1 ·colorMap2 · C 类 2 —— 自列之和 = 65 ≠ 63,且colorMap与「C 类」是同一类的重复计数(65 − 63 = 2 正来自这里)。真源 =textBaseline.RESIDUAL(44 条)+FROZEN_MUTED_GRAY_BY_FILE(44 键)联立;我自测(node …/tmp/docfix/d2-kind.mjs):条目数interactive14 ·interactive-no-equivalent8 ·ternary-no-equivalent9 ·b1-non-migrated7 ·nontext4 ·tag1 ·colorMap1(Σ44)· 处数interactive19 ·interactive-no-equivalent11 ·ternary-no-equivalent11 ·b1-non-migrated14 ·nontext7 ·tag1 ·colorMap1(Σ64)。合并口径:interactive*= 22 条目 / 30 处(不是 35)。- 计划「296 是手抄噪声」这个机理不成立(收口评审 M-6):296 是朴素剥注释口径的真值,295 才是旧
sliceScan的真值 —— 差额恰为components/NoteRowContextMenu.tsx:175那一处。独立复算(42e88740导出树):OLD 295 行 / 105 文件 · NEW 296 行 / 105 文件 · NAIVE 296 行 / 105 文件。⇒ 那是口径差,不是手抄错;解释读数差异必须点明是哪两种口径(台账 §四 #32 的追加一例已入册)。
🔻 批 5 收口就地加注 · 错误行「位置」的处置(A6 = C11 = D11;2026-09-12,上面全部加注与本表原文一字未改)—— 批 5 只预留槽位,不重排任何既有
StatusLine调用点;位置与像素判定转批 8****:
- 槽位形态(两侧逐字一致):
class="ed-view-error-slot" data-view-error-slot="",各恰 1 个,位于切换器之后、内容为空 —— 会话侧app/src/components/session-detail/SessionViewHost.tsx:121(剥注释后 1 处;裸子串 2 处,第 32 行那处是头注释里的引文 ⇒ 裸/声明级两个读数并列)· 笔记侧app/src/components/notes/NotesReadingColumn.tsx:268(自闭合空元素);切换器行号 103/108(会话)与 252/258(笔记)⇒ 槽位在切换器之后 ✅(顺序判据)。- 机器判据:
app/src/views/architecture.guard.test.ts:250-258(A5③:剥注释 + 顺序 + 「恰 1 处」+ 类名钩子,2 passed)。反向对照(有牙):T15-M-A5(删掉会话侧槽位)⇒failed 1 / passed 16,红 = A5③;T15-M-A5c(槽位整体上移到切换器之前,数量与属性逐字不变)⇒failed 1 / passed 16,红 = A5③(顺序那一半);反向对照(必绿):T15-R-A5b(槽位加合法属性role/aria-live,位置与数量不变)⇒0 failed / 17 passed✅。- 既有调用点一处未动:本批没有把任何页面级
StatusLine从列表底部搬到顶部(那会把页面级 status 拆成 5+ 个 state,状态面扩张且与三条硬约束无关)⇒ 「底部 vs 顶部」的可达性差异在 jsdom 里判不了(需真实视口 + 用户行为),实现与像素判定归批 8 的布局/像素 pass。- 出处:批 5 计划 §收口回写 §四(C11 行)·
tmp/t18/measurements.md§2.3。
- 尺寸三档:S 380(确认类)· M 520(表单类)· L 720(向导/工作台);遮罩统一
rgba(26,26,26,.34),圆角 10。 落地(批 0-D):三档 =.ed-modal--s|m|l(ModalSize),层级两档tier: "modal" | "modalNested"(300 / 400, 值一律从zIndex()标尺取),默认m/modal。 - 四个必补能力:①
role="dialog"+aria-modal+aria-labelledby;② 焦点陷阱 + 打开聚焦首元素 + 关闭归还焦点;③ ESC / 点遮罩关闭(脏表单时先内联确认);④ 进出场接口(L4 动效的前置)。 落地(批 0-D):①②③④ 全部已实现(三条全仓 0 命中的契约createPortal/role="dialog"/aria-modal从 0 变成 1; 进出场 200/160,出场比进场快)。未做:body 滚动锁(现状 20 个弹层也没有,批 4 观察项)。 Enter提交必须带 IME 组合守卫 —— 现状全库仅 1/9 处有,中文输入法回车会直接触发危险动作。 落地(批 0-D):判定出口isImeComposing()(ime.ts)只建不接 —— 本批无表单;批 4/5 在每个「Enter 提交」处消费它。- ★ 两条批 0-D 实测新增的契约(不是设计推导,是踩出来的;批 4 必须遵守):
Modal是 Portal / 焦点陷阱 / ESC 栈的唯一持有者,消费者不得自建第二套。ConfirmDialog已按此改写 (无createPortal/ 无zIndex/ 无文档级键盘监听 —— 有源码与 CSS 扫描断言钉住),28 个手写弹层迁移后同样不得 保留自己的遮罩与windowESC 监听。ESC 的「最内层」判定必须用 React 树深度:实测朴素入栈序(effect 自底向上) 与 DOM 序(portal 插入序反转)都会把外层当成栈顶。- 退场相位必须禁指针事件:
[data-phase="exit"]⇒pointer-events: none。open=false后弹层仍挂载 160ms (Modal.css),那段时间面板还在屏上 —— 点击是即时的而退场是异步的,删除 / 级联删除的误触面就在这里。 已落盘(T783710e27,遮罩与面板各一条;ConfirmDialog侧另有两条文件内缓解,T8ef240816)。 附带纪律:JS 侧兜底窗口与 CSS 侧过渡时长必须同值(Modal.tsx/Toast.tsx的EXIT_MS↔var(--ed-dur-overlay-out|toast-out, …)↔motion.css定值,三方对拍守卫在style-contract.test.ts)。
| 档 | 动作 | 通道 |
|---|---|---|
| 低危可逆(单条笔记 / 单图 / 单引用) | 立即生效 | 撤销 toast 10s —— 用保留的原行载荷重新插入,不改 schema |
| 高危不可逆(组删除 / 体系级联 / 采集弃置 / 毕业结算) | 确认框 | ConfirmDialog,框内必须列明级联影响与保留项(例:「将删除 1 个组 · 3 条排序记录 · 笔记 7 篇保留」) |
| 级联 | — | 一律不给撤销(只给确认),保持撤销栈边界清晰 |
| 序 | 文件 | 行数 | 拆成 |
|---|---|---|---|
| ① | pages/NotesPage.tsx |
602 | NotesToolbar · useNotesKeyboard · useNotesBatchActions |
| ② | components/NoteListView.tsx |
609 | NoteListToolbar · NoteListTree · useNoteListSelection · NoteListContextMenuHost |
| ③ | components/SessionDetailPanel.tsx |
656 | SessionDetailHeader(粘性头)· SessionTranscriptPane · SessionScreenCards · SessionSegmentsTimeline · useSessionDetailData |
| ④ | pages/ClassroomPage.tsx |
724 | ClassroomSourceColumn · ClassroomCapturePanel · ClassroomInputPanels · ClassroomBanners · useClassroomShortcuts |
豁免表同步纠偏:~11 个 >300 行未登记(RefineWorkbench 471 · GoalDetail 371 · SessionsPage 352 · EnrichPanel 324 等)· 8 个登记值与实测不符 · 1 个可移除(AiConversationDock)· 统一「前端测试文件是否登记」的口径。
- 顶栏 8 项(📡 课堂 · 🗂 会话 · 📝 笔记 · ✅ 行动 · 🔄 复习 · 🧠 体系 · 🎯 目标 · 💬 AI 对话)+ 右上 ⌘K + 采集状态 + ⚙ 齿轮。
- 溢出两级:≥1180 图标+文字(约 1070px,余量 ~200px);1024–1180 仅图标 + 悬浮名(约 720px)。
- ⌘K 命令入口 用来替代现在手写的 9 个
focus*参数跳转,数据源接kb_search。
2026-09-12 批 3 回写(原文一律保留,只加注) ① 「约 1070px / 约 720px」两个估数的前提与实测(W20): · ≥1180 档:实测改前
natural = 1281.8 px(默认窗 1280 上溢出 16.8 px,A7 实测),比「约 1070px」高 ≈212 px。 逐元素拆解(T7 探针parts):brand 135.53 + tabs 716.83 + 右侧簇 389.44(Ctrl+K97.86 +对话面板110 + 徽标 73.58 +设置84 + gaps 24)+ padding 32 + gaps 8。 ⇒ 该估数只有在「右侧簇不带文字」的前提下成立 —— A7 裁决 R2 把右侧簇(⌘K / 对话面板 / 齿轮)在<1400px收成仅图标 +title、把 Tab 的 padding/gap 收紧后,实测 1027.94 px(含徽标;预测 1073.94,实现后更小),与「约 1070px」同一量级。 ⇒ R2 是把规格原本的设想补回来,不是偏离规格;1281.8 才是偏离。 · 1024 档:「约 720px」准确 —— 实测改前 717.11 px(Δ2.89);R2 后 691.11 px(含徽标)。 · 最坏徽标变体(「⏸ 暂停挂起(重连中)」= 145.58 px):1180 档 1099.94(余量 +65.06)· 1280 档余量 +165.06 ⇒ 三档 × toast 三态 × 徽标两变体 48 行全 OK(改前 21 行溢出)。 ② 「图标+文字」的适用对象(W18 / A2):本行「≥1180 图标+文字」指的是8 个域 Tab;右侧簇(⌘K / 对话面板 / 齿轮)在max-width:1399px内只有图标 +title—— 这是规格未写明的形态,由 A7 裁决 R2 落地,两级阈值分别住在shell/breakpoints.ts的navFull = 1180与navActionsFull = 1400(单一真源,CSS 里写1179px/1399px由守卫断言钉住)。 另:本行括号里的 emoji 是排版示意,不是规范态 —— 规范态是 §1 决策 5 的「自绘线性图标集」(A2 裁决:emoji 出局;它同时是测量毒物,见批 3 陷阱 #16)。 ③ 「9 个focus*参数跳转」实测是 10 个(D7):多出focusChatId。批 3 的 ⌘K 覆盖了其中 2 类有载荷入口(检索命中 → 笔记高亮;新建体系)+ 页面命令覆盖全部 9 页目的地,10 个字段一个未删(收敛状态机归批 5);逐条映射表见批 3 计划 §收口回写。 ④ 采集状态的口径(A3):本行「+ 采集状态」= 顶栏右簇的采集徽标;AI toast 不在本行 —— 它已按 A3 移入MainShell最外层的 fixed 覆盖层(top: calc(var(--ed-nav-h) + 8px)),因为它是 1024 档溢出的唯一主因(单项 373.75 px = 视口 36.5%)。
ColumnSpec = { key, default, min, max, autoFoldBelow, pinnable },由单一注册表汇总,页面不再自建 hook。
| 页 | 列 | 默认/最小/最大 | autoFoldBelow | 本次改动 |
|---|---|---|---|---|
| 📡 课堂 | 源列 | 320 / 240 / 420 | 1100 | 阈值 860→1100;采集态整列隐藏 |
| 📡 课堂 | 右面板 | flex | — | 统一 wrapper,消灭 640/全宽两档跳动 |
| 🗂 会话 | 列表列 | 320 / 240 / 420 | 1100 | 详情头改粘性 |
| 📝 笔记 | 组列 | 240 / 180 / 320 | 1024 | 并入注册表 |
| 📝 笔记 | 列表列 | 320 / 240 / 420 | 1024 | 工具栏三层合并为单行 |
| 📝 笔记 | 大纲列 | 180 / 140 / 260 | 1280 | 接线拖拽+记忆或删钩子(现为「假可调」) |
| ✅ 行动 | 单列 | 页签内分区 | — | 不变 |
| 🔄 复习 | 单列 | — | — | 复习态零 chrome |
| 💬 AI 对话 | 侧栏 | 260 / 200 / 320 | 1100 | 接入列基础设施(现硬编码 240) |
| 🧠 体系 | 体系列 | 260 / 200 / 360 | 1100 | 阈值 860→1100;折叠态持久化 |
| 🧠 体系 | 详情列 | 320 / 260 / 420 | 不折叠 | 34px 窄条收进统一列头 |
| 🎯 目标 | 左列 | 320 / 240 / 420 | 1100 | 接入列基础设施;默认 380 → 320 |
| ⚙ 设置 | 单列 | 居中 860 | — | 现 720 左对齐 → 改居中 |
阈值口径:按「折叠后正文是否仍 ≥520px」反推 —— 三列页 1024 · 两列页 1100 · 大纲列 1280。
记忆规则:记忆列宽与手动折叠态;不记忆自动折叠态、顶栏档位、相变态。
2026-09-12 批 3 回写(原文一律保留,只加注) ①
ColumnSpec实际是 7 个字段(W21):上面那句列了 6 个 ——{ key, default, min, max, autoFoldBelow, pinnable };实现多一个page: PageKey(app/src/shell/columnRegistry.ts)。加它的判据收益有两条:①columnsOf(page)能按页取列(顶栏/页面接线不必另立清单)② 守卫能判「列不许挂在已删页上」(page ∈ 导航注册表键集)。⇒ 这是实现的加法,不是规格的反悔;本行原文保留,字段清单以这 7 个为准。 ②pinnable是计划取的默认、无消费方:规格给了字段但未给逐行值 ⇒ 批 3 全行写false,今天没有任何消费方(登记给批 6,与列折叠动效一起定)。 🔻 批 6 收口就地加注 ·pinnable的批 3 实际取值(R6.6;2026-09-13,上面原文一字未改):上面「批 3 全行写false」与代码不符 ⇒ 代码是权威:app/src/shell/columnRegistry.ts的notes-outline那一行逐字含pinnable: true,且该文件的口径注释自称「除笔记大纲列…为true」⇒ 批 3 的实际取值 = 除notes-outline外全false(13 行逐行值:12 行false/ 1 行true)。本规格两处(本②与 §10「批 3 的收口」行)都写「批 3 全行false」⇒ 两处原文均按本加注读。消费方仍为 0(全app/src实测 15 处pinnable命中全在同一注册表文件内:1 处注释 + 1 处接口字段 + 13 行取值,无任何读取点)⇒ 本批(列折叠 Flip)只登记消费方缺口,不接线。 ③ 大纲列「接线拖拽+记忆或删钩子」的裁决(W22 / D6):走接线(不删钩子)。计划 Task 8 Step 4 逐字写「onToggleOutline改为outlineCol.expand()」——字面照做会把 ✕「收起大纲」也变成expand(),凭空制造一个新缺陷;实现取folded ? expand() : setManualFolded(true)(窄条 → 展开、✕ → 手动折叠),两个控件各自语义正确。旧实现的死局(J1-3:窄窗自动折叠下folded ≡ true,点窄条永不展开)由此解开。 ④ 笔记列表列的阈值(D3):本表写autoFoldBelow = 1024,而今日实测是 700(且三值并存:860×4 / 700×1 / 1100×1)——批 3 已按 §1 决策 16 与「折叠后正文仍 ≥520px」的口径改判为BREAKPOINTS.threeCol = 1024,三值并存消灭;本行原文保留。 ⑤ 本表 13 行的落地状态:13 行全部进shell/columnRegistry.ts(单一注册表);页面不再自建宽/夹取/阈值,但执行器仍是useColumnLayout(A5 裁决:注册表持规格、hook 执行)。7 处旧调用点 + 4 处未接入点(ChatSidebar/GoalsPage/SettingsPage/ClassroomRightPane)全部改为从注册表取规格。 ⑥ 「本次改动」列里未做的两条:🗂 会话 · 详情头改粘性与📝 笔记 · 工具栏三层合并为单行不属批 3(壳层与列契约),未做 —— 登记去向见批 3 计划 §收口回写「未做」表。 ⑦ 34px 窄条(🧠 体系 · 详情列)未吸收:KnowledgeDetailPanel的折叠窄条width: 34仍在。理由:ColumnSpec里没有「折叠窄条宽」这个概念,取.min(=260) 会把 34 px 变成 260 px(可见回归);只加一个collapsedWidth字段则是扩写规格引用的契约形状去凑数(A1 明禁)⇒ 登记给批 4(与「统一列头 /ColumnBar收敛」一起做才是真吸收)。
🔻 批 5 收口就地加注 · 本表「本次改动」列最后两条的处置(A5 = C13 / ADR-034 S-4;2026-09-12,上表与上面七条加注的原文一字未改):
🗂 会话 · 详情头改粘性→ ✅ 批 5 已做:app/src/components/session-detail/SessionDetailHeader.tsx= 176 行(预算 ≤180),落地形态 =position: sticky+top: var(--ed-space-4)(= 4 px)+zIndex("raised")(= 10,走ui/zIndex.ts标尺,不写裸值);补了 1 条行为级判据(该文件此前无同名测试):SessionDetailHeader.test.tsx9 passed(改前 5 passed / 4 failed ⇒ 改后 9/9,删改的是它自己新增判据的中间态,既有断言零改动)。⚠️ 真实粘性不可验(诚实登记,不得读成「已验证」):jsdom 无布局引擎 ⇒ 只能给静态结构级判据(position: sticky∧top来自 token)与祖先链核验;真实滚动下的粘性行为未验证,归属批 8 的真机/像素 pass(C13 逐字要求把这一点写进「未验证」)。📝 笔记 · 工具栏三层合并为单行→ 批 5 未做,转批 8(C13 逐字)。理由(C13):要动NotesPage.tsx(拆件后 288/300)+NoteListView.tsx(241)+app/src/components/NoteListToolbar.tsx(95,事实更正:真身不是NotesListToolbar.tsx)三个无测试面文件,「投入产出比最差」⇒ 与批 8 的布局/像素 pass 同批。本行原文保留,去向以本加注为准。- ADR-034 侧的同一条处置见该 ADR §登记 下
:115的加注⑦ 与批 5 加注(本收口已就地补记「T18 的处置=登记为批 5 follow-up」的最终结果)。
🔻 批 6 收口就地加注 ·
pinnable的消费方终态 + 本表与 §6.3 的内部矛盾(R5.7 · R40.1 · R55/R58 的路径 B 裁决;2026-09-13,上面原文与七条批 3 加注、批 5 加注一字未改):
pinnable的消费方终态 = 仍为 0 处(本批未接线):全app/src实测命中仍全在同一注册表文件内(接口字段 + 13 行取值 + 口径注释),无任何读取点。批 6 的列折叠 Flip 走的是授权路径 B(data-flip-id跨元素匹配、不动 DOM 结构),不消费pinnable⇒ 上面②「消费方仍为 0(只登记消费方缺口,不接线)」在批 6 依然成立,逐字登记为未接线。- 🔴 规格内部矛盾(R40.1,两处原文均保留、就地加注消歧):本表
📡 课堂 · 源列行写「采集态整列隐藏」,而 §6.3 的相变态表写「源列保留(采集配置面)」—— 两句互斥。本规格不在此裁决可见性(模块与批 6 都未裁决):批 6 交付的是相位通道 + 顶栏相位 CSS + chrome 两态,列可见性未实现(app/src内「采集态整列隐藏」0 处实现;shell/columnRegistry.ts的注释已就地写「两个口径都不由这里兑现」)⇒ 两个口径按本加注并存,实现面以 §6.3 的「源列保留」为既成事实(采集配置面今天不隐藏),去向 = 批 7/8 或用户裁决。- 出处:
task-34-report.md§10(生产调用点读数)· 批 6rulings.md§四十(R40.1)· §五十五/§五十八(T33 的路径 B)。
| 态 | 顶栏 | 域导航 | 列结构 | 顺带修掉的审计项 |
|---|---|---|---|---|
| 采集态 | 58px LIVE 仪表(波形 + 计时 + 暂停/标记/停止) | 隐藏 | 源列保留(采集配置面) | G3 · G7 |
| 复习态 | 零 chrome | 隐藏 | 单列,卡片居中 640 | B5 |
| 常态 | A′ 顶栏 | 显示 | 按 6.2 契约 | — |
🔻 批 6 收口就地加注 · 上表的落地读数(R4.3–R4.5 · R42⑥ · R49.1④;2026-09-13,上表原文一字未改):
- 通道:
<html data-shell-phase>,取值逐字"idle"|"capture"|"review";单一写入方终态成立 —— 全仓唯一useShellPhase(...)调用 =app/src/shell/phaseSource.ts:84(shellPhase.guard.test.ts的名册钉住),载体 =App.tsx:394的<PhaseChrome phase={phase}>(1 处)。⚠️ readShellPhase的 TS 读取仍 0 生产调用点(消费方是 CSS 的 3 条选择器)。- 采集态 58px LIVE 仪表 + 波形:
--ed-nav-h-live: 58px落 token 真源(T17,gen-tokens.mjs→tokens.css);链路闭合 1 / 1 / 1 ——<PhaseChrome>(App.tsx:394)→shell/PhaseChrome.tsx:102<LiveBar …>→shell/LiveBar.tsx:135<Waveform …>(LiveBar自身 0 处直挂,由LiveBarHost之内挂载;T18 结束时的「0 调用点」已由 T19 闭合)。- 复习态零 chrome 的实现路径 = 相位 CSS(
motion.css的相位块 +TopBar.css的html[data-shell-phase=…]两态),不是列隐藏;相位块的块序是硬事实:相位块 → 档位块 → reduced-motion 块(实测行号 191 < 210 < 260)。- 🔴
navHeight.consumption.test.ts零改动仍绿(T17 的自证:新增--ed-nav-h-live未破既有消费判据)。两态像素面(采集真的 58px / 复习真的零 chrome)jsdom 不可判、本批未测 ⇒ 只登记(task-34-report.md§12)。- 🔴 本表第 1 行「源列保留」与 §6.2 的「采集态整列隐藏」互斥 —— 消歧见 §6.2 的批 6 加注(本批未实现列隐藏,两个口径按加注并存)。
| 部件 | 形态 | 解决的问题 |
|---|---|---|
ViewSpec |
{ key, label, icon, appliesTo, Component, lazy } |
把「这个视图能看什么对象」变成类型约束 |
viewRegistry |
按对象类型查可用视图的单一注册表 | 现状展示形式硬编码在页面里,故一对象只能一种样子 |
ViewSwitcher |
一个原语(分段控件),放正文列头部 | 体系域自建了 tabbar,别的域没有 |
| 依赖方向 | 领域 → 视图 → 容器 → 原语(禁止反向) | 视图不得直接调 Tauri 命令,数据由容器注入 |
🔻 批 5 收口就地加注 ·
ViewSpec的字段形态(C1;2026-09-12,上表原文一字未改)——Component静态字段与lazy布尔已被load取代,批 5 已按此实施:
- 落地形态 =
{ key, label, icon, appliesTo, load? },其中load?: () => Promise<{ default: ComponentType<P> }>;宿主用React.lazy+Suspense(复用既有ShellFallback)。⇒ 上表不是偏离:C1 的定性是「把lazy布尔升级为可执行加载器」—— 规格自己给了lazy字段,说明设计意图本就包含「非默认视图不静态加载」;而把load做成静态Component(方案 a)会结构性把 5 个视图 + markdown 栈拉进首屏(shell/**与 primitives barrel 都在首屏静态可达集内)⇒ 直接超 200 kB 预算。规格原文保留,字段清单以本加注为准。- 默认视图无
load(同步渲染 + 常驻):实测session[0].hasLoad = false·note[0].hasLoad = false,非默认 5 个 spec 全部hasLoad = true;views/registry.ts顶部 4 条 import 逐字全是import type⇒ 0 个视图组件静态 import,且每个load体内恰 1 个import((5/5)。- 落点:注册表 =
app/src/views/registry.ts(109 行,预算 ≤120);ViewSwitcher落在原语层app/src/ui/primitives/(见ADR-033§1 的批 5 加注)。- 读数出处:批 5 计划 §收口回写 §一 ·
.superpowers/sdd/2026-09-12-frontend-redesign-batch5-view-layer/tmp/t18/measurements.md§1.1/§1.2(该目录 gitignored,不入库)。
| 对象 | 现有唯一形式 | 本批 | 登记不排期 |
|---|---|---|---|
| 🗂 会话 | 列表行 → 详情文档 | 三轨对齐 · 印样 · 原文 · 卡片流 | — |
| 📝 笔记 | markdown 阅读 / 编辑 | 原文 · 卡片流 · 带证据三轨 | 大纲(回归评估) |
| 🧠 体系 | 树/画布/图谱/概念/模型(已 5 种) | 作为模板迁进视图层统一管理 | — |
| 🔄 复习 | 卡片 + 四档评分 | — | 印样式回顾 · 时间轴复习 |
| ✅ 行动 | 裁决队列列表 | — | 时间轴(按计划日)· 卡片流 |
| 🎯 目标 | 详情页 | — | 矩阵视图(目标 × 相位) |
↳ 批 5 收口就地加注(C2 的条件项 + C17①;2026-09-12,上表原文一字未改)—— 「📝 笔记」行第三列的「带证据三轨」本批未交付;笔记侧交付 = 2 视图(原文 · 卡片流):
- 依据 = C2 的条件判据(「先做只读数据可行性探针;存在 ⇒ 3 视图;不存在 ⇒ 2 视图 + 就地加注 §7.2 与 §11-6 + 登记批 7;不许做空壳视图」)+ T1 的只读探针(
task-1-report.md·tmp/t1/c2-evidence-probe.md)+ T13 的独立复现(task-13-report.md§②):不存在逐段级「笔记 ↔ 证据」关联的读取路径 ⇒NoteEvidenceTrackView不做、不建空壳(实测全仓NoteEvidenceTrack*= 0 命中)。本批笔记视图键终态 =["raw","cardflow"](app/src/views/registry.ts:108)。- 三条独立证据(T13 复现读数;命令与原始输出见
task-13-report.md§②): ①app/src-tauri/src/**/*.rs全树 571 文件,精确串note_evidence|evidence_segment|note_segment= 0 命中(双侧自证:note_id→ 400 ·segment_id→ 68 ·zzz_no_such_symbol_zzz→ 0 ⇒ 真 0 非假 0); ② 数据模型侧:db_migrations.rs共 26 张实体表 + 1 张 FTS 虚表(kb_fts,:305;合计 27 处建表)与 26 条ALTER TABLE … ADD COLUMN(24 个唯一列名)里无任何「笔记 × 证据」连接表或字段;notes对会话只有整篇级session_id(:408); ③ IPC 侧:唯一段级引用artifact_blocks.refs_json.segment_id(artifact.rs:64)的维度是 session 而非 note,且 0 个#[tauri::command]返回SessionArtifact/ArtifactBlock/BlockRefs(两种独立手法各 0;全仓#[tauri::command]= 321 个)⇒ 前端读不到;前端 284 个 invoke 名里「同时含note与segment|evidence|artifact|block」= 0。- 准确边界(本批接受 T1 的判定,并已在仓内逐条取证):笔记 markdown 的段首 in-band 锚点
[⏱ MM:SS]([[ts:ms]])(发射concat.rs:122-127· 契约anchor_strip.rs:3-4· 金测试note_filter_golden_tests.rs:117-124· 前端渲染器utils/html.ts:32)不构成逐段级读取路径,三条理由各自独立成立: ① 是文本不是关联(它是notes.content这段TEXT里的字符——无外键、无约束、无索引,用户编辑即可删改); ② 是 ms 不是 id(证据本体是session_segments.id/session_ocr_blocks.id;而 T13 的 E2 逐字要求data-evidence-id与关联 id 逐字一致,ms在类型上无法满足); ③ 不保证存在(只在转写/结构/章节草稿的段首发射,且受PurifyConfig.anchor_timestamps开关控制——purify_config.rs:66,96默认true、金测试:125-127逐字钉住「关闭后无锚点」;BodySource::OcrDirect(图文会话)走note_filter_ocr::rebuild_ocr_markdown(note_filter_render.rs:85,全仓format_timestamp调用点里note_filter_ocr.rs= 0 处);BodySource::Web是#[allow(dead_code)]预留变体、正文直取web_session_pages.markdown(note_body_source.rs:24-27);手动笔记更不会有;且精修输入会主动剥离段落锚点(anchor_strip.rs:8-16,消费点ai_refine_task.rs:155·commands_ai_refine/workbench.rs:81·commands_ai_refine/session.rs:57),只回挂章节锚点(ai_refine_protocol.rs:46))。 ⇒ 改判为「交付 3 视图」属改规格(E2 降级为 ms 最近邻 · E1/E3 的「派生段落数」改为「带锚点段落数」 · 并须新开「无锚点段落」的显式标记路径),不在执行单元权限内。- 去向 = 批 7(必须先写规格),逐条登记见
task-13-report.md§④(含 E2 降级口径、E1/E3 双分母、OcrDirect/Web/手动笔记/anchor_timestamps=false四类无锚点 fixture、段落无稳定 id 的根因、以及若要用artifact_blocks必须新开 command ⇒ 触及规格 §3 红线 6「后端数据模型零改动」需另裁)。- R8 对拍(防「条件项被当成已交付」):本批不得出现「笔记 3 视图已交付」的表述;终态 = 2 视图,且 §11-6 的验收不因此变红(2 ≥ 2,见 §11-6 的批 5 加注)。
🔻 批 5 收口就地加注 · 会话侧矩阵的终态读数(A2;2026-09-12,上表原文一字未改):
- 会话 = 5 个视图:
FROZEN_VIEW_KEYS.session = ["raw","tritrack","proof","cardflow","preview"](app/src/views/registry.ts)—— 与上表「三轨对齐 · 印样 · 原文 · 卡片流」逐项对上,多出的preview是既有的笔记预览视图,按 §7.3② 一并进注册表并转为惰性(它原先住在页 chunk 里)。笔记 = 2 个视图:FROZEN_VIEW_KEYS.note = ["raw","cardflow"](第三列的条件项见上一段加注)。- 两个终态清单分别由守卫对拍:
FROZEN_VIEW_KEYS与keysFor()双向对拍(app/src/views/registry.test.ts12 用例)·registry[0].key === "raw"且默认视图无load(app/src/views/architecture.guard.test.ts17 用例 +architecture.slots.test.ts2 用例,共 19 passed)。- 上表第 4 行「依赖方向」在本批的机器判据:
views/**8 个生产文件对@tauri-apps的裸子串 0 / 声明级 0(阳性对照components/session-detail/SessionScreenCards.tsx裸 1 / 声明级 1 ⇒ 仪器有牙);views/**首屏静态可达 = 0(TS-API 口径 66 文件,工具口径 91 = 源 77 + CSS 14,双口径并列)。- 出处:批 5 计划 §收口回写 §一 ·
.superpowers/sdd/2026-09-12-frontend-redesign-batch5-view-layer/tmp/t18/measurements.md§1.2/§2.2(该目录 gitignored,不入库)。- 印样数据契约(
proof视图;规格未给 ⇒ 批 5 T8 定,登记在此;收口评审 Minor-4 落位):props =Pick<SessionViewSlot,"detail"|"imageUrl">(type-only、其余 8 槽一个不接 ⇒ 结构上不可能取数/交互;也不许自己 importconvertFileSrc);DOM 锚点 =data-testid="session-proof-view"(根,空态分支也在)· 每张data-proof-sheet={first_seen_ms}·figure[data-proof-figure](图注位恒在,有图/无图两条分支都渲染)·div[data-proof-body](正文区);不复用SessionScreenCard(两形态只共用数据语义,代码真源是那张卡)。七条语义(F1–F7):F1 重叠谓词 = 半开区间seg.start_ms < last && seg.end_ms > first(零宽屏first === last归一为点[first, first+1);首尾相接不算重叠;与useSessionDetailData的「屏 → OCR 块」同源)· F2 跨屏段在两张印张上都出现(重叠归属而非切分归属;与任何屏都不重叠的段不出现在本视图 ——「原文不丢」由默认原文视图承载,见 §7.3①)· F3 段序 =start_ms升序、并列时id升序(先复制再排序,不原地改 props 数组)· F4<img>仅在image_ref !== null且imageUrl(ref) !== null时渲染(且imageUrl只在image_ref !== null时被调用 —— 计划漏了「ref 非空但解析不出」这一支,否则渲染src={null}= 碎图)· F5 两槽位锚点(台账口径的「两槽位锚点」= 上面的figure[data-proof-figure]/div[data-proof-body];计划只锚了根与印张 ⇒ 没有这两个边界,P2「图注位保留」/P3「正文按区间归属」只能退化成「整篇textContent包含」的弱判据)· F6 序号 =screen_id ?? index + 1(与容器SessionScreenCards逐字同源)· F7detail.screens.length === 0⇒ 走EmptyState(testId="session-proof-empty",标题「本会话无画面要点」,说明指向原文视图;根data-testid仍在)。出处:task-8-report.md§2.1–§2.3(逐条理由 + props 表)·progress.md§二十(契约原文)—— 两者都在.superpowers/**(gitignored、不入库)⇒ 本行即该契约在仓库内的持久记录。判据侧:views/session/SessionProofView.test.tsx5 用例(P1–P5 各带变异体 M1–M8)+ 只读判据 P4 与nativeButton.ratchet①② 双红;SessionProofView.tsx168 行。
- 原文视图永远保留 —— 未标注内容(核心处理 γ 只为「值得长期调用」的类型建机制)、长文阅读、自由书写都需要文档形态。
- 惰性挂载 —— 默认视图常驻(保活滚动与编辑态);非默认视图惰性挂载 + 卸载,重挂载恢复
scrollTop。否则「9 页常驻 × 每对象 4 视图」会成为内存炸弹。 - 编辑态切视图先 flushSave ——
RichEditorView卸载会丢编辑器状态;落库失败则阻止切换并提示,绝不静默丢弃。
🔻 批 5 收口就地加注 · 三条硬约束的机器判据落点与终态读数(A3;2026-09-12,上面三条原文一字未改)。口径:每条判据给「文件 / 用例数 / exit」+ 反向对照的变异体出处(带任务号);三条合计 9 条判据全绿(出处:批 5 计划 §收口回写 §一 ·
tmp/t18/measurements.md§1)。
- ① 原文视图永远保留 —— 判据四条:结构 1
registry.ts的SESSION_VIEWS[0].key === "raw"∧NOTE_VIEWS[0].key === "raw"(自写结构探针,exit 0)· 结构 2(G2) 默认视图不带load且非默认 5 个全带(app/src/views/registry.test.ts12 用例,exit 0)· 行为 H1 会话「切到每一个非默认视图后原文节点仍在 DOM ∧ 挂载计数不减」(SessionViewHost.test.tsx11/11 passed)· 行为 F5 笔记「切到cardflow后正文仍在 DOM,且原文子树节点同一性不变」(NotesReadingColumn.views.test.tsx11/11 passed)。反向对照(有牙):T10-M1({resident}→{isDefault ? resident : null})⇒6 failed / 9 passed,红含 H1;T14-M5(默认视图改回互斥条件渲染 = 旧SessionDetailPanel:200-206形态)⇒1 failed / 10 passed,唯一红 = F5。- ② 非默认视图模块级惰性 —— 判据五条:A1(图级)
app/src/views/**首屏静态可达 = 0(工具口径与 TS-API 口径双列)· A2 生产运行时导入者恰 2(pages/NotesPage.tsx/pages/SessionsPage.tsx),views/** → registry的生产侧 7 条边全是import type(运行时边 0)· G7 每个load体内恰 1 个import((5/5)且注册表顶部0 个视图组件静态 import(4 条 import 逐字全是import type)· 行为 H2 切到 ⇒ 挂载 / 切走 ⇒ 不在 DOM(11/11)· 行为 H3Suspense+ShellFallback在位(11/11)· 行为 F6 笔记侧惰性 + 卸载 + 记忆恢复(11/11)。反向对照(有牙):T10-M2c(惰性视图粘滞常驻 ∧ 去掉默认视图门控)⇒failed 1 / passed 14,仅 H2 红;T10-M3(删<Suspense>包裹)⇒failed 5 / passed 10,红含 H3;T14-M6(非默认视图用display:none代替卸载)⇒failed 1 / passed 10,唯一红 = F6。产物级:真实构建后懒 chunk 22 → 31,逐视图字面量恰命中 1 个懒 chunk(逐 chunk 具名台账见 §收口回写 §五/§八)。- ③ 编辑态切视图先
flushSave、失败则阻断 —— 判据五条:F1 reject ⇒ 值未变 + 目标未挂载 +role="alert"+ 记忆未写 · F2 resolve ⇒ 切换发生 + 目标挂载 + 无错误行 · F3 非编辑态直通(editorRef.current === null)· F4 阻断全过程 0 个 toast 节点(并证明选择器有牙)· F9 既有断言原样绿(语义只在「切视图」这一条路径被修正)—— 四条it全在app/src/components/notes/NotesReadingColumn.views.test.tsx(11/11 passed)。反向对照(有牙):T14-M1(把catch分支改成「保存失败也继续切换」= 本条逐字禁止形态)⇒1 failed / 10 passed,唯一红 = F1。显式登记未做:RichEditorView内的 Ctrl+E / 完成按钮路径仍不阻断(今天就是 fire-and-forget,不是本批引入的回归)⇒ 批 8;flushSave的返回类型未升级(NoteEditHandle)⇒ 批 8 接口卫生。提示形态:catch⇒ 不切视图 + 保持编辑态 + 就近一行StatusLine kind="error"(不用 toast);错误行宿主在非NON_MIGRATED_14的层(NoteReadingView.tsx/NotesReadingColumn.tsx),两条 B1/B2 守卫一字未改且绿。⚠️ 引用变异体时必须带任务号(ID 撞名):T10 的M1=「默认视图条件渲染」= 约束①的反向对照(6 条红);T14 的M1=「catch分支继续切换」= 约束③的反向对照(唯一红 F1)。不是同一个变异体。⚠️ 两条「无专属变异体」的判据(只登记、不在收口提交里补测):F9 是文件头@ai-context注释而不是it(它断的是跨文件的「既有断言未被动过」,单文件变异体无法表达)· A5①/A5②(architecture.guard.test.ts的默认视图 display 三元)没有以自己为目标的变异记录 —— 这两条性质分别由 G2(registry.test.ts)与行为级 F5/H1 守着 ⇒ 不是覆盖漏洞,只是这条判据自己没有专属变异体。逐条四要素见tmp/t18/measurements.md§9.1,去向 批 6/7。
出处与状态(这一行是本章的定位,别跳读):
docs/versions/v0.22.md:561逐字「笔记「带证据三轨」→ 批 7(必须先写规格)」,判否依据 = 批 5task-13-report.md§④(B7-1…B7-9)+ §②(探针读数)。🔴 本批只交规格,实现未做 —— 本章是批 8 的输入契约,不是交付证明;🔴 全仓NoteEvidenceTrack*= 0 命中(本批独立复测:app/src/**的.ts/.tsxPROD 0 处 / 0 文件 · TEST 0 处 / 0 文件;仪器.superpowers/sdd/2026-09-12-frontend-redesign-batch7-unwired/tmp/t20/probe-spec-readings.mjs,负控zzz_no_such_symbol_zzz= 0)⇒ 不存在「第三种笔记视图已经交付」这回事,本章也不得被读成它。
- 🔻 口径更正(2026-09-13 · 批 8 T3;上一行的实测域收窄,原文保留):上一行逐字写的「全仓」是字面假命题 —— 它包含本行自身(上一行既含「全仓」也含那个以
Track结尾的符号名)⇒ 自我指涉(与 §11-7 在:905-906的更正同源、同形)。🔴 T3 于7c1fcc41实测(入库域 =git ls-files,1,615 文件;口径 = 行含子串,剥注释抹等长空白保偏移):app/src/**(生产 + 测试)= RAW 0 行 / 剥注释 0 行 / 0 文件 ✅ · **app/src/**之外 = RAW 27 行 / 剥注释 27 行 / 4 文件,全部在docs/**(按顶层目录 =docs:27行 /docs:4文件)—— 含上一行自身。⚠️ 口径注(勿与 §11-7 的读数混用):本注的「剥注释」只对.rs/.ts/.tsx生效(.md无注释语义,原样比对)⇒ 本注域内两者恒等;§11-7 的:905那组读数(RAW 16 / 剥注释 6 / 3 文件,时点53bd0759)口径与时点都不同 ⇒ 🔴 两组数不得互推、不得当趋势读(§3.5「数字必须带口径与时点」)。本注自身含该符号名恰 1 次 ⇒ 落注后全仓 RAW +1 行 / +0 文件(即 28 行 / 4 文件),app/src/**仍 0 行 / 0 文件。- ⇒ 🔴 正确表述:「
app/src/**(生产 + 测试)= 0 处 / 0 文件」(这才是「实现未做」的有效证据域);app/src之外的 27 行全是文档与计划里的提及(其中含本章自身),那不是实现。上一行的「全仓」一律按本注收窄读(收窄后与 §11-7 的:906现口径一致)。阴性对照 = 本任务现造的随机串(入库域实测 0 命中;因它一旦入库即失效,故本注不写它,读数见批 8task-3-report.md)。- 🔧 T3 自捉更正(2026-09-13,落注后复测;上面三条原文保留):①
⚠️ 上一条「口径注」末句的自指预测「本注自身含该符号名恰 1 次 ⇒ 落注后全仓 RAW +1 行(即 28 行 / 4 文件)」实测不成立 —— 上一条刻意用「以Track结尾的符号名」指代、并未复写该串 ⇒ 它不含该串,不产生自增。🔴 实测(同域 =git ls-files· 同口径 · 落注后):全仓仍 27 行 / 4 文件,app/src/**仍 0 行 / 0 文件 ⇒ 以本实测为准;「+1 行 / 28 行」按本注作废(本条更正同样不复写该串 ⇒ 也不改变该计数域)。② 上一条「正确表述」里的「上一行的「全仓」」指代错位 —— 应为本章定位行:542**(:544是「口径注」、不含「全仓」)。- 📌 本节 T3 各注的行号锚口径(2026-09-13 · T3;P-36 的落地):上面三条注(含本条)里的行号锚一律是
7c1fcc41时点的编号(即本注自身插入行之前的编号)—— 🔴 T3 的实测证据:7c1fcc41时点它写:905-906/:565,而4966d9ee时点实测已漂到:921-922/:576(漂移量 = 本任务在它们上方插入的 16 / 11 行;本章定位行:542未变)。⇒ 🔴 跨时点引用一律按「锚名」读::905-906⇒ §11-7 的 T21 口径更正 ·:565(见 §D 表下的 T3 加注)⇒ §D 标题 ·:540⇒ 本章定位行。⚠️ 行号随时点漂移(P-36),数字只作时点读数、不作锚;本条声明本身也不再给「当前绝对值」。
| # | 旧口径(今日规格原文) | 🔴 改写成 | 为什么必须改(类型上不可能满足旧口径) |
|---|---|---|---|
| E1 | 「每段有 data-evidence-for」 |
「每段都有 data-evidence-for(含无锚点段)∧ 只有带锚点段才渲染证据列」 |
无锚点段落客观存在(§C 的四类)⇒ 旧口径把「无锚点」与「缺陷」混为一谈;新口径把无锚点本身变成一等状态(有锚点无证据列 = 缺陷;无锚点无证据列 = 正常) |
| E2 | 「data-evidence-id 与关联 id 逐字一致」 |
🔴 降级为 ms 最近邻,且必须显式给出三件事:① 容差(|锚点 ms − 候选 ms| ≤ 容差才算命中;容差值由实现批定,必须写进判据而非注释)② tie-break(多个候选同 ms 或同距离 ⇒ 取确定序:start_ms 升序 → 同值取 id 升序;不得依赖数组顺序)③ 失配的显式标记(容差内无候选 ⇒ 出显式「无证据」标记,不许静默取最近的一个) |
段首锚点只带 ms([[ts:63000]]),而证据本体是 session_segments.id / session_ocr_blocks.id(artifact.rs:62-69)⇒ ms 在类型上无法与 id 逐字一致;旧口径是一条永远不可能满足的断言 |
| E3 | 「派生段落数」当分母 | 🔴 两个分母并列、不许混用:分母甲 = 派生段落总数(渲染器实际产出的段落节点数)· 分母乙 = 带锚点段落数(其中含 [[ts:ms]] 锚点者)。⇒ 报告与判据必须分别给出两个比值(「有锚点的覆盖率」用分母乙;「全篇覆盖率」用分母甲),🔴 禁止只报一个数就称「覆盖率」 |
分母只有一个时,无锚点段落会被算成「未覆盖」⇒ 读数结构性偏低,而真实缺陷面(有锚点却无证据列)会被稀释 |
🔻 批 8 T3 就地加注 · 上表 E2 行的出处更正(2026-09-13;上表原文与各格一字未改):E2 行的「为什么必须改」列逐字用
artifact.rs:62-69支撑「证据本体 =session_segments.id/session_ocr_blocks.id」。
- 🔴 实测该处是
BlockRefs(app/src-tauri/src/artifact.rs:60-69::62pub struct BlockRefs {,字段:64segment_id: Option<i64>·:66ocr_block_id: Option<i64>·:68frame_ms: Option<u64>)—— 它是产物块引用结构(ArtifactBlock.refs: BlockRefs,同文件:127),维度是 session 而非 note,且 0 个#[tauri::command]返回该类型(0 IPC 出口;域 = 入库app/src-tauri/**/*.rs,实测BlockRefs只出现在结构定义 / 字段 / 内部构造 / 测试四类位置)。⚠️ 照字面读会误判成「必须新开 command」(这正是本章 §D3 的由来)⇒ 🔴 实际不需要:证据 id 的定义处 =app/src/types/session.ts的SessionSegment.id(:22-23)与SessionOcrBlock.id(:33-34),及表session_segments(app/src-tauri/src/db_migrations.rs:45)/session_ocr_blocks(同文件:56);前端取数走既有get_session_detail(app/src-tauri/src/commands_session.rs:137→:164;:146list_segments(id)·:147list_ocr_blocks(id),:164一并返回)⇒ 零新 IPC / 零 schema(控制方 §2 A1)。- ⇒ E2 行的技术结论不变(
ms在类型上无法与id逐字一致);变的只是出处 —— 支撑该结论的是session.ts的类型 +get_session_detail,不是artifact.rs:62-69。- 🔻 批 8 T6 就地加注(2026-09-13;上一行原文保留)—— 「三轨」的实现口径(控制方 §2 A3):笔记段落轨(
data-evidence-for挂在其上)+ 转写段轨(session_segments.id)+ OCR 块轨(session_ocr_blocks.id)。🔴 规格原文未逐字给这三条 ⇒ 以本注为准;证据本体是 id、段落锚点只有 ms ⇒ E2 的「降级为 ms 最近邻」是类型上的必然,不是实现偷懒。
| # | 类 | 出处(发射路径) | fixture 必须断言什么 |
|---|---|---|---|
| 1 | OcrDirect(图文会话) |
note_filter_render.rs:85(走 note_filter_ocr::rebuild_ocr_markdown;该文件里 format_timestamp 调用点 = 0 处) |
段落全部无锚点 ⇒ 每段仍有 data-evidence-for、0 个证据列、0 个「无证据」告警(无锚点 ≠ 异常) |
| 2 | Web(网页正文) |
note_body_source.rs:24-27(BodySource::Web 是 #[allow(dead_code)] 预留变体,正文直取 web_session_pages.markdown) |
同上;且这条 fixture 是「未接线变体」的唯一覆盖面(它今天没有生产发射路径) |
| 3 | 手动笔记 | 无发射路径(用户手写/改写) | 段落无锚点 ⇒ 同 1;另断言:用户编辑不得被自动补锚点(§4.4 的「绝不猜」同源纪律) |
| 4 | 🔴 anchor_timestamps=false(关闭开关的用例必须有) |
purify_config.rs:66,96(默认 true);金测试 note_filter_golden_tests.rs:125-127 已逐字钉住「关闭后无锚点」 |
同一份输入在开关 true / false 两态下各跑一次:true ⇒ 有锚点段 > 0 且证据列只在那些段上;false ⇒ 锚点 0 个、证据列 0 个、data-evidence-for 仍逐段在。🔴 只测默认配置 = 假绿(会让实现退化成「只在默认配置下绿」) |
- 事实:
anchor_strip.rs:8-16主动剥离段落锚点;消费点 =ai_refine_task.rs:155·commands_ai_refine/workbench.rs:81·commands_ai_refine/session.rs:57;剥离后只回挂章节锚点(ai_refine_protocol.rs:46)。 - 🔴 写成契约(本节的交付物):精修产物的段落级锚点不保证存在;精修输入路径上「段落锚点消失」是设计行为(防止模型把 in-band 锚点当正文改写/编造)。⇒ 带证据三轨在精修后的段落上必须走 §A 的 E2 失配分支(显式「无证据」标记),不得把它报成缺陷或回滚精修。
- 两态 fixture 清单:① 精修前(
notes.content原文,锚点在段首)② 精修后(章节锚点回挂、段落锚点 0)。两态各一份 fixture,同一套断言(E1 逐段锚 + E2 三件 + E3 双分母),差值必须逐条归因到本节契约。
- 段落无稳定 id 的根因:
notes.content是扁平TEXT(db_migrations.rs:18-27),段落身份由noteCardModel派生 ⇒ 派生序号会随编辑漂移(用户在上方插入一段 ⇒ 后面所有段落身份全变)。 - 要稳定配对的两条路:(a) 派生序号(零 schema 改动,但漂移可观测)· (b) 新增段级身份 ⇒ 🔴 触及规格 §3 红线 6「后端数据模型零改动」 ⇒ 必须控制方另裁,本批不开。
- 唯一段级引用:
artifact_blocks.refs_json.segment_id(artifact.rs:64)—— 维度是 session 而非 note,且 0 个#[tauri::command]返回该类型(0 IPC 出口)⇒ 若要用必须新开 command,同 2 的红线裁决。🔴 不得在执行单元内顺手开。 - 🔴 不得新写第 3 支手写 markdown 解析器(与 §7 的 markdown 归一冲突);实现若落地,复用
utils/markdownLine.ts/NoteMarkdown的既有渲染链。
🔻 批 8 T3 就地加注 · 本节 §D 的两条红线裁决(2026-09-13;§D 的标题与第 1–4 条的原文一字未改**)**:第 2 / 3 条逐字写的「必须控制方另裁」(标题
:565同写「需要控制方另裁,不在执行单元权限内」)已由控制方裁决(控制方 §2 A2 逐字):
- 🔴 走 (a) 派生序号 —— 即第 2 条的 (a):零 schema 改动;§D1 的漂移事实不变(漂移可观测,按其登记,不因此改设计)。
- 🔴 明确不开 (b)「新增段级身份」(第 2 条 (b),仍触 §3 红线 6),也不开 §D3 的「新开 command」 —— 前端取数走既有
get_session_detail(出处与实测见 §A 表下的 T3 加注)⇒ 第 3 条末句「若要用必须新开 command」按本注不再成立(不开 command 就够)。- ⇒ 本节标题与第 2 / 3 条不再是「待裁」状态;下游实现单元不需要任何新增 IPC / schema。§E 逐条登记的「批 8 输入 ②(§D 的两条裁决)」按本注闭合。
- 📌 锚口径(承接 §7.4 定位行下 T3 的同类声明;2026-09-13 · T3):本注里的「标题
:565」是7c1fcc41时点的编号 ⇒ 🔴 一律按锚名「§D 标题」读(本任务在其上方插入行后已漂移;绝对值见上引声明)。
- 批 8 输入:① 本章的实现(视图 + ms 最近邻纯函数 + 四类 fixture)② §D 的两条裁决(段级身份 / 新 command)③ E2 的容差取值(本章只定「必须有」与「三件形态」,不定数值)。
- 诚实边界:本章没有任何实现,因此没有可跑的判据、没有覆盖率读数、没有观感结论;
NoteEvidenceTrack*的 0 命中是本章未实现的证据,不是「已交付但没测」。
用户纲领原文:「我希望我的软件是充满动效的、充满创新设计、充满生命力的,而不是呆板、死板的。」 本节各项均以此为准绳。
| 层 | 时间尺度 | 解决什么 | 具体点 |
|---|---|---|---|
| 响应层 | 80–180ms | 应用在听你说话 | 墨渍 hover(从指针位置扩散)· 按下微陷 · 焦点环落纸 · 勾选框落笔 |
| 环境层 | 2–6s 循环 | 应用在呼吸 | 探针摆动 · 采集脉冲 · 未确认段落墨度极缓慢起伏(幅度 2%) · 到期刻度微光 |
| 编排层 | 400–900ms | 签名时刻 | 对齐 · 显影编排 · 相变凝固 · 时间码回跳 · 记忆浮现 · 图谱浮现 |
| 生长层 | 秒 → 天 | 熵减看得见 | 到期刻度生长 · 笔记树生长 · 知识图谱次第落位 · 一场课结构化过程中的收拢 |
引擎:GSAP(core + Flip + ScrollTo + CustomEase)+ @gsap/react 的 useGSAP() 做清理(React 19 StrictMode 会双调用 effect,裸用 useEffect + gsap.to 会留下重复 tween)。GSAP 只进自己的 chunk 懒加载。
| 判据 | 用什么 |
|---|---|
| 单属性 · 无时序 · <200ms | CSS transition(hover 底色、焦点环、按下 scale) |
| 多元素 · 有时序 · 需中断/反向/seek | GSAP timeline |
| 「从 A 布局滑到 B 布局」 | GSAP Flip |
| 循环环境动效(骨架 / 探针 / 脉冲) | CSS keyframes(不占 JS 主线程,reduced-motion 一条媒体查询即静态) |
Flip 解锁了布局动画:先改布局 → 测量差异 → 用
transform补回起点 → 动画到 0,全程只动 transform。因此列折叠、列表排序、视图重排、卡片提拔全部可做连续运动。
| 面 | 基调 | 缓动 | 适用 |
|---|---|---|---|
| 有「读数」的界面 | 精密仪器 | power3.inOut,匀速段更长,沿轴线、带刻度感 |
采集 · 复习 · 时间轴 · 到期刻度 |
| 有「文字」的界面 | 活的纸 | power2.out / 自定义「洇开」曲线,带惯性沉降(不是回弹) |
笔记 · 会话 · 体系 |
--dur-micro 120ms(响应)· --dur-card 220ms(面板/视图/列折叠)· --dur-reveal 500ms(显影)· --dur-skeleton 1200ms · --dur-page 150ms · --ease cubic-bezier(0.2,0,0,1) · 位移上限 8px。
进出场:弹层 200/160(出场比进场快)· Toast 180/140 · 相变 chrome 用绝对定位交叉淡入,不 animate height · 列折叠内容先淡出 120ms 后宽度瞬跳(宽度本身不做 transition,除非走 Flip)。
usePresence(约 40–80 行 + 单测):只负责卸载时机(GSAP 不管这个);transitionend 监听 + 超时兜底(reduced-motion 下不会有 transitionend,缺兜底会「关不掉的弹层」);matchMedia 必须自带守卫(vitest 全局 node 环境、setup.ts 无 matchMedia 桩)。
| 档 | 行为 |
|---|---|
| 节能 | 只留响应层;编排层直接跳终态 |
| 标准(默认) | 四层全开,环境层幅度减小 |
| 丰富 | 环境层幅度与频率提高,编排层加长、错开更明显 |
系统 prefers-reduced-motion 优先于档位,档位跟随系统初值。
| # | 名称 | 内容 | 只有这个产品才有的理由 |
|---|---|---|---|
| 1 | 对齐 | 转写/画面/笔记三轨从错位滑到对齐 | 双通道融合本体的可视化 |
| 2 | 显影编排 | 沿时间轴逐段显影,节奏 = 语速函数 | 「熵减」的字面可视化 |
| 3 | 相变凝固 | 波形收束成直线、琥珀退去、导航淡入;可反向 | 形态变化而非状态切换 |
| 4 | 刻度生长 | 到期刻度按真实间隔生长;答「忘了」则回缩 | 让 FSRS 调度可以被感觉 |
| 5 | 时间码回跳 | 播放头沿时间轨滑到目标位置,掠过几帧缩略 | 把「每句话可追溯」变成可见动作 |
| 6 | 记忆浮现 | 墨色洇开 + 字距极轻收敛(用 x 而非 letterSpacing)+ 剪报底纹左刷 + 评分按钮随后浮起 |
揭晓是有节奏的一件事 |
🔻 批 5 收口就地加注 · 第 1 行「对齐」的第三轨口径(A4 = C2 的连带硬要求;2026-09-12,上表原文一字未改)—— 第三轨 = OCR 文字,不是「笔记」:
- 上表第 1 行逐字写「转写/画面/笔记三轨」,而 C2 裁决的会话三轨 = 转写 / 画面 / OCR 文字(
segments/screens/ocr_blocks全在SessionDetail里 ⇒ 零新数据面、不碰 Rust,符合规格 §3 红线 6)。理由:SessionDetail不含笔记(实测),且笔记是产物、不是原料 —— 把「笔记轨」并进「会话三轨对齐」会混淆两个对象;「双通道融合」的产品价值在 OCR 口径下依然成立(双通道 = 语音 + 画面,OCR 是画面的文字面)。- ⇒ 批 6 的动效纲领按本加注后的口径执行(「对齐」动效的第三轨取 OCR);「笔记轨」未交付的原因与去向(= 笔记侧「带证据三轨」的 C2 条件项判否)见 §7.2 与 §11-6 的批 5 加注。
- 批 5 只落「响应层接缝」,不装引擎:
ViewSwitcher落--ed-dur-micro(120 ms)接缝,实测ViewSwitcher.css63 行(预算 ≤80)·ViewSwitcher.tsx135 行(预算 ≤150)· 零行内 style;不装 GSAP、不写@keyframes(B9 中间态声明:「只有接缝、没有纲领」—— 三档强度 / 双基调 / GSAP 在批 6)。
原文(用户,回答 §12 的留空问题):「我希望我在对其进行交互时,它是活的」。 控制方解读(若与你本意有偏差请直接推翻):这句把"活"的重心放在用户动作的那一刻,而不是"没人操作时它自己在动"。
由它推出的四条硬约束(批 0-D / 3 / 4 / 6 都要照此,不是新纲领、是 §8.1 四层的配重):
-
配重(2026-09-11 用户二次确认后定稿):两个主场,交互优先 ——
- 第一优先 = 响应层(80–180ms)与"用户动作触发的编排层":交互的那一刻是"活"的主战场(见第 2 条)。
- 第二优先 = 环境层(2–6s)保持"可感知的生命感":用户原话是"交互时最重要,但闲置时也要有生命感(环境层别退太多)"⇒ 不得把环境层降为纯背景、不得把它压到看不见;它按 §8.1 已定的项目与量级存在(探针摆动 · 采集脉冲 · 未确认段落墨度极缓慢起伏 2% · 到期刻度微光),并在 §8.5 的「丰富」档如实变丰富(幅度与频率提高),而不是只在响应层加料。
- 两者的分界:环境层永远不抢注意力(幅度上限不动)、不阻塞交互、
prefers-reduced-motion下整体静态;响应层必须每次都给回执。
-
每个用户动作都要有即时回执:点击 / 拖拽 / 悬停 / 键入 / 勾选 / 展开折叠 / 切换视图 —— 每一类都必须有有质感的即时反馈("做完了"与"收到了"必须可区分)。这是验收口径,不是形容词:批 6 收口时逐类动作列出其响应层动效,缺一即不达标。
-
可中断、可反向是"活"的硬指标:交互触发的动效必须能被下一个输入打断(下一个动作接管当前动效,而不是排队等待)。⇒ 批 0-D 的原语必须预留动效接缝:
Button(hover / active / focus-visible / disabled 四态 + 按下微陷)·Surface(hover 升起 / 边框墨度)·Text(墨度与字距的可动画钩子)·Modal/ConfirmDialog(进出场 presence 钩子 + 遮罩淡入,走 §8.4 的 200/160)·Toast(进出场 180/140 + 可打断)·Loading/Skeleton/Probe(骨架微光 / 探针的 CSS@keyframes钩子 —— 只有这两个"循环环境动效"用 keyframes) ·EmptyState(一次性入场钩子.ed-empty-enter) ·StatusLine(一次性浮现transition,无循环动画)。否则批 6 只能回头改每一处调用点,而批 0 交付的正是"让后面每一批都能一次改对所有地方"的能力(§10)。分桶裁定(控制方 2026-09-11,回应 T12 评审 I-2):本节原先把
StatusLine与Loading并列为「CSS keyframes 钩子」,与计划给它的实现(transition + 明确「无循环动画」)分叉。裁定:StatusLine归 transition(无循环),keyframes 桶只留Loading/Skeleton/Probe。 依据是本节第 1 条「环境层永远不抢注意力」——状态行是信息不是「呼吸物」,循环动效会让它在长列表里变成噪音;「闲置时也有生命感」由Probe承担。同裁定记入 ADR-033。 -
"活"不得以无障碍为代价:
prefers-reduced-motion优先于强度档位(§8.5);键盘路径(Tab 顺序 / 焦点可见 / Esc 退出)与"活"冲突时,无障碍优先。
3D 翻转 / 弹性回弹 / 粒子 · 对用户输入的夸张响应 · 页面转场滑动。
🔻 批 6 收口就地加注 · §8 的实现面回填(§8.1–§8.7 逐小节;2026-09-13,本节所有原文与批 5 加注一字未改):
§8.1 四层纲领的逐层落点:响应层 =
motion.css的元素级全局回执 + 原语层四类回执(T12,零调用点改动)· 环境层 =motion.css的环境层四件 +app/src/motion/env.ts(幅度真源,T13)· 编排层 =useGSAP()+ 六个签名 hook(波 C)· 生长层 = 本批只做「到期刻度生长」(components/review/useScaleGrowth.ts),其余登记。§8.2 引擎:
gsap@3.15.0+@gsap/react@2.1.2(本批唯一一次「零新增依赖」破例,R2.1);唯一入口 =app/src/motion/engine.ts,顶层gsap.registerPlugin(useGSAP, Flip, ScrollToPlugin, CustomEase)(恰 4 个、顺序逐字);🔴 双实例陷阱(测试底座独有):@gsap/react@2.1.2无exports、main指 CJS ⇒ Vitest external 后拿到另一份 gsap 运行时,不registerPlugin时context.revert()静默空转(实测:裸useEffect= 2 tween、useGSAP()也是 2 个;注册后 = 1 个、卸载后transform === "")。✅ 真实产物上成立:vendor-gsap-BQLVn3Z6.js(105,584 B)在产物里、不在firstScreen.chunks(首屏仍 3 chunk)。§8.3 双基调:载体
data-tone(取值逐字"instrument"|"paper")+ 两个缓动 token(gen-tokens.mjs真源)+CustomEase具名 ease。⚠️ 量化事实:CSS 侧cubic-bezier只是近似 ⇒maxDiff ≈ 0.409 @ x=0.40(本批接受该差,但接受 ≠ 可两路横跳:同一落点只许一条路径)。§8.4 token 与清单:10 个变量已迁入
gen-tokens.mjs单一真源(motion.css的--ed-*定义恒 0,由style-seams.test.ts的回归封条钉住);「不 animate height」已判据化(T19 的 V1:相变 chrome 走绝对定位 + 交叉淡入)。§8.5 三档:载体
data-motion("eco"|"standard"|"rich",默认standard;持久化键motion:intensity;初值跟随系统);源序 = 防御性钦定(真实承重机理 = reduced-motion 块逐条带!important;🔴 不得给档位块加!important);三档的机器面 = 档位映射 + DOM 属性 + 源序 + 时长参数,观感面进「只能登记」清单。🔴 §8.6 六个签名动效逐条兑现度(规格 §11-10 的四行判据「持有 / 中断 / 降级 / 三档」各有专属变异体;生产调用点读数出处 =
task-34-report.md§10):
# 名称 生产调用点 落点(逐字) 兑现度(未兑现的带原因) 1 对齐 1 views/session/SessionTriTrackView.tsx:251✅ 可判(三轨共轴 + 同 ms 高亮 + 位移 ≤8px);真实数据上「同 ms」极少成立 ⇒ 共轴容差 = 规格未给数字 ⇒ 不发明,去向产品裁决 2 显影编排 1 components/session-detail/SessionRawView.tsx:96🟡 部分:编排可判;节奏 = charRate字符率近似(不得称为「真实语速」—— 规格未定义语速函数);🔴 反向 / 重播replay()入口 = 0(状态机与判据齐备、无生产入口)3 相变凝固 1 shell/LiveBar.tsx:90✅ 可判(波形收束成直线 / 琥珀退去 / 导航淡入三件 + 可反向) 4 刻度生长 1 components/review/ReviewSessionPanel.tsx:98✅ 可判(生长 / 回缩;回缩用 review_card的精确intervalDays)5 时间码回跳 1 views/session/TimeRail.tsx:140🟡 部分:落位 + ≤8px 掠过已交付;长距离连续滑动未交付 6 记忆浮现 1 components/review/ReviewSessionPanel.tsx:102✅ 可判(墨色洇开 + 字距用 x而非letterSpacing+ 剪报底纹左刷 + 评分按钮浮起)(附) 列折叠 Flip 2 / 8 处 components/ChatSidebar.tsx:80·pages/GoalsPage.tsx:42🟡 走授权路径 B( data-flip-id跨元素匹配、零既有断言改动);其余 6 处未接线;🔴Flip会写width/height(layout 属性)⇒ 与 §11-10 的属性集合判据天然冲突,如实登记(不为让判据变绿而放宽 R8.4)🔴
[[ts:ms]]端到端只通一半:NoteMarkdown的芯片已带上毫秒(T26 修掉「芯片是死的」这一真实缺陷),但会话页那一跳未交付 ⇒ 登记为批 7 首要候选(task-26-report.md的逐行成本与 patch 落点保留)。§8.7 三条不做:未触碰(
bounce/elastic/ 粒子 / 页面转场滑动 = 0 处)。🔴 像素面全部未测:本节的观感面(真的直线 / 真的 0.72 / 真的 220ms 淡入 / 真的 58px)jsdom 不可判 ⇒ 只登记,见
v0.22.md批 6 节的「诚实代价」。
| # | 命令 | 处置 | 说明 |
|---|---|---|---|
| 1 | ai_clear_key |
删 | 旧单 provider 密钥链 |
| 2 | ai_enhance_mock |
删 | 补缝三连(宿主 ArtifactView 已下线) |
| 3 | ai_enhance_status |
删 | 返回常量;自包含零外溢 |
| 4 | ai_goal_plan_estimate |
补 UI · 登记不排期 | 目标规划成本预估 |
| 5 | ai_save_key |
删 | 旧单 provider |
| 6 | ai_test_connection |
删 | 旧单 provider |
| 7 | artifact_to_note |
删 | 产物视图 v0.11.5 已删 |
| 8 | build_draft |
删 | 旧草稿链 |
| 9 | build_session_artifact |
删 | 产物视图 |
| 10 | export_manual_fill_done |
补 UI · 登记不排期 | 周回顾手动回填 |
| 11 | export_write_todotxt_file |
补 UI · 登记不排期 | 迁出到 .todo.txt |
| 12 | get_note_group |
删 | 已被 list_note_groups 全量 + 前端 map 取代 |
| 13 | get_session_artifact |
删 | 产物视图 |
| 14 | kb_search |
补 UI(本批) | ⌘K 的数据源(ADR-029 RAG 层) |
| 15 | learning_metrics |
补 UI · 登记不排期 | 学习指标面板 |
| 16 | list_group_fragments |
删 | 被 list_fragments 全量 + 收件箱取代;DB 层保留(flashcards/settlement 仍在用) |
| 17 | quiz_group_cards |
补 UI · 登记不排期 | 组级自测;selfTestPassedRate 恒 null 的根因 |
| 18 | recognize_image |
删 | 旧直调 |
| 19 | reset_tag_color |
补 UI(本批) | 标签线;与 set_tag_color 成对处理,不可只删 reset |
| 20 | save_draft_as_note |
删 | 旧草稿链 |
| 21 | scan_ai_candidates |
删 | 补缝三连 |
| 22 | session_outline |
补 UI · 登记不排期 | 与笔记大纲回归一起评估 |
| 23 | structure_models_dir_cmd |
删 | — |
| 24 | transcribe_audio |
删 | 旧直调 |
| 25 | update_note_tags |
补 UI(本批) | 标签可写;全仓现无任何写 notes.tags 的生产路径 |
| 26 | vad_threshold_diag |
删 | 开发诊断用;未来若需要,届时按诊断需求重新引入,不留半成品 |
| 27 | video_profile_by_kind |
删 | 前端已有等价的 profiles.find(...) |
| 28 | video_profile_for_spec |
留(本批接线) | 档位通道的读端 |
| 29 | video_profile_memory |
有意保留 | 自述「诊断用」,零成本 |
| 30 | video_profile_spec_by_kind |
删 | 前端已有 KIND_TO_FORM / KIND_TO_TIER 双写 |
| 31 | action_badge_count |
有意保留 | 文档明确「保留命令无前端调用方」 |
| 32 | add_session_ocr_block |
撤下 IPC,保留内部函数 | 低级写原语,暴露只会造脏数据 |
| 33 | add_session_segment |
撤下 IPC,保留内部函数 | 同上;「手动补录」应另立新命令(带来源标记与校验) |
| 34 | analyze_session_command |
补 UI(本批) | 会话详情「重新分析」 |
| 35 | audit_due_for_system |
补 UI · 登记不排期 | REQ-212 审计报告视图 |
| 36 | create_session |
撤下 IPC,保留内部函数 | 手动建空会话无意义 |
| 37 | delete_session_images_all |
补 UI(本批) | 整场图集批量删(现只能单张) |
| 38 | detect_video_domain |
删 | 上游 OCR 标签通道从未建起来;平台信号不是瓶颈(infer_platform 已从标题/URL 自行补标签) |
| 39 | finish_session |
补 UI(本批) | 恢复动作「结束会话」(崩溃后卡在录制态的收尾通道) |
| 40 | get_decision |
补 UI(本批) | 决策日志单条详情 —— 顺带修审计 H7 |
| 41 | open_capture_float |
删 | 2026-09-11 结清:前端 0 调用者;开路径由 float_toggle(useClassroomFloat.ts:38)与 FloatAction::Open => float_open_core(commands_window.rs:250)承载,本命令只是又包一层 float_open_core ⇒ 批 1 Task 8 删 |
| 42 | refine_session |
补 UI(本批) | 会话详情「手动精修」(UI 现只调 auto 版) |
| 43 | release_live_prepare |
有意保留 | 前端注释「保留供未来显式调用」 |
| 44 | remember_video_profile |
删 | 功能被 remember_video_profile_form 完整覆盖,双重死亡 |
| 45 | set_tag_color |
补 UI(本批) | 标签线 |
| 46 | update_fragment_group |
补 UI(本批) | REQ-201 声称已接线但实际无调用方 —— 需同步修正记录 |
| 47 | update_knowledge_system |
补 UI(本批) | 体系改名 / 核心问题 / 状态 —— 最明确的功能缺口 |
🔻 状态更正(2026-09-13)· 指上表 #14
kb_search行:本行的「补 UI(本批)」已在批 3 Task 12 交付(kbCommands.ts:116→useKbPaletteSearch.ts:61→CommandPalette.tsx:127,提交b567f0e6,带 9 条用例)。原文保留(本行是规格原文,批 8 对账须能看见「规格写 12、实做 10」的差额来源)。🔴 T21 实测复核:kb_search的前端生产调用点 = 1(app/src/shell/kbCommands.ts,五形态并列探针)⇒ 本行的「已交付」为实测事实。🔻 角色变更登记(2026-09-13,批 7 T19)· 指上表 #30
video_profile_spec_by_kind行:本行当年删除video_profile_spec_by_kind的理由是「前端已有 KIND_TO_FORM / KIND_TO_TIER 双写」。批 7 把读端接到后端video_profile_for_spec(#28)之后,那张前端映射的角色从「并行真源」变成「离线降级路径」(兜底) —— 它仍然存在、也仍有生产调用点(AGENTS.md §3.4 要求本地兜底路径必须留),不是被删除。⇒ 本行的删除理由在"真源"这一层不再成立,在"兜底"这一层仍成立;原文保留,本注为准。🔴 实测:video_profile_for_spec前端生产调用点 4 处 / 1 文件(components/ProfileDetector.tsx);KIND_TO_FORM/KIND_TO_TIER仍在且仍有生产调用点(R-11 剥注释实测 6 处 / 2 处;T21 未剥注释粗测 7 / 3,差额为注释行)⇒ 两张映射一个字未删。🔻 状态更正(2026-09-13)· 指上表 #46
update_fragment_group行:本行的「需同步修正记录」已在批 1 完成(docs/product/requirements-pool.md:337含 2026-09-12 批 1 更正)。批 7 只做"接线"那一半(命令本身的生产调用点)。🔴 但 T21 实测推翻了后半句的兑现:update_fragment_group在app/src/**(含测试)命中 0 文件 / 0 处,而它仍在 registry(定义 311 / 注册 311 / 重复 0含该条)⇒ 「接线」那一半在本批未做。处置:与 §C9.1 的裁决不冲突(该行被排除出 10 条实做名单的依据是「记录同步已做」,不是「接线已做」)⇒ 逐字登记为批 8 输入,不得读成「本批 12 条补 UI 已全部接线」。🔻 收口更正(2026-09-13 · T21 追加轮;上一注的实测发现保留**、处置作废):上一注把「接线」那一半登记为「→ 批 8 输入」—— 🔴 该处置作废。依据
rulings.md§C56.2 逐字:「这是批 7 的交付缺口,不是「批 8 输入」……不得让一次漏做在事后读成一次有意的延期」**。理由:本行处置栏逐字是「补 UI(本批)」,且计划的指派三处一致 ——:532A-2「不做记录;命令本身接线」→ 本批 ·:2299C11 给了落点与判据 ·:2309Step 3 逐字「C 组(C5–C11 共 7 条)—— 逐条单独提交」。
- ✅ 已在批 7 内由 T23 补做并交付(3 条提交):
125eec85 feat(components): 片段行补上移动到组入口(4 路径,含新件app/src/components/FragmentGroupAction.tsx)·5f662811 test(components): 把源码探针标题同步到七条命令·5d59e332 fix(components): 碎片归组候选改用 feed 地形组(地形返工:候选集由container改为feed)。- ✅ T21 于追加轮独立复测(口径 = node
fs全仓扫描;正控invoke(68 个生产文件 · 负控 0):update_fragment_group前端命中 = PRODapp/src/components/FragmentGroupAction.tsx(4 处;:92逐字invoke("update_fragment_group", { fragmentId, groupId: target })) + 测试侧FeedFragmentList.test.tsx(9) ·batch7UiWiring.test.tsx(2) ⇒ PROD 0 → 1(≥1)。- ✅ 落点形态:
FragmentGroupAction.tsx:71invoke<NoteGroup[]>("list_note_groups", { terrain: "feed" })+:72.filter((g) => g.terrain === "feed")(后端真源 + 客户端第二道)· 载荷键名{ fragmentId, groupId }(Tauri 2 camelCase;Rust 真身app/src-tauri/src/commands_fragments.rs:141-145=update_fragment_group(state, fragment_id: i64, group_id: Option<i64>))·groupId: null= 移出组(与Option<i64>的None逐字对齐)。- ✅ 判据(T23 自报 + 控制方 §C57.5 逐项复核):V7 正控(feed 组入候选 + 查询载荷逐字
{ terrain: "feed" })+ 🔴 负控有效(容器组不入候选)· V8 父层 ≤300 · V9 两株("feed"→"container"红在FeedFragmentList.test.tsx:225:33;删客户端收口红在 V7 负控:227:82)· V1–V6 重跑通过 · CONTROL 同树 29/29 绿。- 🔴 缺口成因(逐字登记,供 T22 的二分清单收录):计划口径正确且甚至预警过 ——
:2304自陈「数一数是 11 个名字」、:2305裁决「按名字列全 11 个,不删任何一个……不自行删减」;而 T20 报告的计数口径「6 + T18/T19 的 4 = 10」恰好吞掉了被删减的那一个名字 ⇒ 缺口成因 = 实做方的计数口径,不是计划缺陷。
汇总:删 22 · 本批补 UI 12 · 登记不排期 7 · 撤下 IPC 3 · 有意保留 3 · 待核实 0 = 47。
2026-09-11 改判:#41
open_capture_float由「待核实」改为「删」(依据见该行说明)⇒ 删除批由 21 条升至 22 条。
两条更正,可单点回退:#38
detect_video_domain与 #44remember_video_profile在早期分桶中被列入「A 桶 · 补 UI」,经专项侦察后更正为删除 —— 前者的上游 OCR 标签通道从未建起来(平台信号不是瓶颈,infer_platform已从标题/URL 自行补标签),后者的功能被remember_video_profile_form完整覆盖。这两行独立于其他决策,若需回退为「补 UI」,只改这两行即可。
删除的通用影响面:仅 lib.rs 的 generate_handler!;capabilities/*.json 无自定义命令 ACL;无 bench/集成测试目录;单测全为 #[cfg(test)] 内联且不引用这些命令。唯一例外是补缝三连的模块级连带死代码。
🔻 就地更正(2026-09-13):注册清单已搬到
app/src-tauri/src/app_commands.rs(批 0-C3;check-command-registry.mjs:22的DEFAULT_REGISTRY),lib.rs里已无generate_handler!(line-limit-exemptions.md:26自证)。本行的"仅lib.rs"按app_commands.rs读;原文保留。🔴 T21 实测复核:app_commands.rs现含 311 条generate_handler!条目(定义 311 / 注册 311 / 重复 0)—— 即本行「删除的通用影响面 = 注册清单一处」这一判断仍然成立,只是那"一处"换了文件(批 1 删 22 条、批 6 增 1 条、批 7 撤 3 增 1 条,全部落在这一个文件里)。
| 批 | 内容 | 验收 |
|---|---|---|
| 0 基座 | 4 条 ADR + 修订 ADR-010 · 豁免表纠偏 · 拆 4 个超限文件 · token 层 · z-index 标尺 · 图标集 + 单测 · 原语三层 | 4 个 >600 行 → 0;豁免表 100% 一致 |
| ↳ 批 0 的 ADR 归属(批 0-D 收口时更新) | ADR-032 ✅(批 0-A/0-D) · ADR-033 ✅(批 0-D,L1 原语层与视图层契约) · ADR-034/035 顺延(推定为批 3 壳层 / 批 6 动效,见 ADR-033 的「登记」节)· 修订 ADR-010 属批 1 |
— |
| 1 删除批 | 22 条命令 + 补缝三连连带模块 + ADR-010 修订 + 清理 structuredBlocks.ts:63 死文案 ✅ 已落(2026-09-11 立案 / 2026-09-12 落地) |
注册表 334 → 312(−22);cargo test 2300 / 0 / 6 全绿;ADR-010 已废弃;structuredBlocks:63 死文案已清 |
| 2 包体治理(可并行) | manualChunks + 按页动态 import + 量首屏 gzip ✅ 已落(2026-09-12 收口,e46e0e82..9921767c,11 个提交) |
从 651KB gzip 降到达标或给出瓶颈清单 ⇒ ✅ 达标:首屏 654.72 → 92.79 kB(−85.83%),守卫 exit 0、余量 107.21 kB(原「651KB」为过期快照,实测 654.72) |
| ↳ 批 2 的收口(批 2 完成时更新) | 口径注:manualChunks 本身一个字节都不降首屏(只把同一批字节切成多文件,入口仍静态依赖全部 chunk);它的价值是 ① 让批 6 的 GSAP 落进独立懒 chunk ② 给 import() 产生的懒 chunk 稳定的共享 vendor 边界。首屏下降全部来自 import()(Task 6 页级 + Task 7 窗口变体 + Task 8 对话面板,三条缺一不可)。交付形态 = 8 页懒 + 课堂页静态(懒课堂页会把「首屏即被抓取的 20.04 kB」记作 lazy,低估首屏读数 20.04 kB)。终态 25 chunk = 首屏 3 + 懒 22;两窗变体首屏 97.29 / 94.19 kB(计划原推理「入口 + 零 vendor」为假,实测 = 入口 + 4 个 vendor chunk;「变体 < 60 kB」结构性不可达 —— vendor-react 单独即 60,367 B,且三窗共用同一份 index.html、静态闭包逐字节相同) |
收口六门禁(2026-09-12 实测):line-limits --full 0 / 123 / 123 · docs-check exit 0 · registry 312/312/0 · tsc 0 错 · vitest 125 文件 / 1233 用例 · cargo test 2300 / 0 / 6 · clippy 19(集合 identical) · 首屏预算守卫 exit 0 · 92.79 kB。包体瓶颈清单见 批 2 计划 §收口回写 |
| 3 壳层落地 | A′ 顶栏 + ⌘K + 溢出策略 + 窗口尺寸 + 列注册表 + 断点 + --nav-h ✅ 已落(2026-09-12 收口,85d51d83^.. 至收口提交,22 个提交) |
9 页全走注册表 ✅;1024 无溢出 ✅(限定词:常态;toast 已按 A3 移出导航行);7 处魔数归零 **✅(判据重述:已吸收 8 · 有目标未吸收 1 · 无目标 2,见下注 —— 不压回「7」) |
| ↳ 批 3 的收口(批 3 完成时更新) | 改动面 8 个文件族:shell/{navRegistry,columnRegistry,breakpoints,windowSize,TopBar,CommandPalette,ShellFallback,kbCommands,useKbPaletteSearch} + App.tsx + 4 处页面/组件接线(ChatSidebar / GoalsPage / SettingsPage / ClassroomRightPane / NoteReadingView / NotesReadingColumn);--nav-h 的落点是 token 生成器(app/scripts/gen-tokens.mjs 单一真源 → ui/tokens.css 产物,不是手改产物);列契约的执行器归属(A5 裁决):注册表持有规格、useColumnLayout 仍是执行器(选项 (b)「注册表自实现」登记为日后可能的合并方向,且不得声称能力对等);pinnable 字段是本计划取的默认(规格 §6.2 给了字段但未给逐行值,批 3 全行 false,无消费方);本批四个非目标:① 不重做批 2 包体工作(守住)② 不迁 L1 原语(守住,三条 primitives=false 断言)③ 不建视图层(守住)④ 不装 GSAP / 不加动效(守住,CSS 静态属性断言) |
三条验收的机器判据与原始读数:批 3 计划 §收口回写 · tmp/acceptance.md(不入库) |
🔻 批 6 收口就地加注 ·
pinnable的批 3 实际取值(R6.6;2026-09-13,上格原文一字未改):上格「批 3 全行false,无消费方」的取值半句与代码不符 ⇒ 代码是权威:app/src/shell/columnRegistry.ts的notes-outline那一行逐字含pinnable: true,且该文件的口径注释自称「除笔记大纲列…为true」⇒ 批 3 的实际取值 = 除notes-outline外全false(13 行逐行值:12 行false/ 1 行true)。本规格两处(本行与 §6.2 的批 3 回写②)都写「批 3 全行false」⇒ 两处原文均按本加注读;「无消费方」半句成立(全app/src实测 15 处pinnable命中全在同一注册表文件内,无任何读取点)⇒ 本批(列折叠 Flip)只登记消费方缺口,不接线。
🔻 收口评审 M-2 就地加注(2026-09-12,上格原文保留)——「8 个文件族 / 4 处接线」两个数字不可追溯,实测口径如下:
- 改动面实测 = 31 个生产文件(命令:
git diff --name-only 85d51d83^..42e88740 -- app/src app/src-tauri app/index.html app/scripts app/package.json,再剔除*.test.*/test.mjs):app/src/**28(shell/*11 ·ui/*2 ·components/*5 ·pages/*9 ·App.tsx1)+app/index.html+app/scripts/gen-tokens.mjs+app/src-tauri/tauri.conf.json。⇒ 上格「8 个文件族」是计划期陈旧估算(照抄批 3 计划 Task 3 Step 5 的「写清 8 个文件的改动面」),既非实测、也与它自己列的shell/{…}清单(9 个名字)不符。- 接线实测 = 6 处页面/组件(上格写「4 处」却列了 6 个名字 ⇒ 同句内部矛盾):
ChatSidebar/GoalsPage/SettingsPage/ClassroomRightPane/NoteReadingView/NotesReadingColumn。- 另有 18 个新测试文件(
app/src/shell/*14 +components|pages4;git diff --name-only --diff-filter=A …实测),不含在上面的「生产文件」计数里。- 判据按实测口径读(本仓口径:按实测/判据重述,不迁就数字);上格其余内容(
--nav-h落点、A5 裁决、pinnable默认、四条非目标)不受影响。 | 4 原语迁移 | 20 弹层 / 44 空态 / 85 加载 / 196 错误行 / 4 toast / 2 confirm / Button/Surface/Text | z-index ≤6;role="dialog"20/20 | | ↳ 批 4 的收口(批 4 完成时更新 · 2026-09-12) | ✅ 已落(4905d4d8^..<收口提交>,49 个提交 = 48 个实施/评审/修复 + 本节所在的收口提交;含左端点口径见 v0.22 批 4 节);上格原文一字未改。两条验收全部达标:①z-index ≤6—— 裸值 58 处 / 43 文件 / 17 值 → 3 处 / 3 文件 / 3 值(10/999/1000,全是 B2 例外且逐条带理由;冻结名单 58 → 3;六档 =raised 10/panel 100/popover 200/modal 300/modalNested 400/toast 500);②role="dialog"20/20 ——DIALOG_20的 20 个文件全部只经原语持有弹层机制(barrel ∧ 无深导入 ∧ 无自建遮罩 ∧ 无keydown∧ 无裸 z-index),role="dialog"的源码命中只出现在ui/primitives/Modal.tsx。R2 的中间态(必读,否则会引用一句已变形的话):验收第 3 条「五类重复 → 各自 1 个原语」在批 4 结束时并不成立 —— 批 4 走的是 B11「切片 + 棘轮」:只有切片内清零,切片外余量逐类冻结并登记去向(见 §11-3 加注)。八门禁终态:line-limits --full0 / 122 / 122 ·docs-checkexit 0 · registry 312/312/0 ·tsc0 错 · vitest 166 文件 / 1608 用例 / 0 失败(对拍批 4 开工基线 LOST=0 · SHRUNK=0)· 首屏预算 100.30 kB gzip(真实构建,余量 99.70 kB;CSS 62.63 kB 不计入判据只报告)· eager 89 文件(源 76 + CSS 13)/ TS-API 真实边 65 / npm 包 4(Δ 与机理见 v0.22 批 4 节)· Rust 未复跑(本批零 Rust 改动 ——git log 42e88740..HEAD -- app/src-tauri为空)。观测口径:观感从本批真的开始变(叠放值收敛 · 面板宽度档位 · 圆角 6→8 9 处 · 边框/底色冷灰→暖纸 · 20 处阴影换 token),但只有接缝、没有纲领(三档强度/双基调/GSAP 属批 6)。 | | 5 视图层样板 |viewRegistry+ViewSwitcher+ 会话 4 视图 + 笔记 3 视图 + 惰性挂载 + flushSave 守卫 | 各 ≥2 种形式可用;原文不丢 | | ↳ 批 5 的收口(批 5 完成时更新 · 2026-09-12) | ✅ 已落(ad9d80d2^..至收口提交,31 个提交 = 30 个 T0–T17 实施/守卫提交 + 本节所在的收口提交;含左端点口径见 v0.22 批 5 节);上格原文一字未改。上格两处数字与实盘不符,按实测读:① 「会话 4 视图」→ 5 个(raw/tritrack/proof/cardflow/preview—— 多出的preview是既有笔记预览,按 §7.3② 一并进注册表并转为惰性);② 「笔记 3 视图」→ 2 个(raw/cardflow):第三种「带证据三轨」是 C2 的条件项,只读探针判不存在逐段级「笔记 ↔ 证据」读取路径 ⇒ 按 C2 逐字「交付 2 视图 + 就地加注 §7.2/§11-6 + 登记批 7」,不建空壳视图(见 §7.2 与 §11-6 的批 5 加注)。验收「各 ≥2 种形式可用;原文不丢」✅:会话 5 ≥ 2 · 笔记 2 ≥ 2;「原文不丢」= 默认视图raw常驻不卸载且有行为级判据(H1 11/11 · F5 11/11)。三条硬约束 9/9 判据全绿(判据落点与变异体出处见 §7.3 加注)。八门禁终态(HEAD = b4edf8e4· 真实构建产出app/distmtime 2026-09-12 22:58:51 +08:00):line-limits --full0 / 122 / 122(零新增登记)·docs-checkexit 0(扫描 277 / 检查 177)· registry 312/312/0 ·tsc --noEmit0 错 · vitest 184 文件 / 1770 用例 / 0 失败 / 0 skip(逐文件对拍批 5 开工基线2559a3fd166 文件 / 1608 用例 ⇒ LOST=0 · SHRUNK=0;GROWN 4 · ADDED 18)·check-bundle-budget.mjs(真实构建,取tmp/build.lock,attempt=1、finally释放)exit 0 · 首屏 100.49 kB gzip(原始 318,299 B;余量 99.52 kB;CSS 63.23 kB 原始 / 14.51 kB gzip 不计入判据,只报告;入口index-Bn5oI23G.js108,620 B)·bundle-eager-graph91 文件(源 77 + CSS 14)/ npm 包 4,TS-API 真实边口径 66(结论口径;--keep-type-only= 77 自证 ⇒ 差额确由 14 CSS + 11 条纯类型边构成)· Rust 未复跑(本批零 Rust 改动:git log 091d1c3d..HEAD -- app/src-tauri与git log 4905d4d8..HEAD -- app/src-tauri两条均为空)—— 判据仍是批 3 的 2300 / 0 / 6,不得读成「已跑」。观测口径(B9 逐字):「只有接缝、没有纲领」—— 三档强度 / 双基调 / GSAP 在批 6;本批交付的是内容与结构(视图层骨架 + 多视图可用),不是手感。 | | 6 动效系统 | GSAP 接入 + token + 四层 + 三档 + 相变两态 + 6 个签名动效 +usePresence| 可中断可反向;三档正确;60fps | | ↳ 批 6 的收口(批 6 完成时更新 · 2026-09-13) | ✅ 已落(ac504b06^..975b3285,77 个提交 = 批 6 计划 1 + 36 个任务中已提交的 34 个(T15 / T34 各零提交)+ 微单元;含左端点口径见 v0.22 批 6 节);上格原文一字未改。验收面的逐条实际结果(口径 = R0.1 第 2 条「6 个签名动效 + 相变两态 + 承载面 3 项」,读数出处task-34-report.md§10,T36 出最终表):6 个签名动效 6/6 各有 ≥1 生产调用点 —— 唯一缺口 = #2 的反向 / 重播入口 = 0(状态机与判据齐备、无生产入口)· 相变两态 = 单一写入方(shell/phaseSource.ts:84)+ 载体 1 处(App.tsx:394)· 承载面 3/3 链路闭合(采集态 LIVE 仪表/波形 → 到期刻度 → 时间轨/播放头)· 环境层第 3 件(未确认段落墨度)= 1 处(R12.4 要求 ≥2,差 1) · 列折叠 Flip = 2/8 处(授权路径 B) ·[[ts:ms]]端到端只通一半(会话页那一跳未交付 ⇒ 批 7 首要候选)。上格验收列三项:可中断 / 可反向 ✅(双断言模板 + 逐条专属变异体)· 三档正确 ✅(机器面 = 档位映射 + DOM 属性 + 源序 + 时长参数)· 🔴 「60fps」= 未测(jsdom 无合成器;代理判据 = 未动 layout 属性)—— 不得读成「60fps 已达成」。八门禁终态(HEAD = 975b3285· 真实构建产出app/distmtime 2026-09-13T05:10:24.838+08:00 · 入口index-CBZzLV5U.js117,002 B):line-limits --full0 / 122 / 122(零新增登记)·docs-checkexit 0(扫描 280 / 检查 180)· registry 313/313/0 ·tsc --noEmit0 错 · vitest 221 文件 / 2132 用例 / 0 失败 / 0 skip(一次通过、零 flake)·check-bundle-budget.mjs(真实构建,取锁attempt=1、finally释放)exit 0 · 首屏 103.60 kB gzip(原始 326,681 B;余量 96.40 kB;CSS 4 个 68,778 B 不计入判据、只报告)·bundle-eager-graph103 文件(源 89 + CSS 14)/ npm 包 7(结论口径 = TS-API 真实边:75 源文件 / 4 包)· 🔴cargo test --test app_lib_tests真跑:running 2335 tests→test result: ok. 2329 passed; 0 failed; 6 ignored,exit 0(R0.1 第 1 条③ 兑现)·cargo clippy --all-targets:error 0 · lib warnings 15 = 基线。观测口径:从批 5 的「只有接缝、没有纲领」变为纲领与承载面均已落地(B9 的中间态声明在本批到期作废,由「已交付 / 未交付」二分清单取代);但像素面与真实帧率仍未测(jsdom 不可达)。 | | 7 未接线落地 | 12 条补 UI(含kb_search→ ⌘K)· 标签线 · 档位通道 · B 桶 3 条撤下 IPC ·structuredBlocks整模块存废(批 1 控制方裁决:接线(4 个导出全接入、真实置信度渲染「低置信点线」)或删除(连同类名与规格/登记表一并移除)二选一,批 1 未决前不得删) | 标签能写进去;档位选完真生效;structuredBlocks已作出接线或删除的明确裁决 |
🔻 批 7 收口就地加注(2026-09-13,上格原文一字未改):
structuredBlocks的"二选一"由控制方按「逐导出裁决」(第三条路)执行 —— 这不是绕过二选一,而是二选一在两个粒度上各自取正解:①escapeHtml(:13的再导出,真源在utils/html.ts:11)⇒ 只摘 import 与再导出,真源一个字不动;②renderLatex/renderMarkdownTable(唯一消费者是它们自己的测试)⇒ 删;③lowConfidenceClass(唯一生产消费者session-detail/SessionRawView.tsx:138,import 在:50)⇒ 留 + 加宽到 ≥2 生产调用点(顺带兑现批 6 R12.4 环境层第 ③ 件的「≥2」)。本加注即控制方的明文授权(依据rulings.md§C4.1/§C4.2)。🔻 批 7 收口就地加注 · 上格其余三处状态的实测落位(2026-09-13,上格原文一字未改):
- 🔴 「12 条补 UI」的实做面 = 10 条(§C9.1 逐字裁决):
kb_search(#14) 批 3 Task 12 已交付、update_fragment_group(#46) 的记录同步批 1 已完成 ⇒ 本批实做 10 条 =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)。🔴 上格的「12」是规格原文,一字不改 —— 批 8 对账必须能看见「规格写 12、实做 10」的差额来源。- 🔴 registry 的批 7 净值 = 313 − 3 + 1 = 311(−3 = §1 L5 行 31 的三条撤下;+1 = 行 34 新增的
remember_video_profile_tier)⇒ 收口判据 = 311 / 311 / 0。- 🔴 「B 桶 3 条撤下 IPC」的落地形态(行 31 逐字「撤下但保留内部函数」):摘
#[tauri::command]属性 + 删注册条目,函数体逐字保留、不改*_inner名(create_session/add_session_segment/add_session_ocr_block)。 | 8 治理收口 | 豁免表终态 · 回写ui-ux-system.md/theme.md· 新增动效规范章节 · 需求池同步 | 11 条验收全达标 | | ↳ 批 1 的收口(批 1 完成时更新) | 22 条命令已删(本表原写 21 + #41open_capture_float改判;git diff --name-status --diff-filter=D e96ab63d HEAD= 10 个文件)· 补缝三连连带模块已删(ai_judge+AiMockAdapter::enhance+ai_protocol.rs的AiEnhance*半边,−26 用例 = 9+7+10;另 T3 整族删除 −25、T6 −4、T7 −4 ⇒ 全批 −59)· ADR-010 已废弃(文件保留)·structuredBlocks死文案已清(整模块存废登记给批 7) | 收口门禁(2026-09-12 实测):registry 312/312/0 ·cargo test2300/0/6 ·cargo build0dead_code· clippy 19(集合与开工基线 identical)· vitest 124 文件 / 1124 用例 ·tsc0 错 ·line-limits --full0 / 123 / 123 ·docs-checkexit 0 |
🔻 批 8 终态就地加注(2026-09-13 · T21;上格与上面各
>块的原文一字未改) —— 上表 批 8 行(| **8 治理收口** | 豁免表终态 · 回写 ui-ux-system.md / theme.md · 新增动效规范章节 · 需求池同步 | 11 条验收全达标 |)有两处不得照字面读:
- 🔴 「11 条验收全达标」= §11 的 11 条整册验收,不是批 8 的行内验收。批 8 计划
## Global Constraints 二逐字写死:「本批的「三条验收」= 三条主线的验收……不是规格 §11 的 11 条整册验收 —— 那 11 条逐条登记去向」⇒ 🔴 批 8 只兑现与三条主线直接相关的部分,不得声称「11 条全达标」。- 🔴 「新增动效规范章节」已在批 6 落地(
docs/standards/motion.md,bffed928)⇒ 留批 8 的是docs/product/ui-ux-system.md/theme.md的四层动效 / 三档强度回写,🔴 而批 8 仍未做(它只回写了「审校模式」那一节:b077d530·ffb7e28a)⇒ 登记为下一批输入。- 批 8 的三条主线兑现度(逐条机器读数;出处 =
docs/versions/v0.22.md的「批 8 · 治理收口与三条主线」节): · 主线一(「带证据三轨」+「审校模式」两条能力)✅ 成立 —— 注册表第三项落地:app/src/views/registry.ts的FROZEN_VIEW_KEYS.note由 2 键变 3 键 =["raw", "cardflow", "evidence"](T21 于 2026-09-13 逐行直读);全量 vitest 235 文件 / 2300 passed / 0 failed / 0 pending(T21 亲测,时点 2026-09-13T17:34+08:00)。 · 主线二(观感/像素面「收编,不立项」)✅ 成立(含「有读数 ≠ 已统一」的限定) —— 仪器scripts/viewport-probe.mjs298 行在盘、按需入口app/package.json的check:visual在盘、仪器自检 9/9 ✅、14 条观感欠账逐条有读数或具名归属。 · 主线三(治理余项)✅ 四条 4/4 落地 —— CI 挂载(pr-check.yml的无条件 job + 散文探针单列 step)·scripts/validate-all.mjs已删 ·SURFACE_TAG_REGISTRY的键改为(file, tier)·subject ≤50已装上(commitlint.config.js)。- 🔴 段 8f 的四项用户裁决(U1–U4)另计,不并入三条主线:U1 = 音频两条都修 ✅(配置通道 + 面板真开关 + 删会话级联清音频;命令注册表 311 → 312,依据用户裁决 A)· U2 = 只移除凭据槽的代码路径 ✅(已存密钥数据保留、应用内不可达)· U3 =
docs/tech-debt/归档到docs/archive/2026-09-13/✅ · U4 = 观感按需入口入库 + 触发条件写死 ✅(不接 husky、不进 CI)。🔴 U5(真机 / WebView2 冒烟)沿用「跳过」 ⇒ 7 条真机类继续登记、不假装完成。⚠️ 两条口径注:① 本批不新增门禁成员(八闸集合不变;check-exemption-prose只以 CI step 转正、不进八闸对账)② 🔴 批 8 的提交留在本地、未 push(用户前提;「不 push」是本批的唯一强制约束)。- 🔴 本节的自引用边界:上格那「批 8 行」所在的本文件没有在批 8 内被改写成「已交付」—— 本注是追加,
−列为 0(承docs/standards/documentation.md第四部分之补)。
批 0–1–2 期间界面几乎不变 —— 这是设计意图,不是失败。 批 0–1 交付的是「让后面每一批都能一次改对所有地方」的能力。观感从批 4 开始变,骨架在批 3,内容在批 5,手感在批 6。
实施计划的粒度:本规格覆盖 9 批,不建议一次性生成全部 9 批的实施计划。正确做法是每批各自一份实施计划,且后一批的计划在前一批验收通过后再写 —— 因为批 3 之后的细节依赖批 0–2 的实测结果(尤其是包体治理量出的瓶颈清单与拆件后的真实文件结构)。
- 4 个 >600 行文件 → 0;>300 行 100% 在豁免表内且数值与实测一致。
- 手写弹层 20 → 全走
Modal;z-index 不同值 17 → ≤6 档;role="dialog"+ 焦点陷阱 20/20。🔻 收口评审 M-1 就地加注(2026-09-12,上句原文保留)—— 档名写错:
zIndex("palette")档不存在,实盘是zIndex("modal"):app/src/ui/zIndex.ts的六档是raised / panel / popover / modal / modalNested / toast,没有palette(node -e "…/palette/.test(readFileSync('app/src/ui/zIndex.ts','utf8'))"⇒false)。实现用的是zIndex("modal")(app/src/shell/CommandPalette.tsx两处调用;被CommandPalette.test.tsx⑤ 与ui/zIndex.guard.test.ts钉住)。⇒ 本行应按此读:CommandPalette用zIndex("modal")、AI toast 用zIndex("toast")。原文保留的理由:本仓文档回写的一贯口径是「原文 + 加注」,且此处没有改判任何验收判据(口径仍是「全走六档标尺」)。风险已消:批 4 的层级归并不得按palette这个类型系统都不接受的档名做判断。↳ 批 4 收口后更正(收口评审 M-13,2026-09-12):上句里「
CommandPalette.tsx两处调用」是批 3 时点的读数;bde807dc(T9 的 palette 半程)已把层级交给Modal⇒ HEAD(7d541254)实测 0 命中:git grep -n 'zIndex(' -- app/src/shell/CommandPalette.tsx空(bde807dc^上为 2 处)。⇒ 本行的正确读法 =CommandPalette今日不含zIndex("modal")调用,层级由Modal承担;「palette档不存在」的结论不变。 另:读数锚里那句歧义 —— 「手写弹层 20」(§2 弹层行)与 §5.2 的「28 个手写弹层迁移后同样不得…」并存(28 = 弹层 + 确认框 + toast 一类手写覆盖层的合计口径)。批 3 未涉及这组数字中的任何一个,两者都只登记,消歧归批 4/批 8。🔻 批 4 收口就地加注 · 三口径并列 + 例外表 + 有意值收敛(2026-09-12,上面两句原文一字未改;批 4 给出的消歧如下,「消歧归批 8」仍适用于跨文档的对账):
-
验收口径 = 20(规范文本优先,B3)。20 的构成(钉死在
app/src/ui/primitives/dialogMigration.e.test.ts的DIALOG_20,不是散文):A 组 14(T5 的 7 + T6 的 7)+ B 组 4(工作台:KnowledgeSystemWizard·ProofreadPanel·RefineWorkbench·SecondPassPanel)+ E 组 2(PracticeQuestionsOverlays·SopRunOverlay)= 20,逐文件 4 条形态判据(barrel 含Modal∧ 无深导入 ∧ 无自建遮罩 ∧ 无keydown∧ 无裸 z-index)。 -
三个口径并列(不得混用):20 = 本条的验收口径(对话框类);28 = ADR-033 的同行口径(更宽的手写覆盖层合计);34 = 跨行容忍口径(把「
position:fixed与inset:0分写两行」的形态也算进来)。等式(机器判据,双向):34 − 20 = 14 = 11 锚定菜单 + 3 覆盖层;且28 ⊆ 34 ∧ |28| = 28 ∧ 28 == 34 − 6(CROSS_LINE_ONLY_6是跨行口径多出来的 6 条)。逐文件清单与size/testId表见批 4 计划 §收口回写 §一。 -
例外表(B1 + B2,逐条带理由,不许静默):
# 文件 类 为什么不迁 1 components/BrowserChrome.tsx锚定菜单(B1) data-app-menu右键菜单:无对话框语义,只落popover(200)2 components/GroupRowContextMenu.tsx锚定菜单(B1) 透明点击层 + 锚定面板成对;层内相对序由 DOM 序保持 3 components/GroupSidebarRow.tsx锚定菜单(B1) position:absolute; top:100%行内下拉4 components/NoteHeaderActions.tsx锚定菜单(B1) 笔记头操作菜单 5 components/NoteListBatchMenu.tsx锚定菜单(B1) 批量操作菜单 6 components/NoteMoveToGroupMenu.tsx锚定菜单(B1) 「移动到组」菜单 7 components/NoteRowContextMenu.tsx锚定菜单(B1) 行右键菜单 8 components/RouteInfoPopover.tsx锚定菜单(B1) 路由理由气泡 9 components/SessionRowContextMenu.tsx锚定菜单(B1) 会话行右键菜单 10 components/chat/ChatLaunchMenu.tsx锚定菜单(B1) T13-b 从 ChatPage拆出的发起菜单(透明点击层 + 菜单,落popover)11 components/note-selection/SelectionActionMenu.tsx锚定菜单(B1) 选区操作菜单(全仓唯一 window捕获相 ESC 监听在此,一并冻结)12 components/CaptureOverlayPanel.tsx覆盖层(B2) 采集覆盖层的子操作条(嵌在全屏采集面内部;迁档会踢出「覆盖层内部层」语义);其根遮罩今日仍未声明 zIndex—— 登记在案13 components/ImagePreviewOverlay.tsx覆盖层(B2) 图片查看(zoom-out 遮罩 + 92vw 大图):迁 modal(300)会让大图落到对话框档之下14 components/ScreenSelectOverlay.tsx覆盖层(B2) 全屏十字光标屏幕点选:迁档会让采集面被任何弹层盖住(只登记根;其子层在根建栈内 ⇒ 已迁 raised)- 这 14 条的硬守卫:
dialogMigration.e.test.ts② 断言「登记为「不迁」的文件不得 import 原语层」+buttonMigration.test.ts④ 同向复核 ⇒ 本批有 9 处(b1-non-migrated,2.54:1)因此回退并冻结(B21:维持守卫、不放开;批 5/7 若要迁这 14 个文件的排版,必须先由控制方裁决 B1/B2 的守卫范围)。 - 🔻 批 4 收口后更正表(收口评审 I-7;上面这张表与它的原文一字未改):上表第 1–11 行自称是「
34 − 20 = 14里的 11 锚定菜单」,但与机器真源NON_MIGRATED_14(dialogMigration.e.test.ts:115-122)的非*Overlay那 11 条差 3 个成员 —— 文档多BrowserChrome/GroupSidebarRow/NoteHeaderActions,文档缺NoteEditView/NoteLinkToSystem/RichEditorView。表格第 12–14 行(3 个*Overlay)正确。 独立复算(node .superpowers/sdd/2026-09-12-frontend-redesign-batch4-primitives/tmp/docfix/d4-membership.mjs,从.e的导出数组解析、不手抄):
文档表行 文件 在 NON_MIGRATED_14?在 ADR033_28?在 CROSS_LINE_34?真源里的类 1 components/BrowserChrome.tsx❌ 不在 ❌ 不在 ❌ 不在 —(文档误列; .e里它只作TABLE4_ALIAS,并有机器断言CROSS_LINE_34.includes(TABLE4_ALIAS) === false)2 components/GroupRowContextMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 3 components/GroupSidebarRow.tsx❌ 不在 ❌ 不在 ❌ 不在 —(文档误列) 4 components/NoteHeaderActions.tsx❌ 不在 ❌ 不在 ❌ 不在 —(文档误列) 5 components/NoteListBatchMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 6 components/NoteMoveToGroupMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 7 components/NoteRowContextMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 8 components/RouteInfoPopover.tsx✅ ✅ ✅ 锚定菜单(B1) 9 components/SessionRowContextMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 10 components/chat/ChatLaunchMenu.tsx✅ ✅ ✅ 锚定菜单(B1,T13-b 拆件新家) 11 components/note-selection/SelectionActionMenu.tsx✅ ✅ ✅ 锚定菜单(B1) 补 components/NoteEditView.tsx✅(文档原表缺席) ✅ ✅ 透明层(非 *Overlay,属那 11)补 components/NoteLinkToSystem.tsx✅(文档原表缺席) ✅ ✅ 透明层(非 *Overlay,属那 11)补 components/RichEditorView.tsx✅(文档原表缺席) ✅ ✅ 透明层(非 *Overlay,属那 11)12–14 CaptureOverlayPanel·ImagePreviewOverlay·ScreenSelectOverlay✅ ✅ ✅ ✅ ✅ ❌( ImagePreviewOverlay不在 28、属CROSS_LINE_ONLY_6)✅ ✅ ✅ 覆盖层(B2) ⇒ 根因:文档把「recon 的 B1 锚定菜单清单(11 条,多为
position:absolute形态)」与「34 − 20 = 14的非覆盖层那 11 条(含 3 条透明层)」当成了同一个 11;而该表上下紧邻的两句正是「34 − 20 = 14 = 11 锚定菜单 + 3 覆盖层」与「这 14 条的硬守卫」⇒ 表与它自称分解的对象不符。ADR-033:162已同步同一更正。- 🔻 同一行的
b1-non-migrated「9 处」更正(收口评审 M-12):上行的 9 = 回退动作数(tmp/t16b/revert-b1.mjs的SITES= 9 条 / 7 文件:NoteEditView:373·NoteLinkToSystem:258·NoteLinkToSystem:301·NoteListBatchMenu:82·NoteMoveToGroupMenu:135·NoteRowContextMenu:202·RichEditorView:363·RouteInfoPopover:310·RouteInfoPopover:351);该类的冻结处数另算 ——textBaseline.RESIDUAL里kind="b1-non-migrated"的 7 个文件在FROZEN_MUTED_GRAY_BY_FILE的计数之和 = 14(收口修复单元ed07d491之前是 13;差额 1 =components/NoteRowContextMenu.tsx的</x>假阴被修掉,该格 1 → 2)。⇒ 引用时必须写明是哪一个数(回退动作 9 / 冻结处数 14)。
- 这 14 条的硬守卫:
-
🔴 例外只覆盖那 3 条裸值;其余 55 处按 B2 口径登记为「有意值收敛」(durable 登记,出处
task-4-report.md:208-212,由 T4 的8d84ecfe落地):50/51/60/999/1000/1100/1150 → modal(300)·30–61 → popover(200)·900 → panel(100)。这不是「写法变了、观感不变」 —— 叠放值真的变了(如1150 → 300),只是相对序在设计上保持不变;规格 §10 逐字「观感从批 4 开始变」在这里的形态就是「叠放值收敛」。与docs/versions/v0.22.md批 4 节的「诚实代价」同段。
-
- 空态 / 加载 / 错误行 / 弱化文本 / 卡片边框 五类重复 → 各自 1 个原语。
🔻 批 4 收口就地加注 · 本条的中间态(2026-09-12,上句原文一字未改;控制方 B11 的附带硬要求:不加这条注,批 8 会引用一句已变形的话**)**:
- 批 4 结束时,上句「五类 → 各自 1 个原语」在字面上并不成立。 批 4 走的是 B11 的 (B)「切片 + 棘轮」中间态:只有切片内清零,切片外的余量逐类冻结(棘轮只许降)并登记去向(批 5/7)。终局口径不变 —— 上句仍是目标;变的只是批 4 的达成度。
- 五类的终态读数(每类的「切片内 → 0 / 切片外余量 / 冻结数」;命令与逐文件表见批 4 计划 §收口回写 §一):
类 切片内 切片外余量 棘轮冻结数(终态) 空态 EmptyState0(切片 28 文件,非例外命中 0) 5 文件( FROZEN_REST,只许减)+ 例外 8 条全仓命中 ≤44(域内 33 文件) 加载 Loading/Skeleton0(迁移面 10 文件 0 命中) 8(4 backlog 文件 + 3 button-busy+ 1 例外)FROZEN_LOADING_TEXT_TOTAL = 8 == RESIDUAL 8(冻结表 18 键逐格钉死)错误行 StatusLine0(迁移面 49 文件全走原语,含逐文件处数下界) 三红字面量 114 处 / 67 文件 FROZEN_RED_TOTAL = 114(剥注释口径)弱化文本 Text0(切片内 186 处迁完) 63 处 / 44 文件 / 7 类( RESIDUAL逐条带理由)FROZEN_MUTED_GRAY_TOTAL = 63;字号越界 558 处 / 120 文件本批只冻结不迁卡片边框 Surface0(够格 21 处里实迁 14) 边框 226 处 / 108 文件 · 越界圆角 261 / 109 · 阴影 24 处 / 24 文件 三族 FROZEN_*_TOTAL= 226 / 261 / 24;FROZEN_SURFACE_TAG_TOTAL = 14- 🔻 批 4 收口后更正(2026-09-12 · 收口评审 I-6 + 修复单元
ed07d491;上表原文一字未改):上表「弱化文本Text」行的 63 处 / 44 文件 / 7 类 与FROZEN_MUTED_GRAY_TOTAL = 63是旧剥注释仪器的读数。修掉sliceScan.stripComments把</x>的/当正则起点的假阴后,终态 = 64 处 / 44 文件 / 7 类、FROZEN_MUTED_GRAY_TOTAL = **64**(逐文件格components/NoteRowContextMenu.tsx1 → 2;条目数/文件数仍 44)。逐类真源(我自测,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 类 2」是同一类重复计数)。物理恒等式 = 250 = 迁移 186 + 例外 64。 - 「切片」的判据(B11,机器可算):① 本批其它任务已触碰的文件 ∪ ②
pages/**全部 ∪ ③ 该类中有同名测试文件的文件。 - 若控制方当初选 (A) 全量:余量清单就在各类的
*Baseline.ts的RESIDUAL/FROZEN_*_BY_FILE表里(每一条都带非空理由,且「僵尸豁免」判据会红),不需要重新普查。 ⚠️ 判据的限度(诚实登记):emptyStateRatchet的判据来源里,「① 本批已触碰」无法在测试内复算(需要 git 历史)⇒ 那一半只在 gitignored 探针在场时由 ⑥a 覆盖(净克隆里 ⑥askipIf跳过、⑥b 用「盘上可复算的第二源」顶上)。出处:task-t13t15-fix-report.md§六 (a) 5 · §六 (b)。
- CSS 变量 0 → 覆盖全部语义色 / 字阶 / 间距 / 圆角 / 时长 / 缓动;hex 88 → ≤ token 数。
prefers-reduced-motion覆盖率 100%,且系统优先于强度档位。 判据(批 0-D 拍定)= 基类名单 + 动画落点名单,不是「全类集合 ⊇」:每一类原语的根类(动效挂在它身上的选择器)必须在motion.css的媒体查询名单里;且每一处animation声明的选择器原文(含伪元素)也必须在名单里 ——animation-duration/animation-iteration-count不是可继承属性,覆盖写在宿主元素上伪元素拿不到 (T11 评审用 headless Chromium--force-prefers-reduced-motion实测:.ed-skeleton是0.001s/1,而.ed-skeleton::after仍是1.2s / infinite⇒ 当时「让两者都静止」未达成)。名单双向一致(漏一个 = 照旧动;多一个 = 死名字)。 修饰类(--)与子元素类(.ed-modal-head/body/foot·.ed-confirm-seal/-impacts/-keep·.ed-empty__title)不进名单 —— 它们与基类同在一个元素上、已被同一条规则覆盖,逐字枚举只会假红(T10 评审曾担心这条守卫会假红,实测 26/26 绿 ⇒ 不必另设兜底方案)。 机器判据在app/src/ui/primitives/motion-coverage.test.ts。🔻 批 6 收口就地加注 · 本条在批 6 的机器判据与读数(R11.3 / R12.4 / R40.2;2026-09-13,上面原文一字未改):
- 判据落点:
app/src/ui/primitives/motion-coverage.test.ts(名单 + 源序 describe)+app/src/motion/responseSeams.test.ts(I-2 逐条声明带!important/ I-3 两块之间零规则块)+app/src/motion/responseCoverage.test.ts(响应层七类动作回执)+app/src/motion/env.test.ts+app/src/motion/shift.guard.test.ts。✅ 终态(T34 逐件复跑):motion-coverage9/9 passed ·style-seams18/18 passed。 - 🔴 已知残洞两条(如实登记,R46② / R47⑤):①
TopBar.css的动画落点仍无「必须在 reduced-motion 名单里」判据(结构性缺口只补到扫描器这一层;TopBar.test.tsx余 2 行 ⇒ 任何追加必须先拆件)· ② reduced-motion 名单今天只能容纳「基类 或 有animation声明的选择器」,无法枚举 transition-only 落点 ⇒Waveform.tsx的行内 transition 接缝与ColumnResizer的余量同源(机制性缺口,不是「忘了列」)。 - 环境层四件的兑现度见 §4.3 的批 6 加注(第 ③ 件 = 1 处调用点,要求 ≥2);「落了 CSS seam」不算已交付(R11.3 逐字)。
- 判据落点:
- 会话与笔记各 ≥2 种展示形式可用,原文形态不丢。
↳ 批 5 收口就地加注(C2 的条件项 + C17①;2026-09-12,上句原文一字未改)—— 本条终态读数:会话 5 种 · 笔记 2 种,两种都 ≥2 ✅;「笔记 3 种」是条件项、未兑现:
- 会话 = 5 种:
FROZEN_VIEW_KEYS.session = ["raw","tritrack","proof","cardflow","preview"](app/src/views/registry.ts:107)。 - 笔记 = 2 种:
FROZEN_VIEW_KEYS.note = ["raw","cardflow"](app/src/views/registry.ts:108)—— 第三种的「带证据三轨」不存在(C2 的探针判否:task-1-report.md·tmp/t1/c2-evidence-probe.md;T13 独立复现见task-13-report.md§②)⇒ 按 C2 逐字「不存在 ⇒ 交付 2 视图 + 就地加注 + 登记批 7」,不建空壳视图(实测全仓NoteEvidenceTrack*= 0 命中)。 - 本条验收不因此变红:2 ≥ 2 ✅,且「原文形态不丢」成立(默认视图 =
raw,常驻不卸载,§7.3① 的判据另见 §三条硬约束)。 - §7.2 矩阵的同一更正见 §7.2 的批 5 加注;产品机会登记批 7:锚点机制确实存在(
concat.rs:121-127发射 ·anchor_strip.rs:3-4契约 ·note_filter_golden_tests.rs:117-124金测试),批 7 若要做「带证据三轨」必须先写规格——E2 降级为 ms 最近邻、E1/E3 改为「带锚点段落数」,并覆盖OcrDirect/Web/手动笔记/anchor_timestamps=false的无锚点情形(逐条见task-13-report.md§④)。 ↳ 批 7 收口就地加注(C9.17 / C9.10;2026-09-13,本条第 6 行的原文与批 5 加注一字未改)—— 第三种的规格已在 §7.4 交付,实现仍未做: - 🔴 逐字状态:本批只交规格,实现未做。「带证据三轨」的验收口径改写(E1/E2/E3)、两个分母、无锚点四类 fixture 清单、精修前后两态契约全部写在 §7.4;代码零行。
- 🔴 本条验收仍按批 5 的读数成立(2 ≥ 2):笔记视图键终态 =
["raw","cardflow"](app/src/views/registry.ts的FROZEN_VIEW_KEYS.note),本节不改变这个数。 - 实测(批 7 独立复测):全仓
NoteEvidenceTrack*= 0 处 / 0 文件(PROD 与 TEST 双侧;负控zzz_no_such_symbol_zzz= 0)⇒ 不得读成「已交付」。 - 批 8 输入:§7.4 的实现 + 它的两条红线裁决(段级身份 / 新 command)。
- 🔻 口径更正(2026-09-13 · T21 补轮;上一行的实测域收窄,原文保留):上一行逐字写的「全仓」是字面假命题 —— 它包含本行自身(本行就含该串)⇒ 自我指涉。🔴 T21 于
53bd0759实测(入库域 =git ls-files,1,614 文件;口径 = 行含子串,剥注释抹等长空白保偏移):app/src/**(生产 + 测试)= RAW 0 行 / 剥注释 0 行 / 0 文件 ✅ · **app/src/**之外 = RAW 16 行 / 剥注释 6 行 / 3 文件,全部在docs/**(按顶层目录docs:16)—— 含本行自身。 - ⇒ 🔴 正确表述:「
app/src/**(生产 + 测试)= 0 处 / 0 文件」(这才是「实现未做」的有效证据域);app/src之外仍有 16 行 / 剥注释 6 行的文档提及,那不是实现。上句的「全仓」一律按本注收窄读(本页 §7.4 的:538早已按app/src/**写,两处现口径一致)。 ⚠️ 探针卫生教训(本轮实测复现):该声明的阴性对照zzz_no_such_symbol_zzz在入库域命中 7 行 / 5 行(剥注释)/ 3 文件(全在docs/**) ⇒ 🔴 对照串被自己的产物污染(它被写进了报告与文档)⇒ 阴性对照一旦入库就不再有效;改用每次现造的随机串,或把对照域明确限定在app/src/**。(阳性对照useTriTrackAlign在app/src= 17 行 / 12 行(剥注释)/ 6 文件 ⇒ 非假 0。)
- 会话 = 5 种:
🔻 批 8 终态就地加注 · 本条上面那句「批 8 输入」已闭合并给终态读数(2026-09-13 · T21;上面各块原文一字未改):
- 🔴 第三种「带证据三轨」已于批 8 交付:模型层
app/src/views/note/noteEvidenceModel.ts(202 行)+ 视图片app/src/views/note/NoteEvidenceTrackView.tsx(178 行)+ 容器取数app/src/hooks/useNoteEvidence.ts(157 行),提交 =de1f43aa·8cc627de·08b1afda·e493eac8(行数为 T21 于 2026-09-13 用countLines()口径实测)。- 🔴 笔记视图键由 2 键变 3 键:
app/src/views/registry.ts的FROZEN_VIEW_KEYS.note逐字 =["raw", "cardflow", "evidence"](T21 逐行直读)。- 🔴 但本条验收的口径不变,仍是「各 ≥2 种」 ⇒ 会话 5 / 笔记 3,
3 ≥ 2✅;不得把「终态 3」写成「本条要求 3」或「本条因批 8 而改变」。- 两条红线裁决的落地(承 §7.4 §D 的批 8 加注):① 段级身份走「派生序号」(零 schema 改动)② 不开新 command(复用既有
get_session_detail已返回的segments+ocr_blocks)。- 🔴 仍未做 / 未覆盖:真机 / WebView2 冒烟由用户裁决跳过(U5) ⇒ 本条实现面的「端到端」止于 jsdom / Rust 单测层;像素 / 观感一致性未验证(
≥2是形式数,不是「两种形式看起来对」)。
- 47 条未接线命令逐个有结论,无「不知道」。
进度(批 1 收口,2026-09-12):47 条中 22 条已删(含 #41 改判)、25 条处置已定但未执行(补 UI 12 → 批 7 · 登记不排期 7 → 批 7/无期 · 撤下 IPC 3 → 批 7 · 有意保留 3 → 无期)。无「不知道」。批 1 计划 §现状普查第三节给出 47/47 的逐条处置表;删除后复算 = registry 312 / 前端零引用 25 条(= 47 − 22,逐条与上列归属一致)。 进度(批 7 收口,2026-09-13):registry 313 → 311(−3 撤下 IPC + 1 新增
remember_video_profile_tier)· 前端零引用 24 → 11(实测值见收口报告;口径 = 上格那 47 条中仍在 registry 者 22 条里前端生产零引用的条数;仪器 = 五形态并列带引号定界字面量探针,正控invoke(命中 68 个生产文件、负控 0;kb_search已交付的 1 条不计入)· 本次加注不改上格原文。- 差额逐条:24 → 11 = −13,分解 = −10(本批实做补 UI 的 10 条各得 ≥1 生产调用点)+ −3(撤下 IPC 的三条随注册一起离开本集合)。同格局:上格「25 条」是剩余命令条数(含
kb_search)⇒ 现 22 条(−3 撤下);条数 − 零引用 = 11 = 有引用数(与逐条读数一致)。 - 🔴 新命令
remember_video_profile_tier不在上格的 47 条内:前端生产调用点 2(components/ProfileDetector.tsx)⇒ 不计入零引用(它的义务是 §1 L5 行 34 的「新增命令」,不是本格的补 UI)。 - 🔴 残留 1 条挂着「补 UI(本批)」却仍零引用:
update_fragment_group(#46) 全app/src/**(含测试)命中 0 文件 / 0 处,而它仍在 registry ⇒ 本批未接线(它被 §C9.1 排除出 10 条名单,理由是「记录同步」那一半批 1 已做,不是因为接线已做)⇒ 登记为批 8 输入,并见 §9 该行的状态更正注。 - 🔻 收口更正(2026-09-13 · T21 追加轮;上面三条原读数一律保留为「T21 首轮」的历史读数):
update_fragment_group(#46) 已在批 7 内由 T23 补做(125eec85+5f662811+5d59e332;T21 独立复测 PROD 0 → 1,落点components/FragmentGroupAction.tsx:92逐字invoke("update_fragment_group", { fragmentId, groupId: target }))⇒ 🔴 残留 1 条 → 残留 0 条;🔴 前端零引用 11 → 10(口径不变:上格那 47 条中仍在 registry 者 22 条里的前端生产零引用数)⇒ 有引用数 11 → 12(其中本批实做补 UI = 11 条:T20 的 6 + T23 的 1 + T18/T19 的 4;kb_search是第 12 个有引用者,但它属批 3 交付)。⇒ 上面那条第 4 项(「残留 1 条」)的处置改为「已交付」,§9该行的状态更正注已在表末就地更正。⚠️ 批 1 的实测更正(供批 2+ 引用本条时注意):计划的「不删清单」在本批被证伪五次(artifact_templates族 /AiEnhance*半边 /vad_threshold_slot三符号 /spec_from_kind/ 调用点计数),根因是**用「看起来还有人用」代替「删除后可达性」**作保留判据 ⇒ 后续批次判断连通性请照「收口回写」节的四条约纪律(计划docs/superpowers/plans/2026-09-11-frontend-redesign-batch1-deletions.md)。
- 差额逐条:24 → 11 = −13,分解 = −10(本批实做补 UI 的 10 条各得 ≥1 生产调用点)+ −3(撤下 IPC 的三条随注册一起离开本集合)。同格局:上格「25 条」是剩余命令条数(含
- 标签能写进去且标签过滤面板有内容;画面档位选完真的生效且跨会话记住。
🔻 批 8 终态就地加注 · 本条在批 8 的状态(2026-09-13 · T21;本行原文一字未改):
- 🔴 批 8 对本条零改动、零复跑:批 8 的三条主线(两条能力 / 观感收编 / 治理余项)与四项用户裁决(U1 音频两条 · U2 凭据槽代码路径 · U3
docs/tech-debt/归档 · U4 观感按需入口)没有一条落在这条验收上 ⇒ 🔴 本条的结论仍以批 7 的收口读数为准,不得读成「批 8 重新验证过」。- 🔴 防误读(逐字):批 8 的 U1 是「音频存储开关 + 删会话删音频」,与本条的「标签 / 档位」无关 ⇒ 不得把它算进这一条;批 8 也未触碰任何标签线或档位通道的生产代码。
- 🔴 本条的「真机面」仍未覆盖:批 7 的「档位选完真生效」判据是代理判据(记忆体往返 + 负控),不是「采样参数真被采集链路消费」的像素级证据;且真机 / WebView2 冒烟由用户裁决跳过(U5)。
- 批 8 的相关读数(只作旁证,不作本条判据):
check-command-registry312 / 312 / 0 ·cargo test --test app_lib_tests2378 passed / 0 failed / 6 ignored ·npx tsc --noEmit0 错(均为 T21 亲测,时点 2026-09-13T17:32–17:35+08:00)。
- JS 包首屏 gzip 达标或给出瓶颈清单;GSAP 只在独立 chunk 懒加载。
进度(批 2 收口,2026-09-12):✅ 前半达标 —— 首屏 JS gzip 92.79 kB < 200 kB(预算真源
docs/standards/performance.md:28),判据工具scripts/check-bundle-budget.mjsexit 0、余量 107.21 kB、懒加载 22 个 574.84 kB 不计入。 后半 ✅ 已就位但未装 GSAP(「不装 GSAP」是批 2 的硬非目标):app/src/build/manualChunks.ts的vendor-gsap精确包名槽位已预留并被单测钉住(含反例守卫,实测真实构建 746 次调用中vendor-gsap返回 0 次、dist无该 chunk);批 6 装 GSAP 时必须用import(),判据见批 2 计划 Task 5。⚠️ 口径警告(勿误读本条的达成原因):manualChunks自身不降低首屏字节;本条达标全部来自import()(页级 + 窗口变体 + 对话面板)。 进度(批 5 收口,2026-09-12):✅ 前半继续达标且几乎持平 —— 首屏 JS gzip 100.49 kB < 200 kB(余量 99.52 kB),scripts/check-bundle-budget.mjs(真实构建,取tmp/build.lock)exit 0;相对批 5 前基线(091d1c3d冻结值 100.30 kB / 100,297 B)Δ = +188 B gzip(+0.19%),全部落在入口 chunk(108,099 → 108,620 B,+521 B);首屏chunk 个数 3 → 3(Δ=0,构造性成立)。CSS 63.23 kB 原始 / 14.51 kB gzip 不计入判据,只报告(基线 62.63 kB ⇒ +599 B)。懒 chunk 22 → 31 个 · 583.98 kB gzip(1,805,017 B 原始;不计入预算)。后半仍 ✅ 未装 GSAP:app/src/build/manualChunks.ts本批零改动、零新增依赖(npm 包 4 → 4),@keyframes零新增、vendor-gsap槽位仍 0 命中 ⇒ 交接批 6。 诚实代价(本条的批 5 形态,逐条带读数):①ViewSwitcher进 barrel 的首屏 Δ = JS0 B+ CSS+604 B—— 计划 C14① 的「首屏 Δ 不是 0」被实测否证:T5 的时点读数(dist = 25 个.js)显示ed-btn-group/ed-btn--segment0 命中任何 JS、只在首屏 CSS 里命中 ⇒ rollup 把ViewSwitcher的 JS tree-shake 掉了(当时无调用点),终态(34 个.js)该字面量命中懒 chunkregistry-C-RvXIfE.js⇒ 机理 = barrel 里有导出 ≠ 产物里有模块。② 「页 chunk 变小、总懒基本持平」:SessionsPage页 chunk −10,288 B ·NotesPage页 chunk −4,815 B(视图代码搬出页面 chunk ⇒ 懒 chunk 增 9 个真新增块)。 🔻 批 6 收口就地加注 · 本条后半(GSAP 懒加载)在批 6 的落地读数(R2.1 · R11.1 · R63.3;2026-09-13,上面原文与批 2/批 5 进度注一字未改):- ✅ 前半继续达标:首屏 JS gzip 103.60 kB < 200 kB(余量 96.40 kB),
scripts/check-bundle-budget.mjs(真实构建,取锁attempt=1+finally释放)exit 0。Δ(对批 5 收口的 100.49 kB)= +3,118 B(+3.10%);原始 +8,382 B(+2.63%)全部落在入口 chunk(108,620 → 117,002 B);vendor-react/vendor-tauri逐字节不变;首屏 chunk 数 3 → 3(Δ 0,构造性成立)。CSS 68.78 kB 原始 / 15.62 kB gzip(4 个)不计入判据、只报告(批 5 = 63.23 kB / 3 个 ⇒ +5,549 B;归因必须含 T12 / T13 / T19 / T29,不止 T5/T6)。 - ✅ 后半「GSAP 只在独立 chunk 懒加载」成立:产物有
vendor-gsap-BQLVn3Z6.js(105,584 B)且firstScreen.chunks不含它;判据 =engine.guard.test.ts的闭包交集(不是白名单),真实构建后复跑 11/11 passed、exit 0。 - 🔴 结论口径唯一(R63.3 钉死):首屏静态可达的源文件数只许用 TS-API 真实边口径 = 66 → 75(+9)、npm 包 4 → 4(Δ 0);
bundle-eager-graph的工具读数(91 → 103 文件 / 4 → 7 包)只作旁证,且必须注明「其中 2 个是纯类型边(gsap/@gsap/react,由import type … from "../motion/engine"顺边走到值导入)+ 1 个是注释字面量假命中(views,出自app/src/types/session.ts:347的 JSDoc)」。 - 懒侧账(不计入预算,只报告):懒 chunk 31 → 36、原始 +354,344 B、gzip 583.98 → 698.86 kB(+114.88 kB);归因 94.1% / 92.0% 来自两块 ——
vendor-katex+227,858 B(T28 让structuredBlocks.ts首次进图 ⇒katex@0.18.4的第二份副本进产物;懒侧今天没有任何预算门禁)+ 新块vendor-gsap+105,584 B。🔴 该代价逐字进v0.22批 6 节的「诚实代价」,并登记两条批 7/8 候选:「把lowConfidenceClass从structuredBlocks.ts析出轻模块」+「懒侧字节纳入门禁」。
- ✅ 前半继续达标:首屏 JS gzip 103.60 kB < 200 kB(余量 96.40 kB),
- 6 个签名动效各自可中断、可反向,reduced-motion 下正确降级。
🔻 批 6 收口就地加注 · 本条 6 个签名动效的四行判据落点(R8.1–R8.6 · R11.4;2026-09-13,上面原文一字未改):
- 「可中断 / 可反向」的判据形态 = 双断言(同时断
gsap.globalTimeline.getChildren().length(或旧 tween 的totalTime()冻结)与目标元素style.transform)—— 只看style.transform会假绿(GSAP 3 默认overwrite:false)。唯一出口 =app/src/motion/controls.ts(interrupt()真kill,且killTweensOf先、timeline.kill()后)。⚠️ getChildren()默认是递归口径(本实现下的正确值是 2);只有getChildren(false, true, true)才=== 1。- 四行判据的落点(逐条在
task-34-report.md§10 给出生产调用点):#1 对齐views/session/useTriTrackAlign.ts· #2 显影components/session-detail/useRevealChoreography.ts· #3 相变凝固shell/usePhaseFreeze.ts· #4 刻度生长components/review/useScaleGrowth.ts· #5 回跳views/session/usePlayheadJump.ts· #6 记忆浮现components/review/useRevealMemory.ts(每条各带专属变异体与「三档 / reduced-motion 降级」用例)。- 🔴 降级路径的诚实边界:
prefers-reduced-motion下跳终态由controls.ts统一实现(matchMedia自带守卫);像素面(真的直线 / 真的 220ms 淡入)不可判;Flip的几何位移零可观测 ⇒ 只用「结构契约 + Flip 已注册 + timeline 存在 + 属性集合 ⊆ transform 族」的弱判据。
npx tsc --noEmit0 错 ·npx vitest run全绿 ·cargo test全绿(每批)。进度(批 3 收口,2026-09-12):八门禁全绿(
line-limits --full0/123/123·docs-checkexit 0 · registry 312/312/0 ·tsc0 错 · vitest 143 文件 / 1370 用例 / 0 失败 ·cargo test --test app_lib_tests2300/0/6 逐字持平 · 首屏预算 97.16 kB < 200 kB(exit 0,余量 102.85 kB;CSS 不计入该判据,只报告 52.27 kB 原始 / 12.58 kB gzip)· clippy 位置集合 20 = 基线,SET-IDENTICAL)。⚠️ 「vitest 全绿」本轮含一条既有 flake(components/KnowledgeGraphView.test.tsx > 单击节点…):本次全量未复现,但在批 3 开工基线树a7bd1899上复现过(隔离复跑 11 passed / exit 0)⇒ 既有负载敏感 flake,非本批引入(判据与两种读数见批 3 计划 §收口回写)。 进度(批 4 收口,2026-09-12):八门禁终态在静止干净树上重跑(HEAD = 199da54b·app/distmtime 2026-09-12 19:54:33 · 采集 19:5x):line-limits --full0 / 122 / 122(--write复跑零 diff ⇒ 豁免表不在收口提交路径里)·docs-checkexit 0(扫描 276 / 检查 176,五项全 ✅)· registry 312/312/0 ·tsc --noEmit0 错 · vitest 166 文件 / 1608 用例 / 0 失败(逐文件对拍批 4 开工基线 143/1370 ⇒ LOST=0 · SHRUNK=0;GROWN 6 条 · 新增 23 个测试文件,逐条见批 4 计划 §收口回写 §二)·check-bundle-budget.mjs(真实构建,取tmp/build.lock)exit 0 · 首屏 100.30 kB gzip(余量 99.70 kB;CSS 62.63 kB 原始 / 14.42 kB gzip 不计入判据,只报告)·bundle-eager-graph89 文件(源 76 + CSS 13)· npm 包 4,TS-API 真实边口径 65,Δ = 0(机理见批 4 计划 §收口回写 §二)·cargo test未复跑 —— 本批零 Rust 改动(git log 42e88740..HEAD -- app/src-tauri实测为空),判据仍是批 3 收口的 2300 / 0 / 6;不得把「未跑」写成「已跑」。⚠️ 一条已知 flake(components/KnowledgeGraphView.test.tsx的负载敏感用例)在本批多份报告里各出现过 1 次、孤立复跑均全绿 ⇒ 既有现象,非本批引入。 ↳ 收口后处置(2026-09-12,cd85e4c3;控制方已裁):该 flake 的状态记为「已加固、未复现」—— 收口修复单元做了最小稳定性修改(components/KnowledgeGraphView.test.tsx的 18 处waitFor超时5000 → 15000,与vitest.config.ts的testTimeout: 15000对齐;未放宽任何断言、未加睡眠、未改配置、未加retry),但本机两种负载各 8 次 + 无负载 6 次均未复现 ⇒ 不声称「已修好」。纪律:① 变异体实验不得与全量测试并发(负载会把 flake 变成假红);② 今后若在顺序执行下再红 ⇒ 按新 flake 重新定位。 进度(批 5 收口,2026-09-12):八门禁终态在HEAD = b4edf8e4上采集(采集窗口 22:57:07 – 22:58:51 +08:00;真实构建产出app/distmtime 2026-09-12T14:58:51.595Z = 22:58:51 +08:00,入口index-Bn5oI23G.js):line-limits --full0 / 122 / 122(--write复跑逐字节零 diff,sha256 相同 ⇒ 豁免表不在收口提交路径里)·docs-checkexit 0(扫描 277 / 检查 177,五项全 ✅)· registry 312/312/0 ·tsc --noEmit0 错 · vitest 184 文件 / 1770 用例 / 0 失败 / 0 skip(--frozen逐文件对拍批 5 开工基线2559a3fd的 166 文件 / 1608 用例 ⇒ LOST=0 · SHRUNK=0;GROWN 4 · ADDED 18)·check-bundle-budget.mjsexit 0 · 首屏 100.49 kB gzip(余量 99.52 kB)·bundle-eager-graph91 文件(源 77 + CSS 14)/ npm 包 4,TS-API 真实边 66 ·cargo test未复跑 —— 本批零 Rust 改动(git log 091d1c3d..HEAD -- app/src-tauri与git log 4905d4d8..HEAD -- app/src-tauri两条均为空);判据仍是批 3 收口的 2300 / 0 / 6,不得把「未跑」写成「已跑」。⚠️ 本条的仪器口径(批 5 实测,供后续批次引用):vitest 的「文件数」必须用testResults.length—— vitest 4.1.11 的 JSON 顶层没有numTotalTestFiles字段(Object.keys(json)实测仅 12 个键;hasOwnProperty= false、typeof=undefined),而numTotalTestSuites= 647 是describe块数、与文件数差 463 ⇒ 两个字段都不能当文件数用。另:numPendingTests1 → 0(skipped归零,全由批 5 收口的两个守卫提交解释;闭合式1750 + 19 + 1 = 1770)。 批 5 的既有 flake 状态:components/KnowledgeGraphView.test.tsx的负载敏感用例本批全量未复现(批 4 的「已加固、未复现」状态继续有效);批 5 的 vitest 终态 0 失败。 进度(批 6 收口,2026-09-13):八门禁终态在HEAD = 975b3285上采集(真实构建产出app/distmtime 2026-09-13T05:10:24.838+08:00,入口index-CBZzLV5U.js):line-limits --full>6000 · 301–600 档 122 · 登记条目 122(零新增登记)·docs-checkexit 0(扫描 280 / 检查 180,五项全 ✅)· registry 313/313/0 ·tsc --noEmit0 错 · vitest 221 文件 / 2132 用例 / 0 失败 / 0 skip(一次通过、零 flake;对拍批 5 收口的 184 / 1770 ⇒ +37 文件 / +362 用例)·check-bundle-budget.mjsexit 0 · 首屏 103.60 kB gzip ·bundle-eager-graph103 文件(源 89 + CSS 14)/ TS-API 真实边 75 · 🔴cargo test --test app_lib_tests真跑(本批有 Rust 改动 ⇒ 必跑):running 2335 tests→2329 passed; 0 failed; 6 ignored,exit 0(与批 3 基线 / 批 5 持平 ⇒ 用例数 Δ = 0)·cargo clippy --all-targets:error 0 · lib warnings 15 = 基线。⚠️ Rust 侧的判据口径(R25.1):不得要求逐字复现2303/0/6——ffmpeg::tests::run_captured_handles_large_output有基线树复现(含 10s 墙钟超时,与全量并发时被拖超时)⇒ 判据 = 「本批相关用例全绿 + 唯一红若是该 flake 则须单跑复绿」。🔴 六个负载敏感 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 个不在名单内的瞬时红:pages/NotesPage.test.tsx编辑标题→完成 ·pages/ReviewPage.test.tsx打开即见到期数 ·components/SessionDetailPanel.test.tsxP1 默认视图是原文)⇒ 判据 = 「单跑复绿 + 提交树全量绿」,不是「命中某个名单」;且全量 vitest 必须在无并发单元时跑(R40 附)。
| 项 | 状态 |
|---|---|
open_capture_float 前端现有开法 |
✅ 已结清 2026-09-11:前端 0 调用者(活路径为 float_toggle + close_capture_float)⇒ 改判为「删」,落地于批 1 |
| 软删 / 回收站(审计 D2 丙方案) | 独立技术债 —— 需 schema 迁移 |
| T7 档案记忆增量(命中计数 + 会话后自动修正) | 基础闭环已通,增量登记 |
image_stream_store.rs 图像流接线(L6) |
档位通道做完后才具备前提 |
| 滚动驱动动效 · 图谱浮现 · 笔记树生长 · 熵减收拢 | 登记不排期(已从「不做」改为「待议」) |
| 3 套 markdown 渲染器归一 | 可并入批 4 → ⚖️ 2026-09-12 已裁定:不并入批 4(批 4 侦察的裁决 B8 .superpowers/sdd/2026-09-12-frontend-redesign-batch4-primitives/rulings.md:批 4 已背 510 按钮 + 34 弹层 + 44 空态 + 88 加载 + 190 错误行 + 1271 字号,再并入大模块会让单批不可验收)⇒ 登记去向:批 5(视图层)或批 7(未接线落地)。本行「可并入批 4」是许可不是命令,原文保留 |
| 审计文档 D1–D10 编号复用(§4 与 §6 批 3 两套 D 编号) | 需消歧,否则引用会出错 |
| 「某个具体的瞬间希望它是活的」 | ✅ 已答复 2026-09-11:「我希望我在对其进行交互时,它是活的」 ⇒ 已并入 §8.6.1(四条硬约束:配重翻转 / 每个动作都要有即时回执 / 可中断可反向 / 无障碍优先)。批 6 的 6 个签名动效照此配重。 |
旧单 provider 凭据槽 "default" 在应用内永久不可撤销(ai_save_key/ai_clear_key/ai_test_connection 删除后无 IPC 写/清路径) |
登记不排期 · 归属「处理 AI 凭据」的批次做产品裁决(建议与批 7/批 8 的产品文档 pass 同批)。正解 = 新增一条 provider 通道的「清理遗留 scope」命令,不是恢复旧命令;读兜底与启动迁移仍在,前端本就 0 引用(非回归)。出处:批 1 计划「未做(登记)」表 |
批 1 后的 requirements-pool.md 功能级陈旧表述(REQ-050「走 AI 补缝(V1.0)」· REQ-052「五档案模板 + 产物视图 + 落笔记」· REQ-053「低置信/AI 占位样式」) |
登记不排期 · 产品文档 pass(与批 7 的未接线落地判定同批):这三条不点名已删符号,属产品功能级状态重写,删除批不做。出处:批 1 Task 10 报告 §6/§9 |
🔻 批 5 收口就地加注 · 「3 套 markdown 渲染器归一」的去向(A8 = C8 = D8;2026-09-12,上表原文一字未改)—— 批 5 未承接,转批 7****:
- 裁决:批 5 不做归一(理由与批 4 的 B8 逐字同族:批 5 已背 5 个新视图 + 注册表 + 1 个新原语 + 惰性挂载 +
flushSave守卫 + 2 个贴边文件拆件,再加渲染层归一同样不可验收;且NotePreviewView无测试面,替换它没有回归网)。ChatMessageMarkdown→NoteMarkdown的归并、NotePreviewView手写解析器的替换都转批 7。- 批 5 只保证「不新增站点」(防「3 套变 4 套」的硬要求):
react-markdown运行时站点 = 2(NoteMarkdown/ChatMessageMarkdown,不变)·app/src/views/**的react-markdown站点 = 0(含import type;实测含 type 也 0)·remark-*+rehype-*= 8(不变)· 零新增依赖。笔记卡片流的派生器views/note/noteCardModel.ts不手写 markdown 解析器(复用既有react-markdown栈 + 自定义组件映射产出卡片结构),文件头显式命名「结构派生器,批 7 归一」(判据:该行存在)。- 口径更正(C17②,文档与后续批次一律照此写):本行的「3 套」应读作「4 套活 + 1 套死」——
NoteMarkdown.tsx:18·ChatMessageMarkdown.tsx:8·utils/refineDiff.ts:78 mdLineHtml(计划未点名的第 4 套手写解析器) ·structuredBlocks.ts(第 5 套、无生产消费者)。T12 的判据不受影响。- 行数代价:
components/NoteMarkdown.tsx244 → 266 行(只追加一个槽 + 一个类型导出,删除行 = 0;预算 ≤270 ✅)。- 出处:批 5 计划 §收口回写 §七 ·
tmp/t18/measurements.md§9 A8。
🔻 批 7 收口就地加注 · 「3 套 markdown 渲染器归一」的去向终态(2026-09-13,上表与批 5 加注原文一字未改):批 7 已完成归一,形态 = C10.1 的「两支手写链合成一支 + #2 并入 #1」:新建
utils/markdownLine.ts(100 行:#3refineDiff.ts的mdLineHtml+ #4NotePreviewView.tsx的renderMarkdown合成一支,两个具名模式常量逐字保留原样式 ⇒ 零观感变化)·ChatMessageMarkdown并入NoteMarkdown后删除(站点 2 → 1、插件站点 8 → 4)·structuredBlocks按 §C4。终态 = 2 套活(NoteMarkdown+markdownLine)。🔴 未做:把两支手写链换成 react-markdown(禁止 —— 它们是给dangerouslySetInnerHTML的串生成器,换 = 改 DOM 形态/样式/安全面,而 #4 无回归网)。
- 🔴 口径逐字(§C11.1 第 ③ 条要求「报告与规格回写里逐字写」):归一 = 逻辑归一;观感统一未做,归批 8。
- 🔴 补登规格加注的漏点(C4.3)—— 第 4 套活渲染器 =
components/NotePreviewView.tsx:40 renderMarkdown:上表与批 5 加注把「第 4 套」记作utils/refineDiff.ts:78 mdLineHtml、把structuredBlocks.ts记作「第 5 套」,漏点了NotePreviewView.tsx:40 renderMarkdown—— 它才是NotePreviewView那条独立渲染链的真身(批 7 开工实测 346 行,终态 364 行;dangerouslySetInnerHTML两处在:295/:301,图片分支的容器侧前置判断在:61)。🔴 批 7 开工时它"无测试面"(§C9.3 因此把「先补表征测试再替换」定为硬顺序)⇒ T166509e04c已补components/NotePreviewView.render.test.ts(34 用例 / 53 处expect,T21 实测 234 行),T15 的 M1 与 T17 的迁移各有回归网(洞已补上 = 实测事实,不再是推断)。本加注补上这个漏点。- 执行顺序与残余(如实登记):先 T16 补回归网 → T15/T17 迁移(
NotePreviewView迁入markdownLine、RefineWorkbench侧同支受益)⇒[[ts:ms]]芯片在两条串渲染链上均已可点(data-ts-ms+ 容器侧事件委托);🔴 两处页内 seek 未接(AiRefineCard/NoteAiDialog,§C49.3 判为另一条线 ⇒ 批 8 输入)—— 不得声称「[[ts:ms]]全链已通」。
🔻 批 6 收口就地加注 · 「登记不排期」四项的自证 + 本批新增登记项(R0.2 · R5.5-b · R63.1;2026-09-13,上表原文与批 5 加注一字未改):
- 🔴 R0.2 的自证:本批对四项的被做数 = 0**。逐项(自证口径 = 全批 77 个提交的改动面 +
app/src实测):① 滚动驱动动效 = 0 处(ScrollTrigger未装、未注册;engine.ts的插件集合恰 4 个)· ② 图谱浮现 = 0 处(KnowledgeGraphView零改动)· ③ 笔记树生长 = 0 处 · ④ 熵减收拢 = 0 处。⇒ 上表第 5 行的「登记不排期」在本批未被触碰(批 6 承接的 6 个签名动效不在此列,R0.2 已逐字判过)。- 本批新增的登记项(逐条带去向):①
aligned的残余偏差 D3–D6(每次暂停 ≤300ms · 停止尾块 ≤200ms · 逐包重采样亚样本;量级未实测、漂移分布今天不存在)→ 批 7/8 · ② 导入会话无音频承载面(音轨在%TEMP%且导入结束即删、sessions表无源视频路径列 ⇒session_audio_path恒Ok(None))→ 产品裁决 · ③ 跨窗口档位 / 相位同步(?float=1/?overlay=1各自独立)→ 批 7/8 · ④ 孤儿 sidecar({id}.wav.meta.json不在cleanup的.wav过滤面内)+ 删会话不删音频 → 与 ② 一并裁决 · ⑤ 🔴Flip的width/height与 §11-10 属性集合判据的冲突(Flip 会写 layout 属性)⇒ 如实登记为「属性集合判据在 Flip 上不成立」,不得为让判据变绿而放宽 R8.4 → 批 7/8 与判据纪律 · ⑥ADR-019缺号(不补、不复用,只登记)· ⑦docs/tech-debt/仍挂起 → 用户裁决(T36 收口报告列三个选项) · ⑧ 懒侧字节无预算门禁 +katex@0.18.4第二份副本(R63.1)→ 批 7/8 候选:把lowConfidenceClass从structuredBlocks.ts析出轻模块 / 懒侧纳入门禁 · ⑨[[ts:ms]]的会话页那一跳未交付 → 批 7 首要候选 · ⑩usePlayheadJump等 hook 无 unmount 清理(时间线在卸载后仍存活,潜在残留)→ 波 D 已评估、登记批 7/8。
🔻 批 8 终态就地加注 · §12 表内「旧单 provider 凭据槽
"default"在应用内永久不可撤销」那一行(2026-09-13 · T21 落库时该行在:979) ——⚠️ 表内不能插块引用(会截断表格) ⇒ 按批 7 §9 的先例整表之后就地在注、并逐字点名该行;该行原文一字未改(见上表)。
- 🔴 原文那句「读兜底与启动迁移仍在」现在是假话:批 8 的 T25 已移除那条读兜底与启动迁移路径 —— 提交
a054ec73「fix(ai): 移除默认凭据槽作为合法槽位的路径」(parent9b1e8aa8;写集恰 5 条 =ai_credentials.rs·ai_credentials_tests.rs·app_setup.rs·commands_ai_providers.rs·commands_ai_providers_tests.rs),紧随其后的是ae3bba3e「test(ai): 收紧遗留凭据槽判据的具名红点」(parent =a054ec73)。 ⇒ 🔴 原文保留、本注为准:上表该行的「读兜底与启动迁移仍在,前端本就 0 引用(非回归)」描述的是批 1 时点;批 8 时点已不成立。- 🔴 必须并读的另一半(否则会把「移除了代码路径」误读成「数据被抹除」):已存密钥数据保留,且应用内不可达 —— 这是 U2 的 (ii)「不做」的刻意边界(无迁移即销毁不可逆)⇒ 本批只移除代码路径,不物理抹除任何已存数据;将来若要清理需新的用户裁决(登记为下一批输入)。
⚠️ 同源文本另有两处、按「时态判据」不动的:docs/superpowers/plans/2026-09-11-frontend-redesign-batch1-deletions.md与docs/superpowers/plans/2026-09-13-frontend-redesign-batch8-groundwork.md各一处「读兜底与启动迁移仍在」⇒ 历史计划文本、一字不动。⚠️ 真实盲区(如实登记,不掩饰):启动期行为无单测(该判据在行为侧不可达)⇒ T25 的那条红点由静态判据承担;且 「仅有default槽的真机用户凭据会失效(需重填)」这一风险在本环境测不了(真机 / WebView2 冒烟由用户裁决跳过,U5)。⚠️ 引述来源:本节的两条事实(T25 的五条写集 / 三处文本定位)出处 =.superpowers/sdd/2026-09-13-frontend-redesign-batch8/controller-rulings.md的 §33.1 与 §33.4① —— 🔴 该目录整体 gitignored、不入库,故此处只给路径不给链接;提交 sha 与写集已由 T21 用git show --name-only -1 a054ec73独立复核。
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| 拆件行为不等价 | 拆 4 个超限文件时夹带功能改动 | 本批不加任何新功能;现有测试全绿 + 手工走查 |
| 删命令删到活代码 | [DEAD] 判定被测试文件污染 |
每条删除前重新确认调用方(一次 grep)—— 批 1 实测升级为三向复核(前端生产字面量 / 前端测试 / Rust 调用形态)+同名三域归属(命令 vs 同名活函数 vs 注释提及):22 条全部为空,OCR 引擎与导入转写链路的同名活函数一处未伤。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)⇒ 必须用引号定界字面量 / 整词边界,且任何「0 命中」结论都要点名仪器并先自检(计划 §收口三)。代价:本批因此额外删除 59 条测试(计划原预测 16 条),每一笔都由控制方逐条裁决 —— 见批 1 计划「收口回写」节 |
| 未确认档 3.22:1 被误用 | 有人把关键信息放进未确认档 | 4.3 三条规则写进规范 + review 检查 |
| 剪报底纹标错来源 | 历史数据缺来源标记时「猜」 | 4.4 防御性规则:无标记即无标记,绝不猜 |
| 视图层内存膨胀 | 每对象多视图全部常驻 | 7.3 惰性挂载契约 + 重挂载恢复 scrollTop |
| 编辑丢稿 | 切视图时 RichEditorView 卸载 |
flushSave 先行,失败则阻断并提示 |
| 包体继续膨胀 | 引入 GSAP 与新视图 | 批 2 先治理;GSAP 独立 chunk 懒加载。批 2 已落(2026-09-12):vendor-gsap 精确包名槽位(app/src/build/manualChunks.ts)+ 单测三条(含反例)+ 首屏预算守卫 scripts/check-bundle-budget.mjs(首屏 92.79 kB,exit 0)。.husky/pre-commit / CI(批 2 有意不接:它要跑一次真实构建并写 app/dist/,塞进共享的 pre-commit 会让并行期每次提交都依赖「此刻工作树可构建」)⇒ 接线归属批 8,且接线时必须一并修它两个已实测缺口(嵌套输出路径静默假绿 · 把「非首屏」说成「仅动态可达」的假文案)。批 6 接入 GSAP 必须用 import()。另注:本行是「批 2 先治理」的兑现 —— 但治理的是首屏,dist 总量只降 4,415 B,安装包体积由批 8 另裁。 |
| 动效过度导致不适 | 「充满动效」纲领被无限放大 | 三档强度 + 系统 reduced-motion 优先 + 环境层幅度上限 2% |
| 红线名存实亡 | E1/E2 两处例外被当成先例 | 例外须各自登记原因/影响面/回滚;新增例外需再次裁决 |
[需真机确认] 项 |
审计标注的运行态未知项(window.confirm 行为、录制中删会话、任务勾选是否 bump updated_at 等) |
相关批次开工前先真机验证 |
🔻 批 5 收口就地加注 · 本表三条风险的实际兑现度(2026-09-12,上表原文一字未改):
视图层内存膨胀(缓解写「7.3 惰性挂载契约 + 重挂载恢复 scrollTop」) —— 契约已落:默认视图常驻(resident-probe锚点,SessionViewHost.test.tsx5 处)、非默认视图模块级惰性 + 切走卸载(H2/F6 各 11/11,反向对照 T10-M2c/T14-M6 各自唯一红);重挂载恢复scrollTop的真实性不可验(jsdom 的scrollingElement不滚动 —— T17 已留probe-jsdom-scroll*.json证明探针本身有效)⇒ 只登记,批 8。惰性挂载的「运行时内存效果」亦不可测(字节面可测:懒 chunk 22 → 31 / 583.98 kB,内存面不可测)。编辑丢稿(缓解写「flushSave 先行,失败则阻断并提示」) —— 已落且有牙:F1(reject ⇒ 值未变 + 目标未挂载 +role="alert"+ 记忆未写)·F2(resolve ⇒ 切换发生)·F3(非编辑态直通)·F4(阻断全过程 0 个 toast 节点),四条it在NotesReadingColumn.views.test.tsx11/11 passed;反向对照 T14-M1(把catch改成继续)⇒ 唯一红 = F1。未消除的路径显式登记:RichEditorView内的 Ctrl+E / 完成按钮仍不阻断(今天就是 fire-and-forget,非本批引入的回归)⇒ 批 8。包体继续膨胀(缓解写「批 2 先治理;GSAP 独立 chunk 懒加载」) —— 批 5 实测:首屏 100.49 kB < 200 kB(余量 99.52 kB;Δ = +188 B gzip 相对批 4 收口基线);懒 chunk 31 个 · 583.98 kB gzip(不计入预算);三处可见/观感代价登记(拆件顺带迁移:字阶11 → 11.5·13 → 12·#9ca3af → ink-3· 圆角6 → 5落control档)—— 出处见docs/versions/v0.22.md批 5 节「诚实代价」。GSAP 本批仍未装(零新增依赖、manualChunks零改动、@keyframes零新增)⇒ 批 6 接入时必须用import(),判据见批 2 计划 Task 5。
本设计文档:docs/superpowers/specs/2026-09-11-frontend-redesign-design.md
同类需同步更新的文档
| 文档 | 动作 |
|---|---|
docs/product/ui-ux-system.md · docs/product/theme.md |
回写为目标态(C+D、四层动效、三档强度、断点与窗口)—— 属 AGENTS.md §10「额外审查文件」。批 0-D 已落:--ed-shadow-card → --ed-shadow-1/2 的命名关系与定值 · 「L1 原语层」章节(§十一:10 类原语清单/消费场景/禁止事项 · 交互态契约 · 动效接缝与 reduced-motion 承诺 · token 消费纪律与两条用色禁令) · 「剪报底纹上只用 ink-3 及更深」规则 · --due 第二次对比度修正。四层动效 / 三档强度 / 断点与窗口 / §五§十 的旧参数仍留批 8(T1 已登记:§十 tokens 代码块整体是旧版,与 ADR-032 不一致,未顺手重写) |
docs/adr/ADR-032..035 |
新建 4 条 —— ADR-032 ✅ · ADR-033 ✅(批 0-D)· ADR-034/035 顺延至批 3 / 批 6。docs/adr/ 实盘最高仍是 ADR-033,已当场列目录复核)。批 3 的壳层决策全部落在代码与守卫里(shell/ 四个纯数据模块 + TopBar/CommandPalette/ShellFallback + 三组守卫),A1–A7 七处控制方裁决散在批次台账(.superpowers/**,不入库)⇒ 这些决策今天没有 durable 的 ADR 载体。⇒ 建议归属:批 4 开工前补写 ADR-034(壳层:导航注册表 / 列契约 / 断点 / 窗口尺寸 / 溢出两级),或并入批 8 的治理收口;由控制方裁决,本行只登记不擅自补。 |
| ↳ 上格的就地加注(批 4 收口,2026-09-12;原文一字未改) | ✅ 批 4 已补写 docs/adr/ADR-034-l2-shell-navigation-and-column-contract.md —— 控制方 2026-09-12 14:20 裁决「批 4 一开工就先补写」,落在批 4 计划同一个提交 4905d4d8(docs(plan): 批 4 原语迁移实施计划(19 任务),2 路径 = 计划 + ADR-034);随后 783a62ae 按 T0 对码给它补 5 条加注 + 1 个新守卫对(shellReset.test.ts / columnKeys.freeze.test.ts)(+27/−0,正文一字未改),a25ed2c6 再补「⑥ 钉单源 + 回写 B15 授权」(+5/−4)。ADR-034 已进 docs/adr/README.md 索引(docs-check 的「索引覆盖完整 ✅」为此项)。⇒ 剩余:ADR-035 = L4 动效仍顺延(批 6);批 4 未新增任何 ADR。:115 两条(会话详情头改粘性 / 笔记工具栏三层合并)批 4 的 19 个任务无人承接 ⇒ 控制方裁决「由 T18 收口承接或按批次归属登记」⇒ T18 的处置:登记为批 5(视图层)follow-up(不是批 4 的交付),见批 4 计划 §收口回写 §七。 |
docs/adr/ADR-010-gap-filling-ai.md |
修订为退役 —— ✅ 批 1 已落(2026-09-11 裁决 / 2026-09-12 落地):状态转已废弃 + 文内「退役修订」节,索引与交叉引用同步(保留文件,不删) |
docs/standards/line-limit-exemptions.md |
纠偏 + 新拆文件登记 —— ✅ 批 1 收口态:--full exit 0,>600 0 · 301–600 档 123 · 登记条目 123;app_commands.rs 行的人工理由列已按实测更正为「312 条」。app/src/ui/primitives/** 42 个 ≤300 行文件)不在生成器视野内,本批已按 countLines() 逐值复核(42/42 一致),改它不会被门禁发现、也不会被门禁保护。批 2 收口(2026-09-12):app/src/App.tsx 439 → 519 行(Task 6/7/8 三次改同一文件),登记值已与实测同步 —— 收口时 node scripts/line-limits.mjs --write 无 diff(前序任务已刷新),故批 2 的收口提交不含本文件;app_commands.rs 行实测 478 与登记值逐字相等(批 1 的「503 → ~478」预算已在其计划「收口回写」节结清,无矛盾)。 |
docs/standards/ |
新增动效规范章节(现对动效零命中) |
docs/product/requirements-pool.md |
REQ-201 修正(update_fragment_group 实际无调用方)· 新增 REQ 登记 |
docs/versions/v0.21.md(或 v0.20.14) |
本系列交付记录 —— 实际落点:docs/versions/v0.22.md(版本归属理由见该文件 §版本归属说明);批 0-A / 0-B / 批 1 已落(批 1 = 「删除批」节,含交付/验收/规格漂移纠正/过程中纠正的计划错误/未做登记);批 2 ✅ 已落(2026-09-12) = 「批 2 · 包体治理」节(同七段结构 + 瓶颈清单指针)· 批 3 ✅ 已落(2026-09-12) = 「批 3 · 壳层落地」节(同七段结构;含 tauri.conf.json 的 §10 额外审查记录 —— T4 已执行,之前只留在 gitignored 的报告里,现已 durable) |
| ↳ 上格的就地加注(批 4 收口,2026-09-12;上格原文一字未改) | 批 4 ✅ 已落(2026-09-12) = 「批 4 · 原语迁移」节(同七段结构:交付 / 验收(两条 + 八门禁终态)/ 规格漂移纠正 / 过程中纠正的计划错误(①–⑲)/ 未做登记(逐条带归属批次)/ 诚实代价 / 提交清单 4905d4d8^..<收口提交> 含左端点 = 49 个提交)。该节自带的首屏账、五类中间态与「只有接缝、没有纲领」声明是本批最需要下游读到的三块。 |
| ↳ 上格的就地加注(批 5 收口,2026-09-12;上格原文一字未改) | 批 5 ✅ 已落(2026-09-12) = 「批 5 · 视图层样板」节(同七段结构:交付 / 验收(三条硬约束 + 八门禁终态)/ 规格漂移纠正 / 过程中纠正的计划错误 / 诚实代价 / 未做登记(逐条带归属批次)/ 提交清单 ad9d80d2^.. 至收口提交 含左端点 = 31 个提交)。该节自带的三块(三条硬约束的判据与变异体出处 · 首屏 100.49 kB + 懒 chunk 31 个的逐块台账 · B9 的「只有接缝、没有纲领」声明)是本批最需要下游读到的。ADR 面:批 5 未新增任何 ADR(docs/adr/ 实盘最高仍是 ADR-034)⇒ docs/adr/README.md 索引本批零改动;ADR-035 = L4 动效纲领与引擎仍顺延批 6;批 5 的 ADR 动作只有就地加注(ADR-033 §1/§4/§登记 三段 + ADR-034 §登记 一段,只加注、不改结论)。 |
🔻 批 6 收口就地加注 · 本表四行的落地(R6.7 · R6.9 · R14.7;2026-09-13,上表原文与批 4 / 批 5 加注一字未改):
- 🔴
:836的「docs/standards/新增动效规范章节(现对动效零命中)」= 批 6 已做(批次归属的就地消歧):落点 =docs/standards/motion.md(批 6 T1,提交bffed928;已进docs/standards/README.md索引)。⚠️ 同一件事在本行与v0.22.md:35的「批 8 治理收口」行两说(:35逐字写「新增动效规范章节」属批 8)⇒ 两处按本加注读:规范章节本身已在批 6 落地;留批 8 的是docs/product/ui-ux-system.md/theme.md的四层动效 / 三档强度回写(批 6 未写它们,progress.md§一 的「🟡 待裁」仍在)。docs/adr/ADR-032..035行:ADR-035 ✅ 已写(批 6 T2,提交97295d64;文件docs/adr/ADR-035-l4-motion-grammar-and-engine.md,含**「后端契约例外」节并在批 6 收口由 T35 定稿回填)⇒ 本行「ADR-034/035 顺延至批 3 / 批 6」两件均已兑现(ADR-034 批 4 补写 + ADR-035 批 6 落地)。docs/adr/README.md索引本批 +1 行**(T2)并在 T35 更正状态列措辞。docs/adr/ADR-010-gap-filling-ai.md行:批 1 已落(退役修订),批 6 零动作。docs/versions/v0.21.md(或 v0.20.14)行:批 6 ✅ 已落(2026-09-13) = 「批 6 · 动效系统」节(同七段结构:交付 / 验收(八门禁终态 + 验收面逐条兑现度)/ 规格漂移纠正 / 过程中纠正的计划错误 / 诚实代价 / 未做登记(逐条带归属批次)/ 提交清单ac504b06^..975b3285含左端点 = 77 个提交)。docs/adr/ADR-019缺号:🔴 不补、不复用,只登记(docs/adr/README.md的「编号规则」逐字「编号一经分配不再复用」);批 6 实盘最高 ADR = ADR-035。⚠️ docs/product/ui-ux-system.md/theme.md的四层动效 / 三档强度:本任务不写(§14 上格逐字仍留批 8)⇒ 只在v0.22批 6 节的「未做登记」里点名。
🔻 批 8 终态就地加注 · 本表各行在批 8 的落地(2026-09-13 · T21;上表原文与批 4 / 批 5 / 批 6 加注一字未改):
- 🔴
docs/versions/v0.21.md(或 v0.20.14)行:批 8 ✅ 已落(2026-09-13) = 「批 8 · 治理收口与三条主线」节(同七段结构:交付 / 验收(三条主线兑现度 + 八闸终态)/ 规格漂移纠正 / 过程中纠正的计划错误(E8-1 … E8-25)/ 诚实代价 / 未做登记(逐条带归属批次)/ 提交清单5852cdc4^..396b5e5c含左端点 = 63 个提交)。🔴 该节自带的三块(懒侧基线的两个时点与「重冻后总量 == 实测 ⇒ 零余量」的结构性发现 · 八闸第 ⑤ 闸的懒侧写⏭ 未判· T15 / T15b 的两条实测边界)是本批最需要下游读到的。- 🔴
docs/standards/行(「新增动效规范章节(现对动效零命中)」):批 6 已落(docs/standards/motion.md)⇒ 🔴 批 8 未新增任何docs/standards/章节;批 8 在该目录的动作只有就地加注与数值同步(line-limit-exemptions.md的行数值与「312 条」散文 ·performance.md的「懒侧执行者缺口三段式」加注 ·motion.md的判据纪律小段 ·testing.md的门禁稳定性纪律)。- 🔴
docs/product/ui-ux-system.md/theme.md行:批 0-D 已落原语层与阴影命名;🔴 「四层动效 / 三档强度 / 断点与窗口 / §五§十 的旧参数」批 8 仍未写 ⇒ 登记为下一批输入(批 8 只回写了「审校模式」那一节)。docs/adr/ADR-032..035行:批 8 未新增任何 ADR(实盘最高仍是 ADR-035);批 8 的 ADR 动作 = 两处前向指针加注(ADR-034/ADR-035各纯插入 1 行、删除列 0,指令落5018c7ab)。docs/adr/ADR-010-gap-filling-ai.md行:批 1 已落(退役修订),批 8 零动作。docs/standards/line-limit-exemptions.md行:批 8 的终态 =node scripts/line-limits.mjs --fullexit 0「>600硬限 0(棘轮内)· 301–600 档 121 · 登记条目 121」(T21 亲测,时点 2026-09-13T17:32+08:00)。⚠️ docs/product/requirements-pool.md行(「REQ-201 修正(update_fragment_group实际无调用方)· 新增 REQ 登记」):🔴 批 8 未动它(update_fragment_group的接线由批 7 的 T23 补齐)⇒ 登记。- 🔴 本表未列、批 8 新增的一行(归档面):
docs/tech-debt/按用户裁决 U3 = a 归档到docs/archive/2026-09-13/(335a6155·630d2bfa)⇒docs-check的扫描 / 检查数由282 / 182变为284 / 181(282→284/182→181,已逐字登记在docs/archive/2026-09-13/README.md与docs/archive/README.md;T21 亲测现读数 =284 / 181)。
提交策略:批 0 拆成 13 个原子提交(3 条 ADR → 豁免表纠偏 → 拆 NotesPage/NoteListView → 拆 SessionDetailPanel → 拆 ClassroomPage → token 层 + z-index → 图标集 → 原语第一批 → 第二批 → 第三批 → 回写规格文档);后续每批各自原子提交,遵循 Conventional Commits。
- 缺的不是「更好的组件」,是缺失的两层 —— 原语层与视图层。131 个现存组件里 0 个死组件,职责基本清晰。
- 「一个对象只有一种样子」是最大的产品税 —— 9 个域里 8 个如此,而体系域用它自己证明了多视图的价值。
- 动效不是装饰,是状态的直接可视化 —— 四档墨度显示「机器有多确定」,剪报底纹显示「这句从哪来」,刻度生长显示「记忆有多牢」。这三样别的笔记软件都没有。