# 品味账本(taste-ledger.md)— 白纸壳视觉决定累积记录 > 规则(paper-shell V4 防发散协议第 3 条):每个视觉决定一行——维度 / 上下文 / 选 / 弃 / 一句话为什么。 > 已判死的决定不复活;翻案需显式理由并注明日期。新 agent 会话开工前**先读本文件**。 > 本文件是「打磨知识」的持久化——观测台当年磨了很多轮的成果,从此不再随会话蒸发。 ## 来源合并(V2 时完成正式合并,此处先记已实证的事实) 三处已付费的品味资产,DNA 连续(2026-08-20 实证): | 事实 | 观测台(tokens.css) | 白纸原型(paper-prototype*.html) | 墨黄铜(ink-brass-*) | |---|---|---|---| | 黄铜 accent | `--obs-brass-hi: #e8c887` / `--obs-brass: #c9a25c` | `--brass-hi: #c9a25c`(**与 obs-brass 完全同值**) | chronoBrass 渐变同族 | | 动效曲线 | snap `0.12s` / glide `0.3s`,cubic-bezier(0.23,1,0.32,1) | snap `0.14s` / glide `0.32s`,**同 bezier** | 同族 | | 衬线字体 | Fraunces Variable + Noto Serif SC | Fraunces + Noto Serif SC(同款) | 同族 | | 语义色 | pass/warn/fail 三值 | pass/fail 同族 | — | **合并结论(2026-08-20 R1 D-R1-5 升格为已定)**:白纸/深色 = 同一前端的两主题(昼夜两态)。黄铜 accent = 跨主题恒定的仪器 DNA;动效曲线 = 品牌级运动语言;Fraunces = 标题衬线定字体。墨黄铜(ink-brass)= 材质词汇表(跨主题取用的质感元素),非第三竞争方向。V2 契约须交付主题机制(token 双套 / 运行时切换 / 降级规则)。 ## 决定记录(格式:日期 · 维度 · 上下文 · 选 X 弃 Y · 因为…) - 2026-08-21 · 主题双套机制 · V1 首轮 A|B 并排 · 选 dark 立得住、paper 没质感;弃"两态天然都成立" · 同一 DOM 双 token 机制本身无恙——崩的是 paper 态的材质,不推翻 D-R1-5 主题化,只把 paper 态的质感列为待解问题 - 2026-08-21 · 纸材质 · V1 第二轮 C1|C2|C3(plain|cream|parchment) · 弃 C1 冷白("没质感"原话);C2/C3 未获拍板 · 调色方向(暖、羊皮纸系)比冷白好,但仅调色+CSS 噪点不够"纸" - 2026-08-21 · 纸材质·贴图密度 · V1 第二轮 D1|D2(程序化生成贴图±光纪律) · **弃 D 组**("效果不好,质感看起来很别扭"原话) · **素材瓶颈假说被证伪**:贴图密度不是"没质感"的主因——生成贴图叠加后反而更别扭。买美术素材的钱省了;质感问题另寻根源(候选:纸感≠纹理叠加,或需真照片素材,或问题根本不在材质而在排印/构图——见待办) - **范围收窄(2026-08-22 R3-M 翻案注记,非翻案)**:上条证伪的实为「程序噪声平叠」——D 组贴图是算法噪声,既无真纤维结构也无光响应。后续轮次相继测了「真照片平叠」(R3-P)与「PBR 光照材质」(R3-M),原结论保留但范围收窄为「程序化贴图密度不是瓶颈」;「素材要不要买」的判定移至 R3-M 人判(判定分支见评审壳) - 2026-08-21 · 工作面 vs 静物 · 诊断推论 · 记:ink-brass 静物是"烛光下的舞台构图",不能当工作面目标追 · 工作面要长时间盯、内容铺满视口,与静物画的戏剧性光影天然冲突;拿静物当基准会导致永远"差点意思"(此为 C/D 两轮的共同教训) - 2026-08-21 · 块粒度 · 走查弹涌现(用户:「长文字回复整块拖出没必要,只想截取一段」) · 选混合方案、重心选区拖出(块级默认 + 选中一段拖离流 = 抽纸条,拷贝语义);弃段落级预拆 · 粒度交给用户按需取,流视觉密度不涨、块 id 续命机制不伤;纸条隐喻与 D-R2-3「塞纸条」同构。活引用仅块级保留,选区块是纸条本体(用户拍板:直觉与 agent 一致,并排原型取消) - 2026-08-22 · paper 态路线 · V2 开工前岔路(下方待办二选一)· 选 V1 第三轮再攻质感;弃「从简直进契约」、弃「dark 全量 + paper 挂实验态」 · 用户拍板:白纸愿景不搁置——质感问题换思路(非贴图密度路线)再做一轮人判,之后才录 V2 契约 - 2026-08-22 · P 片素材 · V1-R3 备材(cc0 ambientCG 五张扫描纸数据侧写)· 选 Paper001(近白细颗粒,multiply 0.5)/ Paper002(灰暖重颗粒,multiply 0.45 + brightness 1.12 提亮);弃 Paper003(云斑无细纹)/ Paper004(牛皮纸色偏离 cream 家族)/ Paper005(平滑无纹理)· 细/重两档铺强度曲线;选纸依据是均值/暖度/纹理能量统计(模型无图片输入,数据侧写代行) - 2026-08-22 · 组合探针 · V1-R3 人判中途用户点单「排印加重颗粒出一版」· 出 T+P2 组合片(`material=r3tp2`:T 排印层级 + 纸中纸实心对比 + P2 重颗粒扫描贴图),四断言自检过(folio 结构来自 T、颗粒来自 P2、两半同时生效)· 未拍板——观察组合是「排印给骨材质给肉」还是「颗粒淹没字清晰度」;若组合赢单变量,V2 契约按排印刻度+材质管线双节立 - 2026-08-22 · 光照材质刺 · V1-R3-M(用户反馈「总觉得不对劲」+自认两病灶:表面不像/场景太干净)· 出 M1/M2 两片(`material=r3m1/r3m2`:cc0 PBR 组 Color×NormalGL×Roughness 左上光源逐像素烘焙,整纸单铺 2400px 零重复)· 未拍板待人判。**过程中的三个技术实锤**:① 此前所有「真照片材质」(P 组)只用了 Color 平叠——Normal/Roughness 从未开箱,「光响应」整轮空白,第二轮证伪结论据此收窄;② 烘焙接缝检验证实 cc0 两套扫描都非无缝贴图(color 缘差 2.5-4.7,Paper001 normal 达 10.9)——P 组 640px 平铺一直带接缝线,整纸单铺是唯一无接缝路径;③ M2 纵横纹理能量各向异性(1.67 vs 0.99,造纸机纤维方向)是平叠照片给不了的真纸特征。判定分支:M 赢→材质管线按 PBR 烘焙立项、美术资源按 Normal+Roughness+Color 三件套规格采购;M 输→表面非瓶颈,美术资源只在需要「艺术不均匀」(deckle 毛边/艺术级扫描)时按张买 - 2026-08-22 · **R3 人判:全弃** · 全变体评审(基座/T/P1/M1/M2/P2/T+P2/L)· **全弃**(「怎么都不行,很劣质,很粗糙」「你要问我好不好,我觉得都不怎么好」原话;用户进入视觉疲劳态:「做来做去搞的我不知道怎么弄了」)· 三假说无一胜出——走评审壳预设分支「全错→回账本重新立案」;**止损条款首次实际触发:禁生成第十一张变体**,下一动作只许诊断性(参照物/判断条件),不许生成性 - 2026-08-22 · 质感病理推论 · R2-D / R3-P / R3-M 三轮负结果合并分析 · 记:三批材质尝试的死亡语言一致(「别扭」「劣质」「粗糙」——全是缺陷词汇,无一是材质词汇)· 假说:屏幕是发光体,细粒度非均匀在其上被知觉读为噪点/脏污/压缩伪影而非纸材质(纸的质感前提是反射光,屏幕不满足此前提;唯一立得住的 dark 恰是近零细纹理);CSS 渐变+扫描贴图的半吊子模拟落在恐怖谷——不够抽象不够真;且三轮都在原型工艺地板上(620px iframe、假内容、玩具块)判断天花板选择 · 两解指向同一动作:先补参照物(什么样的纸感算好),再谈动手 - 2026-08-22 · 立案重诊路线 · 止损后岔路(参照物板 / 抽象化转向 / paper 搁置)· 选**参照物板 + 全屏重判**;弃直接转向、弃搁置 · 用户拍板:先把「不对劲」翻译成差分信号再定方向——产出 `prototype/reference-board.html`(七张市面纸感产品实拍 + 我们三张同尺寸对照),人判任务=只指出哪几张感觉对 - 2026-08-22 · **参照物判定:R1×R5(质感根源定案)** · 参照物板人判 · 选 **R1 iA Writer × R5 Craft 的结合**· 这是对 R3 重开之问(「质感根源是什么」)的最终回答:**质感 = 排印纪律 × 编辑器工艺密度,与材质无关**——iA 面是零纹理暖平底 + 排印即英雄;Craft 面是卡片工艺(一致圆角/克制海拔/呼吸留白)+ 舒适密度。连带推论:① 材质模拟路线(D/P/M 三轮)正式出局,与三轮负结果互为因果印证;② 我们原型的真病灶除材质外还有「空」(2400px 大纸+一个小 folio=mockup 感,两个参照物都是内容满版);③ T 方向当初的弱阳性是对的,缺的是 Craft 式工艺与密度 - 2026-08-22 · R4 验证片开轮 · 止损条款的适用边界澄清 · 出 `material=r4`(排印×工艺假说验证片)· 性质判定:这不是止损所禁的「第十一张随机变体」——搜索空间已被参照物钉死,此片是**按差分信号施工**:六维提取(零纹理平色 / 排印层级 / 卡片工艺 / 密度满版 / 克制海拔 / 文本区隐形),每维可单独对账 - 2026-08-22 · **材质暂定 R4 + 风格源切换:印刷品方向** · 用户出示外部风格源 `D:/paper-viz/direction-b-print.html`(「方向乙·印刷品 — paper 视觉原型 v3」,来路系用户侧另一探索线)· 选:材质维持 R4 零纹理决定;风格全面转向该文件的**排印宪章 v3**——字号三档锁死(正文 15/注释 12.5/注记 10)、垂直基数 28px(块距 ×2、注记距 ×½、行高 28)、行长 540px≈36 字、无动效纯排印 · 该文件的三个关键洞察:① 块类型映射到**印刷品文类**——问(手写批注)/思(校对批语)/器(脚注)/答(正文)/钉住(盖章剪报),隐喻靠排版惯例承载而非材质仿真;② **书眉+页边注**结构(kind 标签挂左页边,hairline 连线);③ 全幅页面——「一张纸=整个窗口」首次字面成立,深色桌面退场。硬偏移阴影(2px 3px 0)替代软模糊阴影,letterpress 语汇 - 2026-08-22 · 资产策略定案 · 用户问「需不需要成套 UI/图标资产」· 选:**不做成套资产,做三件转录备料**;弃图标库采购、弃预制 UI kit · 理由:印刷品方向的资产成本优势是结构性的——文类签用汉字、状态用注记、按钮用文字,手绘 SVG 需求 ≈0(盘点见 `prototype/glyph-inventory.html`),任何 pictogram 都会打破纯排印场。三件套产出:宪章 token 表 `prototype/print-charter.tokens.css`(V2 契约核心章节前身)+ 字形盘点页 + 表面清单 `v2-surface-inventory.md`(✅7 🔶3 ⬜6,V2 必补 4)。风格源两件已拷入 `prototype/style-source-*` 存档防丢 - 2026-08-22 · **R5 人判:方向通过(V1 视觉史首个正判定)** · 全屏实看 · 「骨架基本上还可以,但是很多地方还缺细打磨」· 三假说全灭后经参照物板收敛的印刷品方向存活——验证了止损→立案重诊→参照物板这条路的必要性 · 进入打磨阶段,两段式:**A 段=转录缺口补全**(对照风格源的保真项,无需人判直接补);**B 段=V4 式单维循环**(真审美开放项,一环一维 A|B 对照,每维 ≤3 环)。待办清单立 `r5-polish-backlog.md` - 2026-08-22 · 精细设计之问 · 用户二次反馈「说不上哪里不对但整体粗糙,没有经过精细设计」+ 追问「排印/UI/字体是否都还需细化设计」· 诊断:粗糙感三源=①工程机器外露(调试读数挂书眉)②首屏锚定错误(首块内容在 ~500px 处,半屏空白)③微工艺与内容缺位(思块未移植/占位文案/微排印缺失)——三源全是转录与严谨问题,零审美发明 · 方法论转向:**黄金样本对齐**——不发明精细,向已认可的 direction-b 渐近收敛;A8-A12 五项当日清账 · **结构性瓶颈点名**:本会话模型无图片输入,agent 看不见自己的产出,眼判类细化只能靠用户眼睛逐轮喂——最便宜的解锁是 vision 会话做自检循环;发明类(未覆盖面)按宪法仍归人仲裁 - 2026-08-22 · **用户疲劳态,项目转自主段** · 用户:「我觉得好累啊」· 按宪法「推进节奏由用户对话带宽决定」:所有人判项挂起,agent 不催促;后续会话注意——**不要向用户批量索要判断**,能自主推进的只有:转录类打磨(建议开 vision 会话对着 direction-b 自检)、文档备料、B 段队列准备 · 用户回来后一句「继续」即可恢复,状态全在账本与 backlog 里 - 2026-08-22 · **最终稿拆出** · 用户:「给我拆出来,不然现在一整个乱七八糟」· 从 multi-material 的 `paper-v1-r3.html` 拆出**单档成品 `prototype/paper-r5-final.html`**:r5-only、无材质切换/无调试读数/无 M·T·G 键、书眉只有印刷品 folio 行、单文件独立。自此 r5 审阅一律看 final,paper-v1-r3 只留作诊断档案不再当成品看。截图 `preview/paper-r5-final.png` - 2026-08-22 · **风格源定稿:兰台注疏(handoff 全量落地)** · 用户经 Open Design 设计线交付定稿包(高保真原型 holo-paper.html → `prototype/lantai.html` + 规格书 `docs/design/lantai-design-spec.md`(锁:注疏范式/字体栈/墨色语义/块映射/术语/印章界栏亭台图标)+ token 表)· 选:注疏方向为产品落地契约——宋体正文(Noto Serif SC+EB Garamond Variable)、楷书手迹(Ma Shan Zheng,**只给来文**)、等宽机读(IBM Plex Mono);矿物墨色铁律(朱砂=人/石青=机/石墨=草稿/墨=正文);七类块映射(user→来文/markdown→正文/reasoning→夹注/diff→抄录/tool→脚注/plan→拟策/notice→贴黄);术语(会话→案卷、发送→拟文);弃 Fraunces/LXGW WenKai/JetBrains Mono 观测台字体族 · direction-b 排印宪章的文类洞察全部保留并扩展成完整注疏系统——这是印刷品方向的**进化完成态而非翻案**;材质 R4 零纹理不变。产品落地:tokens.css 换装(--obs-* 过渡别名层,1338 处引用零断链)+ PaperPanel 七类块注疏化转录(文类签页边注+卷次序号)+ paper/measure 与 ui/pretext-cache 测量栈同步换装 + 案卷首页换皮(蘭臺印章品牌)+ favicon 亭台图标 - 2026-08-22 · token 落地策略 · handoff 字面「覆盖 tokens.css」与代码现状冲突(--obs-* 全 UI 1338 处引用,字面覆盖=全部旧 UI 断色断字)· 选 spec §8 自己留的「并行过渡」分支:兰台 token 为唯一真源 + --obs-* 过渡别名层按迁移对照表映射色彩/字体;结构变量(bar-h/status-h/rail-w/snap/glide)暂保旧值 · 逐文件迁移完成后别名层整体退役;canvas 测量栈必须镜像渲染字体(measure/pretext-cache 两处同步是硬纪律) - 2026-08-22 · **V5 提前拍板:摘除旧观测台前端(显式翻案,最高优先级)** · 用户深夜原话「这个狗日的旧前端就不能摘了吗,就非得挂在这」· 选:**提前执行 V5——纸壳(注疏案卷工作台)成为唯一主界面,旧观测台前端整体拆除**;弃「纸能住人 + R3 访谈后再定」的共居期排序 · 这是对共居期排序的**显式翻案**(原排序:R5 打磨环 → 纸能住人 → R3 访谈 → V5 判断半;新排序:V5 拆除并入当下主线,R3 共居判据随之作废)。当日背景:兰台注疏定稿已全量落地 main(7 commit 门禁全绿),「纸面板即聊天」已成立(composer 接 core.sendMessage,消息流经 translate.ts 转译为块)——拆除的可用性前提与审美前提同日齐备,用户据此不再愿意为旧前端续命。拆除范围与顺序见 plans/README 总控表 2026-08-22(深夜)条目;「关纸面板回哪」按原型 home 全量转录重设计(现状半档重排欠账一并清) - 2026-08-22 · **V5 拆除施工毕(commit a621b1e6,-16843 行,四件套门禁全绿)** · 拆除面:App 树 chrome(CommandBar/DockRail/StatusBar/TimelineHUD/ShortcutsOverlay/BackgroundActivity)+ ChatBeacon 聊天视图族 + 图谱 dock 面板族 + 壳行 12→9(graph/nav/dataflow-parser 退役)+ workspace.ts 渲染面(starGraph 恒 null,**数据面保留**——graphData 分页装载/graph-updated/runCheck 简报注入照旧服务 Agent 工具)+ shell-store.view 退役 + index.html 星图画布/氛围层(three.js 出 bundle)+ paper preset 行 · **四个关键承接决定**:① PromptShelf 独立挂载(PromptShelfHost)——权限卡/ask_user 是会话编排域刚需而非观测台装饰,无承接 = Agent 写操作被静默否决(违「错误不静默」宪法);② 窗口控制自 CommandBar 抽出(WinControls)迁纸壳书眉+首页顶栏——decorations:false 必须有标题栏承接;③ 「关卷」回案卷首页(SessionsHome 常驻基底层)——「关纸回哪」的答案,首页按原型全量转录进 R5 队列;④ scene/ 与 ui/ 大部保留为**休眠层**(chat-stream 冻结 import 走 ui/graph shim;星图/文件查看器的彻底删除是独立 sweep——一次动冻结文件依赖图风险不成比例)· 交互欠账如实入 r5-polish-backlog C 段(C8+:多卷切换/权限卡纸面化/附件入口/模型与权限模式切换入口/状态反馈面) - 2026-08-22 · **vision 自检管线验证可用** · 自主段 C2 设置面板重排自检 · 出 headless Edge 截图 + harness 对拍管线(`prototype/c2-settings-harness.html` 留作回归工具,三轮收敛)· 此前账本记录的「结构性瓶颈:agent 无图片输入」已解除——多模态会话可自行眼判转录保真度;注意:harness 截图字体走系统回退(fontsource 不加载),判断字形需真机截图;B 段审美循环的「vision 会话 + 用户终审」前置不变 - 2026-08-22 · **C7 朱砂圈用户验证通过(当日第二轮真机实测)** · 用户填 key 实发来文,【词】书写语法 + 渲染层解析的零数据契约方案真机过人判——圈点视觉、不拆行、AI 回文【】不受影响全部符合预期 · 附带:同轮会话里 rpc Value 化第二步(出口分派表)也过真用户全工具链验证,回卷链零症状 · C 段 C1-C7 至此全绿,剩余为 C8+ 交互欠账(等产品拍板)与 B 段审美循环(vision + 用户终审) - 2026-08-22 · **C9+C11 联动落地:牒卡 + 单源模式入口** · 用户实测后拍板「暗卡确实不行、权限卡得从下方递出」(位置现状已对,病灶在皮)+ 指出旧模型/模式入口逻辑「明知有问题当时没管,不宜复用」→ 尸检旧链路发现三处实病:切换不镜像 Rust(后台任务半切)/双源单向陷阱(手动切换不落盘,重启回默认)/per-panel 作用域与全局 Rust 镜像错位 · 选:mode-store 单源真相(app 级单例,切换=写 store+镜像 Rust+落盘三件事一体)+ 书眉 ModeIndicator(模型菜单+模式轮转+yolo 落印确认)+ 牒卡换皮(请示/问询双 tag,落印=纸面唯一实色按钮);弃:复用旧 ModelSwitcher/per-panel 模式字段 · 术语定案:常询/半放/全放、请示·PERMIT/问询·ASK、落印准此/本卷均准/驳回 · 真机 CDP 闭环验证含重启水合(auto 落盘→重启直接半放实锤)· 经验:debug exe 的 custom protocol 资源是编译期嵌入——裸跑 target/debug/lantai.exe 不读磁盘 dist,前端变更后必须 cargo build 重编 exe(tauri.localhost 不接 1420 devUrl,此前误诊两轮) - 2026-08-22 · **B 段解锁:vision 前置改直审循环(用户无多模态模型)** · 用户拍板「vision 预筛死了,终审从来就是我的」· 循环改型:agent 干粗活(token/计算样式对拍修偏)+ 用户每环拍 A/B(上限 15 决定,异步可拖)+ 定稿数值钉断言测试 · 首环 B1 垂直节奏当日开:数值账摸出(块距 48 vs 实现旧行 18、asterism 整体缺失、段距 10 缺失)、A/B 对照图出图(prototype/b1-rhythm-ab.html + 截图)、用户拍板三件套全收 + **来文间距反转**(尾距收 8、头顶放宽 72——用户轮次从头顶切分,理由「分得开用户消息和之前的 LLM 消息」;这是超出原型的用户发明,原型 78 全给尾距被否) - 2026-08-22 · **C10 拾遗落地:附件链四病灶根治** · 用户预警「C10 工程量最小但是之前有 bug 的功能」→ 尸检实揍四病灶:拖放 HTML5 drop 在 T2 WebView 从未触发(原生接管,API 方向选错)/浏览器回退 f.name 冒充 path(空头支票)/size 恒 0/📎行拼楷书正文 · 选:夹按钮(拾遗)+ Tauri dialog 真路径 + translate 结构化 + 石青 mono 附件行;弃:接旧拖放(接了也是假功能,要真做须 Tauri onDragDropEvent 原生通道另立) · 经验:无 key 验证机发不出真消息(keyguard 冷启动防护正确拦下),端到端发送链验证待用户机器;vitest include 补 tsx 后缀(首个 tsx 测试落地) - 2026-08-22 · **C12 状态字落地:pushStatus 承接面接回** · 用户判「应该没啥大问题」→ 实测确实最顺:承接面(shell-store statusText/statusLog)与样式语言(书眉 HUD mono 小字)都是现成的,纯接线 · StatusLine:statusText 常显 + analyzing 石青呼吸徽标优先 + 点击展开日志环;真机 CDP 验到 cold-start 推的「已恢复上次案卷」直显(真实链路端到端) · **C 段至此 C1-C12 全绿,仅余 C8(多卷切换)单独立项 + C14(dock-store 收缩)挂其后** - 2026-08-23 · **B2 页边注光学 环1:授权 agent 定(视觉差异不显著)→ 维持顶挂收维** · vision 会话首轮单维循环:数值账(签基线 vs 首行基线落差 来文+9.6/正文+5.8/夹注−0.3/脚注+6.0/抄录+27.8/拟策+28.0)+ 三列对照页 `prototype/b2-margin-optics-ab.html`(A 顶挂现状 / B 全量基线对齐 / C 分组:散文对齐·框架顶挂)· 用户文字判:「横向对比下来看着区别其实不大,你来定就好」→ agent 定 **A 维持顶挂**(top:2/tick:10 原型转录值,零改动收维;理由:差异不显著时守原型最小改动,基线对齐方案判死不入册) · 工具链留档:`D:\tmp\r5-vision\measure-b2.mjs`(黄金样本逐块基线测量)+ `shot-b2.mjs`(对照页截图)· B 段循环模式实证:vision 自检(agent 截图自判增补候选)+ 用户终审拍板的组合成立 - 2026-08-23 · **B3 墨阶配比 环1:拍板 B 提墨(落地)** · 数值账:黄金样本 ink-3×21/ink-2×15/ink-4×6,产品全界面 ink-3×77 分布 9 个 CSS · 对照法:B 变体=黄金样本直拷 + 覆盖层(`prototype/b3-ink-b.html`),「信息承载文本 ink-3→ink-2」一刀切 · **用户文字拍板 B**:信息承载处提墨,饰件(HUD/卷次序号/眉批/placeholder)留 ink-3 · 落地五处:`.pp-block.pp-tool .pp-out` / `.pp-block.pp-code .pp-out` / `.sh-session-row .date` / `.sh-session-row .meta` / `.sh-foot`(folio-sub 原型专属,产品无对应面) · 钉值 tests/paper-visual-decisions.test.ts · 方法注记:变体直拷黄金样本+尾部覆盖层(cascade 后置)比手工 harness 更保真 - 2026-08-23 · **B4 问批音量 环1:拍板 C 折中(落地)** · 前置发现:规格书块映射表锁来文身 `--seal-deep`,但黄金样本 lantai.html 实演是 ink-1(computed rgb(38,34,28) 实锤)——规格书与原型在此处分叉,产品跟随的是规格书 · 三变体对照(截图 `D:\tmp\r5-vision\shots\b4-{a,b,c}.png`):A=规格书现状(朱砂深 18 楷书)/ B=原型实演(墨身,朱砂只留签+批线+圈点)/ C=折中(朱砂深 16px)· **用户文字拍板 C**:来文身 seal-deep 保持(问仍是唯一彩色声音),字号 18→16 收到正文 17 之下 · 落地:PaperPanel.css `.pp-user .pp-body` 16px/1.9 + measure.ts PAPER_USER_FONT/LINE_HEIGHT 镜像 + 规格书 §2/§4 同步 · 钉值 paper-v3a(measure 常量)+ paper-visual-decisions(CSS 字面量) · 含义:黄金样本 lantai.html 的来文身 ink-1 判定为**原型自身偏离规格书**(非产品转录错),原型此点不再当判据 - 2026-08-23 · **B5 代码块印刷化 环2:拍板红绿墨色化(落地)** · 环1 三变体(A 石青/石墨矿物现状 / B 全墨 / C 单墨 ink-2)用户文字判:「颜色不太符合代码块的视觉直觉,直觉上还是红-绿+比较正常,当然颜色选型不要完全用纯红纯绿,不然又丢失墨色的感觉」· 环2 出 D 变体(`prototype/b5-d-cinnabar-jade.html` + 截图 `D:\tmp\r5-vision\shots\b5-d.png`):add 松绿(--pass #5E7A55 矿物绿)/ del 朱砂深(--seal-deep #8C2F26)+删除线 · **用户拍板 D** · 落地:PaperPanel.css .pp-add/.pp-del + renderer-service diffLineClass 注释 + 规格书 §3 铁律补唯一豁免注记(diff 加删走红绿墨色化,del 朱砂深读作擦改/勘误红笔非人语)+ §4 块映射表同步 · 钉值 paper-visual-decisions · **语义注**:pass 绿在工具行完成态同用,diff 新增复用同绿在版内出现两次绿色——用户认可此共用 - 2026-08-30 · **P1-P4 UI 四批精修(自主段,计划批准后施工)** · 用户判「纯纯一坨屎」→ 真实痛点是**细节粗糙非新鲜感**(重灾区=侧边栏/聊天纸面/创作坞/设置面板,糙的类型=排印细节/色彩质感/手感反馈/字体渲染)· P1 收编字号(4 处半像素档 9.5/10.5→10px 归并;**版式钉值 16/17/13.5 等测量镜像一律不动**,动则炸测试)/ P2 提色提主次(输入件聚焦 1px 弱线→2px 朱砂 + 底纸区分、选中态实色条/底线、hover 淡底 7→12%、消息操作条 hover 实底)/ P3 手感(6 按钮 `:active` translateY(1px)+深墨沉感、3 处行/卡 hover 微浮;**纸面块 .pp-block 不加位移**——内容非控件,动则与测量/拖拽打架)/ P4 字体渲染(**先犯后纠**:5 处纯中文操作钮误 mono 化→自检发现 mono 栈无中文字形、会回退系统字体更糊→全撤销;只保留 caret mono + 思考档描述 10→11px 上提)· 门禁 build/vitest(1994 passed)/biome(0/0) 全绿零回归 · **教训记档**:小字中文操作钮禁 mono 化——`--f-mono` 栈(IBM Plex Mono/Cascadia/Consolas)无中文字形,P4 自检逮到的坑,后人勿重踩 - 2026-08-30 · **纸面最后一公里批(自主段,交接窗口四件,commit 2584eedb)** · 用户「多次对照原型后依然毛坯粗糙、被折磨受不了」→ 重入 git 发现 markdown 专项(真渲染+折叠+间距根因)已由并行窗口收口,本批只做剩余面 · 选:**界栏**(流区左右 1px 墨系栏线、活跃卷提浓+朱砂洗底——规格书 §1 锁定件首次落地;栏线不沾朱砂,栏线是版式结构件非人的批注)/ **流式生命感**(块首见 pp-enter 入场、运行中末块**石青**尾笔、浮层全族 pop/veil 递出动效)/ **空态卷首化**(纯排印构图:机读 kicker+宋体题字+注线+花押)/ **卷首编排**(钤印空中按下落定 + staggered reveal + 工作区卡朱批左条)/ P1-P4 政策补漏(provider-settings 瞎眼档上提 + 三处纯中文 mono 纠正 + 五钮 :active)· 弃:**vignette/纸张材质强化**(R4 零纹理定案不变——质感=排印纪律非纹理叠加)、**朱砂尾笔**(自查推翻:运行态语义族恒石青,铁律优先于「笔是朱批」的拟物直觉——拟物逻辑会让「机器写的正文」误披人的声音)· 钉值 paper-visual-decisions 补三条(界栏墨系/尾笔石青+绝对定位/入场单次);门禁 tsc/biome/vitest 2039/build 全绿 - 2026-08-30 · **书眉降噪 + 导航件接回批(同窗续批,commit 90b3b1cf)** · 六件提案用户拍板「昼夜两态搁置,其余做完」· 选:书眉 pp-zoom 只留缩放读数(块/钉/纸条计数入 hover title——「工程机器外露」粗糙源收尾)/ 小地图点击跳转(V3b 欠账,glideViewTo 复用 focusRafRef 与 flyToPoint 互斥)/ 键盘走卷 Alt+↑↓ 块间 Alt+←→ 卷间 / 空卷题字「此卷未落墨」版心竖排 / 楷体栈补 KaiTi/楷体 Windows 回退(tokens+measure 镜像同步)/ **CJK 排印确定性**:pp-root 显式 `text-autospace: no-autospace` + `text-spacing-trim: space-all` · **关键翻案**:原提案「显式开启 autospace 提升混排观感」被镜像纪律否决——Chromium 123+/128+ 默认开启会让 DOM 行宽偏离 canvas 测高(测少渲染多→块重叠,markdown 专项刚修的同族漂移),落成「显式关停保确定性」;质感判断让位测量真相 · 弃:昼夜两态(用户搁置)· 门禁全绿 vitest 2039 - 2026-08-30 · **流式增量渐显(streaming-fade-render-plan,方案 B 施工)** · 打字机式流式文本太冷,用户要 Claude Code 桌面端「渐显」质感(demo 判:「比打字机好太多了」,否决逐字墨迹——表演盖内容)· 选:**旧文本零动画 + 只有新到达字符淡入**(块/行/字符三级切分:稳定段走完整 parseMarkdown、增量按首换行切、行内续写接进末块、换行后成新块);动画 0.72→1 起墨(不从 0 全透明——避免闪烁)、时长 --glide 0.3s(非 --snap 0.12s,流式增量要一点呼吸)、不用 blur/位移 · **增量识别零数据层侵入**:渲染器 ref 记 prev,`startsWith` 判追加(非追加=编辑/回填整块稳定);resetKey(folded)切重置 · 弃:真笔顺(数据重/秒级动画与 token 流冲突)、逐字墨迹动画(先做后否,demo 验证观感差)、deltaKey 强制重建整段(先做后否——单行流式会整行重淡闪烁,改为 fresh 段 key 重挂载)· 钉值 paper-streaming-fade.test.tsx(7 用例)+ PaperPanel.css .pp-ink-delta keyframe;门禁 tsc/biome 0-0/convergence 通过/渲染相关 73+7 用例全绿 · 遗留:markdown 行内续写在流式中短暂以纯文本呈现(稳定化后并入 markdown,流式自然态);别人未提交卷首工作的 paper-visual-decisions 一条既有红与本改动无关 - 2026-08-30 · **流式尾笔翻案:拆除(落地 commit 后述)** · 用户真机看运行中会话:「这个尾笔太难看了,关掉」——2584eedb 拍板的石青尾笔(末块底缘外挂呼吸笔尖,机器书写锚点)被用户判否 · 翻案理由:尾笔 3×15px 石青竖线呼吸形同打字机光标——正是流式渐显刚淘汰的「打字机感」,与内容淡入叠看像闪烁光标 · 选:**整链拆除**(CSS .pp-block.pp-tail::after + pp-tail-breathe keyframes / PaperPanel.tsx tailId 计算与 activeRunning 订阅 / 测试断言 / import agentSessionState 一并清,无残留);弃:改形态(墨点/他形)——用户已判「关掉」而非「换形」,换形是二次审美投资 · 保留:pp-enter 首见入场(与尾笔无关,用户未否)· 钉值改 paper-visual-decisions(尾笔空断言,防复活)+ 删 activeRunning 订阅(agentSessionState import 一并退役) - 2026-08-31 · **案卷侧边栏注疏重排(用户定题「重点解决会话侧边栏 UI/UX」,痛点拍板「全部重来」+ 方向拍板 A 注疏转录 + 三功能全收)** · 病灶:侧边栏是 Stage-3 从 DSH 搬的密列表范式,与全产品注疏版式不同体系 + 违反术语铁律(标题/aria/书脊入口/插件面板 title/command label 五处「会话」,规格书 §5 锁会话→案卷)+ 全份 CSS 未接 --font-scale(P1 字号纪律漏网)+ 行信息扁平(摊开/未摊开靠小字混排)· 选:原型 lantai.html 案卷首页列表语言的窄栏转写——**分节头点线引出**(摊开中 OPEN / 已合卷 CLOSED,rule-strong 分节,.leader 落点在节头)+ **两行式行**(宋体卷名 500 / 等宽机读注记 `Nº 卷号 · N 块 · 相对时间`)+ **当前卷朱砂左条 + 淡朱砂洗底**(与画布活跃卷界栏同语义)+ 已合卷行 ink-2 视觉退后 + **检索条常驻**(等宽「检」签 + 底线输入件聚焦转朱砂,Esc 清空,用户拍板常驻非按卷数显隐)+ 新建钮弃虚线框改 btn-text 语言(hover 墨底反白)+ 行操作改无边框文字钮 **改/合/删**(用户拍板「合」弃「收」,与合卷术语一致;中文钮禁 mono 纪律沿用;:focus-within 显形补键盘可达)+ 键盘导航(↑↓/Home/End roving tabindex + Enter/Space 摊开 + F2 改名 + Delete 两击确认 + Esc 解除武装)· 弃:原型单行「日期+点线+meta」直译(264px 装不下,转两行式,点线移位节头)· 宽度 224→264px;状态方点 D2 拍板沿用不动 · 钉值 session-sidebar-ux.test.tsx(分节/检索/键盘 5 用例)+ canvas-nav.test.ts 补三纯函数(filterRows/splitSections/sessionMeta);门禁 biome 0-0/侧边栏 26 用例 + 全量 vitest 2147 passed(2 处 catalog 守护红属并行窗口在途 loader/manifest 改动,非本批) ### 待办(从判定中涌出) - ~~paper 态是否降级为"从简"路线~~ **已拍板(2026-08-22 用户):不降级,V1 第三轮再攻质感**——V2 推迟一轮,质感根源查清并拍板后再录契约 - ~~质感问题的根源排查~~ **已施工毕(2026-08-22 V1-R3),待人判**:`prototype/paper-v1-r3.html` 五变体(T 排印优先 / P1 细颗粒真照片 / P2 重颗粒真照片 / T+P2 组合探针 / L 光影结构)+ 评审壳 `paper-v1-r3-review.html` + 六张截图(`prototype/preview/r3-*.png`)。基座统一 cream,每片只动一个变量(组合片显式标注两变量叠加);像素级机械自检 16 断言全过(T 零纹理+folio 更白+排印生效 / P1 纹理×1.5 / P2 颗粒>P1+压暗可感 / T+P2 两半同时生效 / L 受光不对称+帘纹经纬+投影偏移)。**判准不是「哪片最好看」是「质感从哪来」**——判定法五分支录在评审壳(T 赢→契约重心排印 / P 赢→材质资产管线 / L 赢→光纪律 / 组合→记账 V4 分维上强度 / 全错→回账本重新立案) - 2026-08-31 · **创作坞 v2:案头批(用户定题「UI/UX 改造交给你来做,不想费神」→ 自查模式整批落地)** · 病灶(对照大厂 agent 评价窗口):空态死白零引导 / 上下文附着面缺一代(无拖放/无 @ 引用)/ 超宽屏输入行拉满 2400px / 占位符当说明书五条提示按键即蒸发 / token 裸 [0] 徽标 / 斜杠命令只靠盲打发现 · 选:**案头态**(零摊开卷坞升居中当主角 + 最近三卷「续」签条架,首句落笔沉降回底——空态从死白变三件套)+ **880 版心度量纪律** + **附着面三路**(引=工作区文件模糊引用 list_directory 摊平+子序列匹配 / 拖文件入卷=Tauri onDragDropEvent 原生通道偿还 C10 尸检课——HTML5 drop 在 T2 WebView 永不触发,界栏高亮+命中坞体才入卷 / 夹=file picker 兜底)+ **律 **册(13 行键位总览浮层,渐进披露——占位符只留一句)+ **一次性眉批**(历史导航提示 localStorage 旗标 6s 自散,提示长在功能所在处)+ **墨量线**(坞底 1px = token/目录窗口占比,>80% 转朱砂,裸徽标退役进 hover)+ **钤印拟文**(发送钮墨色实心方章 hover 翻朱砂——人=朱砂语义:发送是用户的动作)+ **翰**(命令面板入口钮,/ 与翰共用一层面板)+ **运行呼吸线**(画布底缘石青 2px 呼吸,exec 订阅与书脊运行点同源)· 弃:**贴图入卷**(agent 无读图链路,贴图路径是空头支票——C10「接了也是假功能」同款判断,待引擎读图链路成立再立项)· 术语新增:引/翰/律(单字工具钮族与夹/停同族,title 补语义);纸墨语义铁律零违反(运行态恒石青、人的动作恒朱砂)· 钉值 composer-dock-desk.test.tsx 16 用例(翰/律/墨量线/引纯函数+面板/mock 拖放不炸);门禁 tsc/biome 0-0/vitest 定点 37+16/build:builtin-plugins 23 插件/vite build/convergence 全绿 · 教训:ui/ 有封口门禁(manifest 外禁新文件)——单函数新件并入 bridge.ts(Tauri 路由同族),webview-drag.ts 落地即删 - 2026-08-31 · **浸墨法则入宪 + 五面转录(用户问「UI 简陋有没有治」→ 病灶诊断 + A/B 实证 + 拍板 B 整批落地)** · 病灶定案:简陋 ≠ 极简——只有线框没有墨(古籍隐喻抄了线没抄墨:真古籍版框=粗黑双线全页最重墨、印章=实心朱砂、题字=浓墨大字;产品全做成灰发丝+描边+中庸字重)· 证据法:prototype/ink-ab.html 同内容同栅格 A/B,只改墨量即换血,用户拍板 B · 五法则入宪(规格书 §10 + tokens 浸墨块):①墨阶锚点三处(版框 2px/主动作墨底+硬偏移投影/屏级分区硬线)②字重极端(题字 900 新装载/卷名 600/机读 400)③句读点朱(每屏至多一处红字)④纸层次(噪点 .09+边沉+帘纹)⑤完工动作(选中墨底反白/浮层投影/节题方墨)· 五面转录:首页/画布界栏双线框/创作坞/侧栏/设置(设置=克制收敛即达标)· 弃:贴图入卷同款判断——不加新装饰不加新组件,只上墨 · 附带修:案头签条架 stale projectPath(真机截图循环逮到——进入画布晚于挂载致签条恒空)· **方法立宪**:视觉改动此后强制「渲染→截图→自查→修→再截」闭环(无头 Chrome + CDP 管线已通,真机 WebView2 调试口=应用自带 9222 非 9223);钉值 paper-visual-decisions 补 7 断言(界栏钉随双线框翻案改写);门禁 tsc/biome/vitest 2191/23 插件/convergence 全绿 - 2026-09-01 · **UI 全面审计修复批(用户示生图模型 mockup 判「比现在的创作坞好看多了」→ agent 三轮诊断(构图/流程/token)皆被否「说的还是那些东西,我已经来来回回做了很多次」→ 用户拍板「先查有多少地方丑、多少地方根本有问题,然后全修,今天就干这件事」)** · **取证法定型**:headless Chrome 9223 + CDP + **vite 模块注入强开面板**(`import('/src/state/dock-store.ts')` openPanel + Runtime.evaluate 点按钮)——mock 模式可拍全套界面(首页/工作台/引/思考/设置/命令面板),推翻「mock 拍不到工作台须真机」旧结论;脚本 `D:\tmp\ui-audit\cdp.ps1`,修前 02-07 修后 11-14 对照留档 · **视觉选(P0-P2 一批)**:①**选中态定案 `--sel-wash` **(ink-1 7% 洗纸)+ 朱砂左脊——收编三套野选中色(命令面板 paper-deep 黄绿 / 引·斜杠 indigo 蓝选 / 思考菜单 seal-soft 粉选),全产品唯一选中语言;②**创作坞盒转线**(dock-v3 黄金样本语言落地):模型触发器/权限三档/思考/引/夹/翰/律全线去框改纯文字,选中=重墨 600+2px 朱砂底线,拟文印保留全坞唯一墨底锚点(浸墨②收严:黑块分段与拟文印争锚判死);③弹层海拔统一 --elev-menu(raise 硬偏移给不了「弹起」感);④帘纹 .016→.032/晕影 .07→.12(R4 零纹理不破——加的是排印墨非贴图);⑤amber 引导条转墨系(无 Key 是常态非告警);⑥origin 十字 opacity .45;⑦输入条去粉(半透明纸叠橄榄舞台出脏粉);⑧浮层互斥(四层同屏只开一个)· 新 token:--ink-solid(#26221c 墨源实色,遮罩/lightbox/mask 唯一豁免位)· **代码 20 处全修(三 agent 审查)**:chat-core 全局 store 订阅重建累积(模块级退订登记)/假 AbortController/吞错落 warn/abort 超时退订;tauri-io 自然退出监听泄漏 + EOF 后 readLine 挂起;workspace 预热失败静默卡死(复位 _graphWarming+告警)+ 监听器创建期回滚 + doGraphUpdate 死代码删除;settings providers 元素级毒化校验;PaperPanel opsCache 陈旧闭包(补 regionMsgs 同一性);模型选择器自定义提交不收下拉;WinControls timer/ProviderPage 回包卸载守卫 · **查明不改**:!important×7 全带豁免注释;石青状态圆点=机语义合规;圆角 50%×4 是字形非盒角;typedJsonRpc as T 无运行时校验**唯一挂起**(schema 层架构级,单独立项)· **技术坑记档**:`.pp-composer button` 通配(印章语言基类,0,1,1)压单类选择器——坞内控件覆写必须复合选择器(.pp-composer 前缀),本轮三档黑块残留即此栽的 · **钉值翻案**:paper-visual-decisions「选中态墨底反白」随重皮改写为文字语言三断言 · 门禁 tsc/biome(改动文件 0 新增)/vitest 全量 2191/build 全绿,commit c5872200 - 2026-09-01 · **常驻匣退匣:全态一张皮(用户看修后对照判「很明显,空态的这个形态反而更好看」)** · 两态分皮判死(案头直书于纸 / 常驻匣 paper-deep 底)——控件语言统一后,「摆哪」之外的皮差只剩噪音,且案头形态就是 dock-v3 黄金样本本体 · 选:常驻态 .pp-composer 退匣(paper-deep 底→透明,直坐舞台纸面),**分区只留坞顶硬线 + 版口钮**(浸墨③屏级分区线本就是唯一合法分区件)· 弃:全态无线(常驻贴底必须有线落座,无线则输入条与内容流失界)· mock 建卷 CDP 截图验证常驻态(15-after-docked.png)· 钉值不破(「坞顶硬线」断言保留);composer 四测试文件 38 用例绿 - 2026-09-01 · **全宽槽带判死:常驻态改浮层落座(用户真机看后判「很傻比,屏幕最下面有一条横向遮挡」)** · 病灶:常驻槽原是 flex 列里的普通行——即使退匣透明,仍占一条**全宽布局死区**,纸到槽顶被切断,屏幕底部横一条异色带;案头态无此问题正因它是绝对定位浮层 · 选:槽两态统一绝对定位浮层落座(常驻 bottom 14px / 案头 clamp(48px,12vh,160px),全态只有坐深不同),纸铺满到屏底,坞浮纸上;弃:保留布局行(透明也挡纸+挡画布交互)· 代价明示:区域可拖到坞后面(纸叠纸遮挡,用户可拖走,非死区)· --composer-h-live 量高上报保留(小地图/固定件照常上让)· 截图 16-after-overlay.png 实证;composer 五测试文件 43 用例绿 - 2026-09-01 · **视角抢夺修复:canvasSize 变化不再重置 pan(用户报「点模型选择视角跳回原点,怎么会跟视角有关」)** · 病根:初始视口 effect(D-R1-3 锚点对下缘)把「首测落锚」写成了「**每次** canvasSize 变化都重置 pan」——画布 1px 尺寸差(真机上模型下拉引发滚动条/布局微变、拉窗口、开侧栏……)就把用户视角暴力抢回默认锚点;模型选择器只是恰好按在雷上,与模型选择本身无关 · 选:**世界点守恒**——首测落默认锚点 pan(保留),此后任何尺寸变化保持「锚点屏幕位置下的世界坐标」跨尺寸不动(旧尺寸锚点处世界点 → 映射到新尺寸锚点,pan 平移差量);弃:重置式(抢视角)· 代价明示:无——纯守恒,Home 回原点/书脊定位/聚焦飞行全不受影响 · CDP 实证:pan 600→608.5(随 1px 差平移而非跳回 800 默认值);focus-flight/paper-core/space/handoff/canvas-nav/canvas-store 79 用例 + composer 视觉 34 用例全绿 - 2026-09-01 · **UI 全面审计收尾批:§11 层次法立法 + 三轴过审施工(用户拍板「先查有多少地方丑、多少地方根本有问题,然后全修,今天就干这件事」的续批——立法先行,全界面按三轴过审,发现即修)** · **立法(230c8456)**:规格书 §11 层次法——三轴模型(海拔=信息层级梯度/包含=边界与归属/轻重=墨量与许可)+ 四档海拔梯子 + 选中语言分型 + 面审四问清单,此后 UI 审计以此为准绳 · **取证法**:mock dev 恒空态被推翻——mockInvoke 补 workspace_list 种子(置顶活跃/非置顶无注册名引擎关两行)+ 极端种子临时注入(超长注册名/目录丢失)取证边界形态,验毕回退 · **流区/牒卡批**:F2 拟策条目剥标题标记(### 字面量泄漏,measure/render 单一解析同步 d3455eff);牒卡选项 hover/选中统一行型选中语言 sel-wash+朱砂脊(71ba20f8); F1 错误卡无意义 args 不裸奔——hasArgsToShow 单一判据(空串/空白/{}/[]/null)ToolBody/测高/墨迹/foldLabel 四处同源镜像(37b7be00);F4 子代理组组内折叠不摊平——新块 kind subagent 组头恒一行、groupToolRuns skipSubIds 显式跳过不建嵌套组、出错/待审批自动张开(37b7be00,+22 用例)· **设置面板批(46658d21)**:字体缩放滑杆内联 accentColor 压过「原生控件压回墨色」立法渲染系统蓝——删内联、接线零引用死代码立法件 sp-slider-row/sp-range(--pct 驱动填充);插件 tab 安装输入框补 flex:1+minWidth:0(placeholder 裁成 tarball UR)+ 警示框 borderRadius:6 违圆角恒 0 铁律退役 · **首页/侧边栏批(b5650aaa) **:侧边栏「N 块」恒陈旧——从未订阅各卷消息 store(种子实锤恒 0 块),syncMsgSubs 随会话集重挂修活;工作区卡三处:①长名硬裁无省略号+固定徽标被推出卡外——text-overflow 在 flex 容器上 no-op,省略号落真实文本盒 sh-ws-name-text(name client 352/scroll 711 实测)②动作列「右侧操作」立法从未兑现(--row 缺 flex-direction,actions 恒卡底隐形占位 223×42、卡高虚胖 186)——改绝对定位卡底右带与「进入画布 →」同线对望,悬停显形不占几何;弃:严格恢复 row(随排保留 223px 挤主区到 161px、meta 行必裁字——.sh-main 恒 880 恒两列 386 无窄卡,立法词让位包含轴)③目录已丢失卡仍示「进入画布 →」假许诺——dead 态不渲染(合 CSS 自注「诚实显示+禁进」立法)· **收口**:typedJsonRpc as T 盲转唯一挂起 → 立项设计件 docs/design/rpc-runtime-validation-design.md(zod 同址表+重载并存渐进收编+mock 同表自检,landmine-map 挂第三步指针,不施工 d481534e);附带 biome ci 合并门禁复绿 6 文件纯格式收口(53f110be)· 门禁:biome ci 642 文件 0 错/tsc 0/paper 域 74+设置域 9 全绿;截图 25-48 留档 D:\tmp\ui-audit(修前修后对照) - 2026-09-01 · **三轴建设批·海拔轴(用户不满「层次感一点没做」拍板开 D:\HoloGramHG-3build 建设批 jobs 7-11;Job7 盘点+Job8 施工)** · 取证:静态全库 z/影清查 + CDP 截图 50-60 层枚举+像素仲裁(veil 目测曾误判,GetPixel 同坐标采样定案 30% 墨幕存活)· 选:**影两族立法**(纸片件=压印族 `--elev-raise` letterpress 2px 3px 左上;悬浮面板=漫射族 `--elev-menu` 环境软影——按材质隐喻取用不按档位)+ §11 补立面板架档(280/281/282=`--z-paper-base/rack/sidebar`,书脊架/侧栏 token 化)+ 八处散写归档(首页 veil 420→`--z-panel-veil`、toast 900/拖拽幽灵 320→`--z-dialog` 520 全局瞬时带、抽纸条浮钮 300→浮层 70、sl 下拉 40→45)+ 首页模态大软影 `0 18px 48px` → `--elev-raise` 消灭混材质;弃「光源恒 letterpress 单族」(与设置模态/模型菜单两处活体教材矛盾,两族修法零教材改动)· psh-host z500 嫌疑撤销(h0 锚点脚手架)、墨锚洇晕/进度点 seal 环豁免(材质/指示语汇非海拔)· commit 98bdf2be,修后 59/60 存档,vitest 2235/biome 全绿 - 2026-09-01 · **三轴建设批·轻重轴(Job9 字重普查 67 处)** · 选:**四级字重立法**(900 题字 / 700 卷首 / 600 卷名·条目名·动作钮·面板题 / 400 机读注记)+ 16 处 500/700 中间档清零(升 600:会话名/meta b/pp-name/save/sp-btn/ss-label/sp-title/安装钮;降 400:状态签/字段标签/表头/LIVE 徽章·后经印签族惯例收 600/Tab 基底·选中态靠墨底反白)+ 型号名提墨 ink-1 与行内注记分阶(平坦面实锤)· **钉值甄别**:paper-visual-decisions 打回 folio-title——拍板 B 本含卷首 700,规格书 §10 原文漏记,测试即立法记录,已对齐补录 · commit e99229a1,61/62 存档,tsc/biome/vitest 全绿(event-catalog 5s 超时为负载 flakes,独跑 3s 绿,与本批无关) - 2026-09-01 · **三轴建设批·包含轴(Job10 泛框泄漏案)** · 病灶发现法:56/61 截图目测「组框套条目框倒挂」→ 探针复核穿透 pp-root 引疑 → **活样式表递归扫描**(注意 Chrome CSSStyleRule 自带空 cssRules,walk 须查 length 否则全跳)+ 硬刷新复现排除 HMR 积垢 → 元凶=**`.pp-composer button { border: var(--rule-strong) }` 泛框**,特异性 (0,2,1) 压过 `.ms-item` (0,1,0) 三边 none,把创作坞内一切嵌套按钮(模型菜单条目/思考选项)全框成卡中卡 · 选:整条废除(实测 mode-opt/tool-btn/attach/send 全自持样式、泛框零贡献)+ 新立 `--rule-head` 头线 token(2px ink-2 菜单书眉顶缘,收编 ms-dropdown/sl-log 两处散写)+ cd-sheet/pal-box/sp-panel 三处 `1px solid var(--ink-2)` 收编 `--rule-strong` + §11 嵌套语法四条立法(级数递减外≥内 / 两框为止 / 语义缘不入序列 / **泛选择器框禁令**)· 教训:截图目测与粗探针会合伙骗人,computed 值+活规则递归扫才是裁决者 · commit 2a4710a8,64 存档(条目三边归零+头线生效),tsc/biome 646 文件/vitest 2234 全绿(event-catalog 负载 flakes 独跑绿) - 2026-09-02 · **坞位统一批(用户两问合一:①「两张位置」三案拍板 **C——两态同位案头抬起**(A 贴底统一/ B 过渡动画被弃);②「不同窗口上布局会变,说实话很烦」——判 12vh 坐深随窗口高度浮动是病灶)** · 病灶:空卷态 clamp(48,12vh,160) 抬起 vs 非空态 14px 贴底,首句落笔(开口即开卷)坞瞬移下沉最多 ~146px;且案头抬高量随窗口高变(700px 窗=84 / 1080p 满屏=130 / 1440p=160)——不同窗口大小坞位不同 · 选:**两态同位 `--composer-rise: 96px` 固定抬高**(12vh 退役,坞位与窗口大小解耦)+ **签条架出流悬挂**(absolute 挂坞下 14px——架出没不推坞位,槽内仅坞在流)+ **形态差保留**(案头退匣直书 / 常驻装匣坞顶硬线+版口钮——浸墨钉值与 paper-visual 断言不动)+ **消费面清坞顶线全量 +96**(侧栏/书脊/牒卡宿主/小地图 CSS+inline/目次带几何 COMPOSER_RISE——TocStrip/MinimapView 与 token 同源镜像)· 弃:A(用户选 C)/ B 过渡动画(位置仍两态)/ 全形态统一退匣(坞顶硬线+版口钮是浸墨③墨阶锚点钉值,本批不动——若仍嫌换装突兀另立拍板)· 代价明示:常驻态底缘 96px 空带(坞浮纸上,下方画布可拖入钉块——纸叠纸遮挡可拖走,9-01 拍板既有权衡);窗口 <928px 宽时坞仍随窗收窄至 100vw−48(880 版心下限正常响应,≥928px 恒 880)· **自查环逮到真回归(截图立法首功)**:CDP 截图空卷态坞整体缺席 → DOM 探针定位 top:-200000/height:400000——**槽形态类 `pp-desk` 与世界层桌垫 `.pp-desk`(db397238 ±200000px 巨幅)同名撞车**:槽被桌垫 top/height 接管,bottom 过约束被忽略 → 坞射出屏外(该撞车自 db397238 起潜伏,非本批引入;修法 = 槽形态类改名 `pp-at-desk`,桌垫与钉值不动)· 验证:CDP 几何探针两态坞底恒 669(=页底−96)数值级一致;侧栏底缘与坞顶 0px 差对齐;常驻态 2px 坞顶硬线 + 版口钮 ::before 在位;截图 65(撞车实证)/66(案头态)/67(常驻态)留档 D:\tmp\ui-audit;tsc/biome 改动面 0 诊断/composer 域 8 文件 96 用例绿/全量 2257 passed 唯一红 = event-catalog(并行窗口在途事件源改动所致,归其 commit 时再生成,与本批无关) - 2026-09-02 · **流区四连改档:物理包边 + 洗底全退役 + 版口钮独挂 + 划词朱线(用户判界栏墨框「简陋」起批)** · 病灶:①08-30 落地的界栏双线框(2px 半墨 border + 飘浮 outline,规格书 §1 锁定件首次落地)实机判简陋且与 09-01 真纸材质打架——框是「画在纸上的线」,真纸的缘是材料;②活跃卷 seal 4% 洗底+提浓是「变色」不是「结构」,与浸墨③整屏至多一处红互相打架(活跃卷同时挂洗底+全墨框+版口钮 = 一屏三处红噪音);③原型 .folio-head 卷卷挂朱砂短横,系原型先于真纸材质批与一纸多卷定案的历史形态 · 选:**物理包边(读法 B,用户拍板)**——纸缘 = 材料不是墨,border/outline 全退役,box-shadow 四层堆物理四至(inset 受光缘 --sheet-lit 左上 → 背光缘 --sheet-shade 右下 → 裱边带 --sheet-band 7px 一圈纸色深带 → 接触落影 --shadow-sheet 重校 .07/.035); 剂量 A/B 台 prototype/edge-ab.html 定档(亮 .75——米色桌会吃淡光 .55 被吞 / 沉 .13 / 带 42%);WebGL 探针 prototype/webgl-paper.html 判读定案「版框=印在纸上的墨,流区这张叶不印框」· **活跃洗底退役(「变色」判死)**:active 只换落影一档 --shadow-sheet-active(手里正拿着的纸离桌面更高一点),活跃感刻意不押红条上;background 简写禁令延续 · **版口钮独挂活跃卷**(.pp-region-active .pp-folio-head::after)——整屏至多一处红,红在哪卷即活卷;**攥边墨洗**:边缘 hover 朱砂红带→ink-2 30%(红不进结构缘)· **划词朱线**:流区 ::selection 原生洗底退役(UI 面照旧 seal-soft),选区以手写朱笔下划线呈现(纸不动、只落墨,圈点句读语汇、朱砂=人); 新纯函数层 src/paper/sel-ink.ts(mergeSelectionLines 行合并 / selInkPaths 手写路径——主笔 1.7px 实线 + echo 淡墨第二笔浸墨双笔 / selSeedOf 文本 hash 种子——同选区恒同线);.pp-sel-ink 固定视口层 z 62(client 坐标 Range 活矩形,纸内件带上沿 60 之上浮钮 70 之下;跨块选区也画线;行数封顶 400 护 SVG 渲染);host.ts 导出三纯函数 · 弃:界栏墨框改形(改粗改淡都是「还是框」)、选区墨底线(选区语义=人的手迹,恒朱砂)· 规格书同步:§1 界栏行翻案注记 + §1 划词条新增 + §10 纸层次补物理包边段 + 转录位界栏双线框划线 · 钉值 sel-ink.test.ts 9 用例(新文件)+ paper-visual-decisions 改写(region 无 border + band/lit/shade 在列 + active 无 background 只落影一档 + 版口钮门控 + sel-ink 层 z62)· **坑记档**:CSS 注释里写完整选择器子串会撞钉测 ruleBody 的 indexOf(本批两处撞上)——注释避让完整选择器、测试选择器带 ` {` 收窄 - 2026-09-02 · **首挂视角错位根治(用户报「我已经遇到视口 bug 了,视角定位这一块就是有问题」——9-01 视角抢夺修复的残留竞态)** · 病灶:全新页面**首次**进画布 pan=(864,722),偏离正确锚点 (632,613) 恰 (+232,+109);重进反而正常(间歇性)· 取证法:zustand setView/setCanvasSize 调用栈补丁(须打在 vite `?t=` HMR 版本 URL 的活实例上——裸 URL 是另一实例)+ 首挂写入序列捕获 `size(1264,709) → view(400,504) → view(632,613) → view(864,722)` · 根因 = **守恒 effect 与「重挂回锚」effect 挂载竞态**:守恒首跑读 render 闭包(陈旧默认 800×600)落锚 (400,504);RO effect 先行同步写入真实尺寸;「重挂回锚」用 live 尺寸抢先纠至 (632,613);随后守恒二跑(尺寸 800×600→1264×709「变化」)从被改的 pan 反推出**虚构世界点 (−232,−109)**,把新旧锚点差当用户平移补偿回去 → pan=(864,722);重挂时 store 尺寸已持久无「变化」可守恒故正常 · 选:**回锚职责收归守恒 effect 单 owner**(重挂回锚 effect 只留 requestFocus(null)——每次挂载 prevCanvasSizeRef 归 null,守恒首测分支天然落锚,语义等价且无竞态)· 弃:双 effect 调序(时序脆弱)/ conservation 改 live 读(治标——闭包/活读混用继续埋雷)· 教训:**同一 store 的挂载期多 effect 写锚 = 竞态温床**——守恒公式假设「pan 对应 a0」的自洽链路被任何插队写入破坏即出幽灵偏移;锚点写入必须单 owner · 验证:fresh reload 首进 (632,613) ✓ + 三轮重进恒 (632,613) ✓(修复前首轮必 864,722);tsc/biome 0 诊断/paper 域 15 用例绿 - 2026-09-03 · **会话流版式节奏批(stream-rhythm 刀1+刀2,计划件 docs/archive/render-paper-line/stream-rhythm-plan.md 立项当日施工;用户方案《兰台 Agent 会话流:版式系统方案》对审转计划——D1 试值 + D2 最素形态,均待用户真机终审)** · 起批:会话流是等距块栈(块距 48 恒定),20 事件回合读作 20 等价物——瀑布感 · 选:**工作单元 pass**(新纯函数层 paper/grammar.ts 工具族推导 + paper/group.ts 单元封套,单元 = tool/toolgroup/code/subagent 连续运行 + 挂靠夹注;Error 块起恢复单元)+ **间距三档**(intra 32 < 块距 48 < unit 64 < recovery/stage 96,canvas-math ANCHOR 表驱动 rhythmGap——D1 试值)+ **阶段细线**(来文块 ::before 弱线 --rule-soft,落 stageGap 96 中线 top -48px——D2 最素形态:留白+细线)+ **两宪法**(封口纪律:已封口单元不可变、id 锚首成员、成员只增不减;跨消息前瞻禁止:挂靠只在同消息内——tsc 曾抓到真 bug:首版 push 即清 kind 致散块永不成组;测试曾抓到跨消息后向并入破坏封口语义——修法 = 单元不跨消息,消息边界即收口)· 弃:通用 timeline-UI 圆点轴(往模板倒退丢注疏气质)、自动阶段标题(会撒谎,违反时间不能骗人)、新辅助栏(时间序由主列保持,眉批/贴黄挂宿主)· B1 保留:无节奏信息的外部调用面走 B1 基线(块距 48 / 来文 72 / 尾距 8);上方是 user 恒尾距 8(asterism 让位反转优先于节奏档)· 接线:PaperPanel regionCoreCache memo 内 groupWorkUnits→unitMembership→rhythm 档喂 layoutRegion 栈(host 三处同步:host.ts/host.aliased.ts/host-modules.ts faceDeps)· 钉值:tests/paper-stream-rhythm.test.ts 25 用例(分类器/单元成型/封口不变性专项/节奏档矩阵)+ paper-visual-decisions 补三断言(间距值真源 + 细线形态 + 接线在册)· 门禁:tsc 0 / biome 0 / paper 域 186+25 全绿 - 2026-09-03 · **stream-rhythm 刀3+刀4(封口纪律+长会话 / 小修收口——同日续批,agent 自查模式)** · **刀3 布局保证**:活尾重排限定补布局级测试——封口前缀 = **刚体**(追加事件七档前缀演化谱系下,封口块节奏档/相对位置逐字段不变、绝对位移全体同值 = 滚动锚定的数学面;新封块只许追加尾部)+ 分派走新 `group.rhythmAssign` 单一真源(PaperPanel 布局栈与测试共用,防测试/生产漂移;host 三处同步)· **组原子性**:折叠组 = 布局栈单条目(子卡摘除——虚拟化窗口对组只能整取整舍,窗口不腰斩折叠组的结构性保证)、展开组成员栈内连续(切不出交错序);流式滚动锚定 DOM 面 = 既有 `pp-stream-live` transform 过渡 200ms(80ad4801 用户拍板)+ 入场动画残帧根治(8a5823f2)——本批零新 CSS · **长流性能**:~1265 转译块全链(translate→group→rhythm→layout)烟测预算 1.5s(实测几十 ms——数量级回归防线;旧卷回放 = regionCoreCache 按消息引用缓存,groupWorkUnits+unitMembership+rhythmAssign 全 O(块) 线性 pass,不破「单流区更新=常数」)· **刀4a foldLabel 判别量**:工具组折叠行 `▸ 工具 ×3 · read_file a.ts / b.ts / c.ts`(露路径/命令,压缩的是重复不是信息;截断/同值去重补 ×N 总账不失真;无判别字段回退旧计数文案;流式半程 JSON 走 toolDigest 原串兜底)——判别值截 20 字保 10px mono 单行放得下,FOLD_ROW_H 测高镜像零变化 · **刀4b 目次带阶段导航**:`buildTurnAnchors`(裸块 kind 扫描)退役换代 `buildStageAnchors`( **消费工作单元**——阶段 = user 单元,与阶段间距/细线同真源;锚带 stageIndex/unitId 身份键;空预览回退「阶段 N」),hover 兜底升格 `阶段 N · 首句`;units 进 RegionView/regionCoreCache(stub 卷空数组)· **刀4c Error 墨色家族确认(零改动)**:错误状态色 = `--fail` #a9443f 墨浓红(非纯红非朱砂);错因墓碑 = 贴黄款(`--seal` 7% 混纸淡底只作纸晕、墨身 --ink-2);工具/程文错误输出 inline `var(--fail)` 两处单一真源——**朱砂=人铁律复核通过**,钉 paper-visual-decisions 三断言防漂移 · 钉值:paper-stream-rhythm 31 用例(+6:刚体×2/组原子性×3/性能烟测)+ paper-tool-group 判别量 5 用例 + stage4-toc 阶段锚换代 + paper-visual-decisions 33(+3 Error 家族)· 门禁:tsc 0 / 产物重建 30 自包含校验过 - 2026-09-03 · **stream-rhythm 刀5 族节奏批(用户真机判「整个会话流还是瀑布,一点版式设计看不出来」——刀1-4 落地后首个真机负反馈,自查三根因,用户拍板「ABCD 全落地」)** · 根因自查:**①四族分类器是死代码**——grammar.ts 的读/写/验证/提交推导没有布局面消费(只有测试 import),groupWorkUnits 只看块 kind,连续工具全并一个巨型工作单元 → 整段 intra 32,比原来恒 48 **更均匀**(瀑布感反而更纯);**②可见行同质**——折叠态长回合可见行 = 夹注行 + 组头行全是等宽小字行,32/64 间距对比扛不动结构,单元无任何视觉身份;**③规则表承诺缺位**——「单元→单元 细线」「验证链毕标记」只落了阶段档 · 教训:**门禁只保证「管线按规格执行」,规格本身在真实流上产生的节奏词汇太少——真机反馈是唯一能暴露设计深度不足的信号 ** · 修法四件(用户拍板全落):**A 族边界切单元**——grammar 增 `rhythmFamilyOfBlock`(tool → 节律族;toolgroup → 子项末位已表态族;other 收敛 null 不表态——远端/未知名不破语法铁律的节奏层延伸),groupWorkUnits 消费节律族:已知族切换(读→写→验证→落款)即封口旧单元开新工作单元(errorish 转折优先于族界;recovery 同族重试续收、异族切出),WorkUnit.family 在册——回合内出现「读包/写包/验证包」,unit 64 在族间开火、32 收在族内 · **B 折叠组按族切分**——translate.groupToolRuns 族变断组(null 族并入不断):「读 ×3」「写 ×2」「验 ×1」各自成行判别量各露各的,单元边界随之可见 · **C 验证链毕锚**——「✓ 阶段完成」小字(ink-3 mono 挂链末块下方,不占块高测高镜像零变化),发线判据(时间不能骗人):后继单元非 recovery(失败转折自宣告,✓ 不说谎)或 sealed 末位发; 流式在跑不发 · **D 单元视觉身份**——`.pp-unit-lead::before` 单元界短规线(96px 短线比阶段全宽线弱一档,top -32 = unitGap 64 中线;只发 work 首且上方非来文——B1 反转区无线位;叙述不碎、转折自宣告)+ 组头族签(fold.ts 子项已表态族全同 → 前缀族字 读/写/验/落,混族回退「工具」)· 线语法三级立法:**全宽 = 阶段界 / 短线 = 单元界 / 无线 = 同单元收紧** · 接线:rhythmAssign 换签名 (blocks, units) 增派 unitLeadIds/verifyDoneIds(membership 内化——刀2 接线钉值随之演进),RegionView/regionCoreCache/STUB 同步,块类名 pp-unit-lead/pp-verify-done · 钉值:paper-stream-rhythm 37 用例(+6:族切组前缀稳定/族切单元/other 不表态/recovery 族续/链毕四态/单元线规则)+ paper-tool-group 族签换代 + paper-visual-decisions 刀5 四断言 · 门禁:tsc 0 / build 产物 30 自包含校验过 / biome 我的改动面 0 / convergence 通过 / vitest 全量 2397 passed 唯一红 = perf-paper-pan(并行窗口小地图 WIP 的 beginPath,按文件归属分诊非本批)· 提交纪律:PaperPanel.tsx 与并行窗口在途小地图 hunks 同文件——**hunk 级分块 add**(node 过滤补丁 + git apply --cached,只 stage 本批 7 hunks,小地图 WIP 留工作区归其窗口) - 2026-09-05 · **钉住与纸条换装:松手定夺 + 盖章剪报(用户拍板「杀路径 B」+「盖章剪报方向」;计划件 docs/archive/pin-strip-rework-plan.md 立项当日施工,D:\HoloGramHG-pin-strip worktree 隔离)** · 病灶:①钉住块是「画框语言」漏网——outline 14px 悬空细框,正是 09-02 真纸化批给流区判死的病灶(产品照抄 8-22 原型,先于真纸化批,界栏双线框同理由翻案而钉块漏扫);②钉住态无「我已被钉住」身份标记——原型 .pin-hint 竖排「钉住」签产品从未转录;③纸条虚线框是语义错位——层次法线级语义虚线=草稿/占位,纸条是真实物件(且原型无纸条,自创样式从未过账本);④400px 流带判据隐形(拖块回带=取消无预览、拖选跨带=意外成条);⑤commit 时序不一(块拖出越 6px 即时建钉 vs 纸条松手才落);⑥纸条 ✕ 即删不可恢复 · 选: **松手定夺**(块拖出走纯预览→松手判带:带外落钉/带内取消回槽无状态变更;流内挖洞后移到 commit 帧)+ **杀路径 B**(拖选只做选择——划大段字复制绝无误触;抽纸条唯二入口=按住已有选区拖出+浮钮)+ **带显形**(拖拽中来源流区提落影至 lift 档——接触落影族第三档 token --shadow-sheet-lift,变色判死判例延续;拖块悬回带内块影转「松手回流」批注态——「松手入卷」同族)+ **盖章剪报换装**(钉块物理包边轻量档+paper-sheet 纹理——从同一张纸剪下来的;竖排身份签补抄;hover 落影提档不描边)+ **纸条材料化**(虚线退役→物理缘轻档)+ **两击销毁确认**(3s 超时回退)+ **一次性眉批**(PIN_HINT_KEY localStorage 旗标——首次进画布教「按住文类签可钉」)+ **settle 手感**(钉=按下/纸条=放下,from-only keyframes 走 translate 独立属性——pp-enter 事故立法延续)· 分流例外:**眉批撕出保留首动即建钉(instant 旗标)**——其携带预览=孤儿钉跟手,纯预览会全程无像;撕出批注的揭起手感与抽纸条 lift mask 同族 · 弃:洞显形入场动画(虚拟化重挂会重放);路径 B 保留方案(ghost 预览预警不足以覆盖「划字复制」误触面)· 钉值 paper-visual-decisions +8 断言(outline 退役/竖签补抄/strip 物理缘/洞弱化/band lift token/路径 B 退役/instant 分流/settle translate 纪律)· 门禁:tsc 0/biome 0/定点 115 用例绿;全量门禁与真机验收(plan §6 十条)待跑 - 2026-09-10 · **流区激活指示·拿纸 + 朱笔划界动效(用户问「选中的流区怎么样才能明显又好看呢,做个动效?」——同日自动选中退役批的姊妹拍板)** · 病灶:活跃指示静态两处(接触落影加深一档 + 版口钮朱砂条)够克制,但**切换瞬间是硬切**——显式激活这个动作本身没有回响,用户感觉「不明显」的真因在切换时刻不在静态 · 选:**两环一体**——①**拿纸**(pp-region-take keyframes,0.4s 家风缓动):激活瞬间落影从平放档**过冲 lift 档**(拖拽手势既有第三档 --shadow-sheet-lift)再落「在手」档——「刚把这张纸拿起来」的物理过场;基座 transition box-shadow 320ms 承接旧卷缓退(物理世界纸影不瞬移,拖拽带显形起落同享此缓动);class 不变不重放(幂等再点同卷无动效)②**朱笔划界**(pp-seal-draw keyframes):版口钮朱砂条从 0 划到 56px,0.24s cubic-bezier(0.23,1,0.32,1) 同 pp-enter 家风——落笔划界的书写感;红钮既是切换时刻的动效主角又是持久态「红在哪卷即活卷」指示,一枚元素两任 · 三档影值全字面复用既有 token 零新魔数;静态影深/纸色/墨阶/圆角全不动(变色判死延续)· 弃:静态 --shadow-sheet-active 再加深(落影过深纸显脏,且持久指示已由红钮独任);transform 微上浮(.pp-region 若位移 2px,世界坐标换算与 InkLayer 墨迹层即错位——分层对位红线,比块级 transform 事故更隐蔽);光斑扫过/sheen(非矿物墨物理世界的语汇);呼吸灯常驻动画(持续动效拖累内容层 + 与运行态 quill/活墨动画打架)· 钉值 paper-visual-decisions +2 块:拿纸帧内禁 transform 禁 background(pp-enter/settle 事故立法延续)+ 三档影值字面在册;划界宽度动画(非 transform)+ 家风缓动整句钉死;基座 transition 整句钉死(单属性 box-shadow + 缓动,防后续顺手加属性) - 2026-09-10 · **拟策卡渲染专项:markdown 体换装 + 石青策面(用户三连拍板「太毛坯」+「不要渲染行号」+「卡片要有点辨识度」)** · 病灶三连:①内容渲染是 parsePlanItems 剥标记平铺——标题/列表标记剥成裸行,「### 修整方案」只以字面进条目(2026-09-01 F2 修的 ### 字面泄漏只是止血,结构从未真渲染);②01/02/… decimal-leading-zero 石青序号是行号不是列表语义——逐行编号与内容结构无关;③卡片 chrome 只有顶硬线+底软线,与正文块零辨识(满屏唯一差异是一列小号码)· 选:**markdown 体换装**——PlanBody 走 parseMarkdown + MdBlocksView 完整管线(标题/列表/加粗/围栏码/表格/链接全结构渲染),与正文共用 .pp-md 族 + measureMdBlocks 同源测高;行号机制随 ol/counter 整链退役——拟策是提案文档不是清单,列表标记自己长出自己的 bullet · **石青策面**——3px 石青硬左线 + 石青 4% 淡底 + 横向内距 16,顶硬线/底软线保留——与来文朱砂左线对仗:人声朱、机策青;选项区/钤印三钮/已处理态原样入面 · 弃:继续收窄 parsePlanItems 名字面(治标);拟策专属小字号 md 变体(须整套 MD_* 测量镜像翻倍,直接复用正文 17px 体是同源纪律正解);石青底加深(4% 淡底+左线即「稍微有辨识度」,深底与来文/贴黄抢屏)· 退役面:parsePlanItems 整函数删除、CHROME_TOKENS.plan item/num 六键 + PAPER_TYPE.planItem 退役、measure 条目环换 measureMdBlocks、ink 源换 markdownInkSources(inset 参数化);标题/选项区测宽补扣策面横向 chrome(PLAN_TEXT_INSET 35)· 钉值承接:paper-asset-overflow / paper-v3a 拟策测高数字不变(mock 与宽度无关,措辞「条目」→「markdown 体」);token 审计零悬空 · 规格书 §4 拟策行 + 石青用例同步(README/tokens.css/design tokens.css 注释同改)· 门禁:tsc 0 / biome 改动面 0 / 定点 7 文件 140 用例绿 / 全量 vitest 279 文件 2803 passed 4 skipped 全绿 - 2026-09-10 · **设置面板两场景材质统一(用户报「首页开设置 vs 工作区开设置视觉不统一」——排查定案:实现违背立法,非新拍板)** · 病灶:文档级真纸材质(body::after 纹理 9998 + body::before 帘纹/顶光/边沉)在画布态整体退役(2026-09-02 贴纸纹理归属批:fixed 不动之纹出卖拖动空间隐喻)——但退役判据只看 `.pp-root` 在不在,**工作区里开设置时纸壳仍挂载**,全屏模态被连坐剥光:首页开设置 = 纸纹+帘纹+光效的纸感面板,工作区开设置 = 光秃平色板——同一面板两副面孔 · 立法核对:规格书 §10 法则 4 归属三条原文「首页/**面板**照旧」——面板态本就该有材质,实现漏了「画布+模态叠加」态 · 选:**模态豁免**——设置遮罩元素在场(面板 unmountOnClose,开=在/关=无)即恢复文档级材质两条规则;id 特异性 (1,0,1) 压画布态退役 (0,1,1),无需改 JS/加类 · 弃:命令面板/牒卡同款豁免(命令面板是几秒即散的瞬时层,材质归属其下画布;牒卡是局部浮卡画布仍可交互——都不构成「模态改观感」的条件,待用户真机反馈再议);JS 侧给 body 加态类(纯 CSS :has 判据已足够,幂等且零接线)· 钉值 paper-visual-decisions +1 用例(模态在场 display:block + 三件齐回 + 画布退役本体不动)· 规格书 §10 法则 4 补模态豁免注记 · 门禁:tsc 0 / biome 0 / 定点 57 用例绿 - 2026-09-10 · **新建卷两问(用户报「新建卷的视角导航有问题」+「新建卷的会话流区在第一句话输入之前的位置不对」——同一次新建卷操作线上的两个独立病灶)** · 病灶一(视角导航):`flyToRegion` 的**守卫读 canvas-store、目标读 regionsRef**——落位 effect(useRegionPlacement)与 pendingFocus effect(usePaperFocus)在同一提交内先后跑:落位先写 spread(真位置 = 视口中心最近空位),随后 flight effect 的守卫因此放行,但 regions memo 是本提交**渲染期**快照,新卷此刻还没有 spread → `defaultRegionFor(i)` 网格占位(本例 (3120, 0) 而真位置 (4000, −1200))——视角飞向「卷不在那儿」的网格点,且那次假飞行收尾会把 pending 清掉(不再补飞)· 病灶二(流区位置):`let top = 0; for (…) top = Math.min(top, g.y)`——0 是「无块」的哨兵初值,零块卷却把它当 regionTop 用 → 纸面钉在 **世界原点**(`top = regionTop − folioH`)而非锚点:新建卷摊开时纸画在别处,首句落墨 regionTop 变首块顶才跳回锚点——用户看到的正是「第一句话之前位置不对」· 选:**两读同源**(flyToRegion 只读 `getCanvasStore().spread`——流区位置唯一真相;`flyToPoint` 增可选 anchorX,目次带/键盘/书脊调用面不变)+ **空卷有几何**(无 flow 块 → regionTop = anchorY − `EMPTY_REGION_CONTENT_H`(paper/space 单一真源,200),空卷 extent 兜底同源改 `anchorY − EMPTY_REGION_CONTENT_H`)——空卷也是一张贴在锚点上的纸,与首句落墨后的几何同族 · 弃:落位 effect 提前到 flight effect 之前(挂载序注释已声明 C1 必须先于 viewport 的冷启动兜底 effect,链式前移是拆东墙); regions memo 里读 store(渲染期读外部可变源 = 另一类不纯,且 stub 命中判断也要跟着改);给飞行加延迟/重试(掩盖定序问题、放大抖动)· 语义澄清:R1「真位置守卫」保留且更严——护栏是**别飞虚构几何**,不是「别飞新卷」;落位在同提交内已完成,视角本来就该直接到真找位 · 钉值 `tests/paper-new-volume.test.tsx`(1 用例,挂真 PaperPanel 走「新建 → requestFocus → 飞行结束」全序,双断言:视角中心 = spread 真锚点 + 空卷纸面 top/height 绝对值含 folioH);**测试侧发现**:jsdom 的 rAF 时间戳与 `performance.now()` 不同源(实测回调 137ms vs now() 1885ms)→ 飞行动画 `t=(now−t0)/240` 恒负、视口逐帧反向外推且 pending 永不清,本测以确定性同源 rAF 替换(Chromium 两者同源,真机无此问题)· 门禁:tsc 0 / biome ci 0/0 / build 绿 / convergence 通过 / 全量 vitest 278 文件 2813 passed 4 skipped - 2026-09-10 · **expand 悬空定位收口(新建卷两问批的连带清理:先前只在回复里列为残留,本条落账)** · 病灶:`space.expand` 对不存在的卷(已删/墓碑/坏档)读完盘仍无条件 `requestFocus`——失败卷永远不进摊开集,`pendingFocusId` 于是**永不兑现也永不自清**,只能靠用户平移/滚轮顺手清掉;调用侧(SessionSidebar 行点击、PaperPanel 案头签条架)还各自无条件补一次 `requestFocus`(同一病灶两份),且「已摊开卷要飞」这件事被拆在两个调用点里各写一遍 · 选:**收口到 expand 一家**——`loadSessionFromDisk` 返回「是否已在案头摊开」(`Promise`,false = 文件缺失/墓碑/读失败/代际丢弃;已摊开幂等分支返 true),`expand` 依此**成功才发定位**,同时把「已摊开 = focus + 飞」也收进 expand(单一权威入口);调用侧删掉各自的 `requestFocus` · 连带:`onNew` 建卷失败(无工作区)时旧实现会照读 `activeIdx` 对**上一个活跃卷**发起一次无意义飞行——改为案头卷数未增则不定位 · 弃:只删调用侧、保留 expand 内无条件 focus(失败路径仍在);给 pending 加超时自清(掩盖「请求发得太早」的真因,且超时后目标若真出现反而丢失定位)· 语义澄清:失败已由 `loadSessionFromDisk` 弹「案卷文件读取失败」可见,收口只是**不发必然落空的请求**,不是吞错 · 钉值:paper-space +3(读盘失败不留 pending/成功发 pending/已摊开 = focus+飞)、session-sidebar-ux +1(行点击三态:失败无请求、成功有请求、摊开行聚焦+定位);红证已验(源文件 stash 掉 → 三例红,`expected 9 to be null` 即悬空形态)· 门禁:tsc 0 / build 绿 / biome ci 0/0 / convergence 通过 / 全量 vitest 278 文件 2817 passed 4 skipped - 2026-09-14 · **目次带 v3:从「滚动条」到「识别面 + 目次」(用户两问:①「标题栏的操作范围和目次带的鼠标操作范围打架了」②「合卷之后书脊这个地方会出现 UI 跳变」;修完第一问后用户续问「目次带的问题还是没有完全解决……现在感觉其实就是个滚动条,但看 VSCODE 的那种 minimap 其实接近另一种东西了」→ 当日拍板方向「丙:甲 + 乙」)** · 病灶(实机 CDP 实测,用户当卷 289 刻痕 / 带高 1096px):**① 越界**——刻痕盒 `top = stripY − 4`(盒高 8、刻位居中)使最上一枚刻痕落在 y=52,顶进书眉(=窗口标题栏,`-webkit-app-region: drag`)拖动带 4px:那 4px 命中归标题栏=拖窗口,点刻痕点不中、视觉还被书眉压掉半截;**② 命中面挤爆**——289 枚刻痕全做成 button 命中盒(10×8),tool 刻痕 255 枚把 18 枚阶段锚挤进平均 3.8px 间距(262 对相邻间距 ≤4px、4 对完全同 y),命中盒相互叠压、DOM 后渲染者胜: **点自己那枚只有 7.3%**(268/289 被相邻刻痕盖住)——用户读作「刻痕点不中」,且 289 个 tab 停靠点是键盘灾难;**③ 读不出信息**——每块一根 1.2px 首行细条(DENSITY_BLOCKS 降级)在长卷里退化成等距点阵纹理(实测空行率 0.39–0.81),整体读作「滚动条」 · 用户用途排序(本批定优先级):**① 精确跳到某一轮/阶段 ② 连续控制 ③ 一眼扫读概览**;VSCode minimap 的「另一种东西」= 识别面(map)+ 装饰层,与滚动条(control)分家 · **甲(已落地 b774f4c1):可点层与装饰层分家**——①**阶段锚=带内唯一可点目标**:消费既有 `buildStageAnchors`(阶段 = user 单元,与流的阶段间距/细线同真源),朱砂横规 + 28px 命中盒(热区纪律 ≥24px;高度与组件 `STAGE_HIT_H` 单一真源、测试对拍),盒宽只占左缘栏 26px(带右侧留给连续 scrub),点击 = flyToPoint 飞到该阶段首块, **按下锚不启动 scrub**(两个落点不抢同一根指针);②**装饰刻痕退为纯扫读信号**:惰性 div + aria-hidden + CSS `pointer-events:none`(不是点击靶、不再是 tab 停靠点;点它 = 点带空白 = 按位置 scrub);③**映射区顶内缩刻痕半高**(`STRIP_TOP = TOC_TOP + MARK_HALF`)——带内一切(墨迹/刻痕/滑块/未读/hover 索引)共用此几何真源,无一元素越界到书眉带,且 `onPointerDown` 带外一律不响应(旧行为实测:坞下装饰带一点把画布 panY 从 1580 拽到 90285);④**hover 卡与命中盒同源**(卡片所示即点击所得:锚盒内「阶段 N · 首句」→ 贴刻痕读那枚并提墨一档(替代已不可达的 `:hover`)→ 行盒原文);连带删 `nearestAnchorAt` 旧兜底分支与 `.pp-toc-mark:hover` 死规则 · 弃:把刻痕命中做「最近邻 + 阈值」补丁(治标——289 个靶挤在 3.8px 上,再准的判据也点不中; 职责分家才是正解)、hover 卡 clamp 进书眉带(卡片 pointer-events:none,非操作范围,暂不动) · **乙(待定档):识别层的物理下限 + 四个正交通道**——带内缩放比 0.005–0.012(长卷 10 万世界 px → 528px 带),15px 字 = 0.08–0.18px 高,**真字形必然不可辨**(v2 退回 bar 的原始理由);能携带信息的只有四个正交通道,值由原型逐案实测(`prototype/toc-thumb-ab.html`,同数据同几何五栏并排 + 跨栏红线读数):**形状**(行宽剪影:空行率 0.39→0、墨覆盖 0.44→0.77,与基线 α 差 0.35)/**族色**(人=朱砂、正文最重、程文与工具=石青、图表最轻、错=--fail:同形、rgb 差 0.086)/**族纹**(表横纹、码细横、图点阵、工具斜纹:墨覆盖 0.77→0.68、α 差 0.21–0.32——灰度也成立)/ **墨量**(形+深浅:α 差 0.05–0.12)——四通道可叠加,终态预计 = 形状 + 墨量 + 族色/族纹择一;**淘汰案(同尺子判死)**:缩进剪影(缩进 19 世界px = 带内 0.2–0.6px,与形状案像素差 0.001)、阶段分带(阶段界已由可点层承担,差 0.003 = 纯重复)——通则:**凡小于带内 1px 的世界结构一律不可辨**,识别层设计尺度以此为准 · 钉值:新增 `tests/stage4-toc-stage-anchor-layer.test.tsx` 五例(旧实现 5/5 红 → 新实现全绿:刻痕是惰性 div + aria-hidden + 带内 button 只剩锚、按下锚不 scrub、点装饰不跳转但照旧 scrub、CSS 契约 `pointer-events:none` + 命中盒高对拍、hover 卡同源)+ `tests/stage4-toc-titlebar-band.test.tsx` 两例(旧实现红:`expected 52 to be greater than or equal to 56`——与实机量到的 52/56 逐像素对上;带外按下把 panY 拽到 2000)· 规格书同步:新增 §13 目次带 v3(用途排序 / 病灶实测 / 四层职责分离表 / 乙 的四通道与淘汰案) · 门禁:tsc 0 / biome ci 0/0 / build 0(产物重建并拷入运行中 exe 的产物源供热重载)/ 全量 vitest 295 文件 2995 passed 4 skipped - 2026-09-14 · **目次带 v3 乙落地(F:形状 + 墨量 + 族色 + 错)——原型定档**(用户看原型 `prototype/toc-thumb-ab.html` 后一字拍板「F」) · 提案面:原型六栏同数据同几何并排(A 基线 v2 / B 形状 / C 族色 / D 族纹 / E 墨量 / F 合成预览)+ 跨栏朱砂红线读数 + 真字形对照组;**淘汰两案(同一把尺子判死)**:缩进剪影(缩进 19 世界px = 带内 0.1–0.6px,与形状案像素差 0.001)、阶段分带(阶段界已由可点层承担,差 0.003 = 纯重复)——通则:凡小于带内 1px 的世界结构(缩进/块间留白/单行折行)一律不可辨 · 选:**F = 三通道一锅出 + 错另立**——纯层 `src/paper/toc-ink.ts`(`buildTocInkBuckets`,零 DOM:桶高 `TOC_INK_BUCKET=3px`、alpha = `0.18 + 0.82×√(桶内墨面积 / 全带最大桶面积)`、 **a 桶内最宽行定宽并定族色**(形状行=你看得见的那根,它决定「这是什么」)、错旗 = 桶内任一行属 `deriveMarks` error 集);组件(TocStrip canvas effect)只做三件事:行盒→桶输入(`rel/right/area/kind/err`)、逐桶 `fillRect`(族色走 `inkBarColorOf`——墨色真源仍在 `paper/ink.ts`)、错桶另立 4px `INK_FAIL` 短规(错是语义状态,不参与墨量深浅——最响的一档) · 支点:**桶是带内唯一诚实的竖向原语**——带内缩放比常见 0.005–0.012,行距/缩进/块间留白全在 1px 之下,逐行直画即糊;v2 的「每块首行一根 1.2px 细条 + `DENSITY_BLOCKS` 降级」在长卷里退化成等距点阵(实机空行率 0.42–0.81 = 用户读作「滚动条」),本批**整段拆除**(常量、降级分支、`inkColorOf` 依赖一并退役) · 通道取值(原型实测,长卷 90 屏 / 30 阶段 / 235 块 / 10 万世界px / 带高 528 / 缩放 0.0052):形状使空行率 0.42→0、墨覆盖 0.41→0.77; 族色与形状同形但 rgb 差 0.086–0.11(**只看 alpha 会误判「没差别」**——读数须分 alpha/rgb 两轴);墨量 α 差 0.05–0.12;族纹(D)墨覆盖 0.77→0.68、α 差 0.21–0.32(**未采纳**:F 已在族色上答了「这是什么」,纹样留作灰度/打印后备) · 接线纪律:走宿主桥三处(`compose-dock/host.ts` + `host.aliased.ts` + `builtin/host-modules.ts` faceDeps)——`INK_FAIL` / `inkBarColorOf` / `buildTocInkBuckets` 三件同批在册;`INK_FAIL` 是 `tokens.css --fail` 的 TS 字面量镜像(canvas 取不到 CSS 变量,语义状态色必须有 TS 真源) · 钉值:新 `tests/stage4-toc-ink-layer.test.ts` 八例——形状(最宽行定宽 + 定形行定族色)/墨量(宽块恒深于窄块、最密桶 α=1、下限 0.18)/错旗(传播 + **不参与深浅**:同宽同面积桶 α 相等)/**差分断言**(同数据 v2 规则覆盖 9% vs 新算法 ≥80%、空行率 0——算法退化即红,已用「把桶高改成 1.2px」实测:三例红、还原即绿)/几何界(所有桶落在 `[stripTop, stripBottom]`,越界行不产桶=不越进书眉带/坞下装饰带)/桶序(乱序输入 → 竖向输出);`tests/paper-ink.test.ts` 补 `INK_FAIL` 镜像 + `INK_BAR_COLORS` 族色真源两例 · 规格书 §13 同步「乙已落地(F)」段 · 门禁:tsc 0 / biome ci 0/0 / build 0(产物重建并拷入运行中 exe 产物源)/ 全量 vitest **296 文件 3005 passed 4 skipped**(首跑唯一红 = `notes-app-example` 进程握手用例在全量并行下 5s 超时;单跑 1.7s 绿、复跑全量绿——负载抖动,非本批) - 2026-09-14 · **目次带下移批的两个尾巴 + 载体缓存事故(用户二报「标题栏还是和目次带打架」→ 整体下移;实机验收连抓三处)** · ①**带体整体下移**(弃"靠 z 序遮盖"改结构性修法):CSS `.pp-toc { top: var(--bar-h) }`——带体**从书眉(=窗口标题栏,-webkit-app-region: drag)下缘起**,与标题栏零像素重叠;组件几何随之改**带体坐标**(映射区顶 = 刻痕半高 `STRIP_TOP = MARK_HALF`,映射区底 = 画布区高 − 坞抬高 − 坞高);hover 卡补翻转(`cardAnchorFor`:hover.y < 40 改挂红线下方——否则贴顶 hover 时卡片上半越出带体、压住标题栏的设置/回首页/窗口钮,z 80 > 书眉 z 30);书眉高三处同源钉死(tokens.css `--bar-h` = 组件 `TOC_TOP` 字面量镜像 = CSS `top: var(--bar-h)`) · ② **阶段锚命中盒越界**(实机验收当场量到 `pageTop=47 < 56`):锚盒 28px 以刻位为中心,贴顶时越出带体 → 新增 `anchorBoxTop()` 夹到 ≥ 0(规线在盒内居中,最多 14px 视觉偏差——位置读数本就由墨迹缩略承担);修正后实机 **95 个子元素零越界**、y ≤ 55 命中归标题栏 / y ≥ 56 归带体、贴顶卡片 pageTop = 70(翻转态)· ③**载体缓存事故(排查一小时的真根因)**:产物经 `127.0.0.1:14570` HTTP 通道装载,而 Rust 资产服务(`plugin_assets.rs::asset_response`)只发 content-type + CORS、**无任何缓存指令** → WebView2 把 `entry.js` 当可缓存资源**跨重启复用**,「改插件 = 换产物秒级生效」静默失效。实机铁证链:磁盘产物已换 → 页面内 `fetch` 同一 URL 拿到新内容(`clamp=true`)→ 运行中的模块仍是旧的 → 重启后依旧旧(页面 `performance.timeOrigin` 证实是新实例、webview 进程确为新起); 修法 = 该响应加 `cache-control: no-store` + Rust 用例 `asset_response_disables_caching` 钉住(本地文件读取廉价,不依赖 validator) · 教训(并入 §8.5 保险丝家族):**热更承诺有两条隐性前提**——a) 宿主面未变(同日 a′ 指纹闸),b) **载体不吃缓存**(本条);两条都缺作者期/装载期信号时,症状都是"改了没反应",且都长得像我代码写错了 · ④排障副产物:`cargo tauri build` 报 `os error 32(文件被占用)` 的持有者是**我自己启着的 lantai.exe**(AGENTS §10 只记了 rust-analyzer 一例——构建前先停应用) · 钉值:`stage4-toc-titlebar-band.test.tsx` 五例(CSS `top: var(--bar-h)` + 三处字面量同源 / 刻痕与滑块 top ≥ 0 / 锚盒夹紧(`anchorBoxTop(5)=0`、`(100)=86`)/ 卡片翻转 / 带体顶与坞下带按下不响应)——旧实现 4/4 红(含 `expected 60 to be 4`),新实现全绿;`plugin_assets` 新增一例(三态响应都必须带 no-store) · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest **3011 passed 4 skipped** / cargo test **457 + 集成 1 全绿** / exe 重建(`cargo tauri build --no-bundle`)后实机验收全绿 - 2026-09-14 · **标题栏触发范围收归应用自管(app-region 全面退役)——用户三报并直指根因**(前两报我修的是"目次带这一侧":带体下移 + 锚盒夹紧 + 卡片翻转,都没治到病;第三报用户明确「问题是出在标题栏的触发范围上」) · **根因(实机取证:`WindowFromPoint` + 对归属窗口发 `WM_NCHITTEST`;中途两次被前台其它窗口污染——量到的其实是 Chrome 的 caption,已重测)**:拖动区 = WebView2 宿主把页面 `-webkit-app-region` **光栅化的一叠薄子窗**(实测 44 个 `Chrome_WidgetWin_0`:y 0-12 / 12-14 / … / 56-58 / 58-63 / 63-88),每个无条件回 `HTCAPTION`;页面渲染窗从 y≈88 起才是 `HTCLIENT`。这叠**只在宿主初始化那一刻按当时页面算一次、永不重算 **——启动落在首页 → 按首页 `.sh-head`(~88px 高)算,进画布视图于是:① 多出 88px「幽灵标题栏」压在画布顶缘与目次带最上方(在那段里拖内容=挪窗口,即用户报的 bug,实测复现:拖 (2528,60) 窗口从 -8,-8 变成 1553,117);② **书眉里的按钮(缩放/设置/回放/窗口钮)按首页布局被 caption 吃掉**(实机真点缩放钮零反应)。旁证:改 `--bar-h: 30px` 带仍到 88(非元素高度派生)、全删 app-region 带也不消;`no-drag` 的挖除**只对拖动元素的后代生效**(窗口钮正是如此),对书眉以下的兄弟元素无效 · **修法(两层,缺一不可)**:**①前端不再声明任何 app-region**(书眉 `PaperPanel.css` / 首页 `foundation.css` / `shell.css` 的 wc-btns no-drag 全撤——不声明就不产生行窗)+标题栏交互收进新模块 `src/app/window-drag.ts`(单一真源,书眉与首页共用:pointerdown → Tauri 原生 `plugin:window|start_dragging`、双击 → `toggle_maximize`,交互件 button/input/`.wc-btns`/`.sl-root` 豁免; 首页原 Linux-only 兜底与手写 IPC 一并收编)——命中范围恰好是标题栏元素本身;**②壳层兜底** `src-tauri/src/window_drag_band.rs`:常驻轮询给 `Chrome_WidgetWin*` 子窗挂 `SetWindowSubclass`,`WM_NCHITTEST` 里 `HTCAPTION` 一律降为 `HTCLIENT`(`HTTOP/HTLEFT/HTBOTTOM…` 不动 = wry 无边框边框调整照旧),纯函数 `clamp_caption_hit` 带 Rust 用例;Cargo 加 `Win32_UI_Shell` · **走过的弯路(已全部回退,勿重走)**:给书眉以下各面加 `no-drag`(对兄弟元素无效,且实测把书眉自己的拖动带一起挖穿=整窗拖不动)、在整窗容器上 `no-drag`(同样挖穿)、只删 app-region 不接管拖动(窗口钮立刻被 caption 吃掉) · **行为变更(用户可感知)**:标题栏拖动/双击最大化改由应用原生命令驱动(仍走 OS 拖动循环,Aero Snap 保留);书眉按钮在画布视图恢复可点;目次带最上方与画布顶缘不再挪窗口 · **实机验收**(真输入 + `GetWindowRect` 前后对比 + 真点按):拖书眉→窗口移动 ✓/拖目次带最上方 (2528,60)→**不移动** ✓/拖画布顶缘 (1000,70)→**不移动** ✓/首页顶栏拖动→移动 ✓/真点书眉「缩小一档」→ 82%→75%(按钮复活)✓ · 钉值:新 `tests/titlebar-drag-region.test.ts` 四例(全仓样式零 app-region 声明/两个标题栏都接共享实现且不各写一份 IPC/共享实现走原生通道+交互件豁免+宿主桥三处在册/壳层兜底与 Rust 用例在册)+ Rust 两例(caption 全高度降级/其余命中不动);宿主面基线随本批更新(338d1411 → d60a1d57——**作者期闸当场提示「本批需重建 exe」,正是它该说的话**) · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest **3015 passed 4 skipped** / cargo test **459 + 集成 1 全绿** / exe 重建(`cargo tauri build --no-bundle`)后实机验收全绿 - 2026-09-16 · **卷首「版心天头」重排(用户定题「会话的卷首太丑了怎么办」→ 一次性原型台四案 → 用户拍板 B 案)** · **病灶(不是审美分歧:2026-08-30「自原型转录」时把版心丢了。读真源 + 实测四证)**: ① **一块卷首三个轴**——玉徽 `margin:0 auto` 居中于**整张纸**(默认 1440 宽流区的中轴 x=720,恰好压在 720 版心的中轴上), 眉行/题字/档行却左齐于纸缘内距 `padding-left:16`(比正文块左缘 360 还左 **−344px**),而正文块居中于 720 版心; 组合芯片同病,`top:16/right:18` 贴纸缘、离版心右缘 **+326px** 孤悬(与居中的玉徽成对角)。 原型里 `.folio` 整个就是一根 560px 窄栏(`prototype/lantai.html:180-195`)——「居中钤印 + 左齐文字」在栏宽 528 时只错 ~250px 故读作手势; 搬进 1440 宽流区后无人重建版心就散架。**宽度相关**:流区缩到下限 720 时三轴自动合一(实测偏差 0)——所以是「宽卷才犯的病」,而默认落位宽正好 1440。 ② **卷号说三遍**:眉行「兰台 · 案卷 Nº 12」+ 题字 fallback「案卷 12」+ 档行「案卷 #12 · N 块」。 ③ **档行丢了日期**:原型是「二〇二六年八月廿二日 · 案卷 #12 · 8 块」,移植成「案卷 #12 · N 块」——原因可查:`RegionView` 只带 sessionNum/label/blocks,**卷首拿不到任何时间字段**。 ④ **字体换代没跟着重调**:2026-09-10 三体换代后 song/kai/mono 三键同值 = MiSans 单族,原型层级原本靠「等宽小字 vs 宋体大字」的**族对比**扛, 现在只剩字号/字重/字距,而卷首仍沿用原型的等宽参数(10px + `.26em` + ink-3 48% alpha,在纸纹上就是一行又小又散又淡的灰字)。 · **选(B 案 = 版心天头)**:保留原型「钤印居中于天头」的手势,改**居中于版心**——内层盒 `width: min(720px, 100%)` 承载 玉徽 26px / 眉行 11px·`.34em`(居中天头比左齐需要更松的机读感,故字距反是**加宽**;补同值 `text-indent` 修掉末字字距带来的视觉左推)/ 题字 36px·1.22 / 档行 11px·`.18em`(**立卷日 · N 块**),四行同轴居中;硬规线与朱砂版口钮一并移进内层(只画版心宽,钮挂规线左端)。 **卷号在卷首恰出现一次**:有名卷在眉行、无名卷在题字 fallback(眉行退为「兰台 · 案卷」文类行)。芯片改以**版心**为参照系(`top:1px/right:0`,仍绝对定位、不进高度流水)。 · **立卷日数据面**:`ChatSessionMeta` 新增 `createdAt`(起卷 = 当场时刻;摊开磁盘卷 = 卷日志头行 `createdAt`,与投影缓存 `savedAt`「最后落盘」是两回事,不混用), `RegionView.createdAt` 透传;中文数字长日期格式化落**插件本地** `paper-shell/folio-date.ts`(不进 `src/paper/`——档行文案是 paper-shell 自己的呈现面; 且插件取宿主面必须走 `./host`,本地模块免开新宿主面键、不动 host-surface 基线指纹);旧卷无 createdAt ⇒ 档行只显块数(不编造)。 · **连带清理(同批,授权范围内)**:① 修**测高镜像的行为 bug**——`measureFolioHeadHeight` 入参从「题字可用宽」改为「**流区宽**」, 左右内距 16×2 与 720 版心封顶在函数内一次算清;旧调用点手写 `anchor.width - 32`,宽流区下漏掉封顶(默认 1440 实得可用宽 1408 → 长题字永不换行、实测卷首高恒等于一行, 与实际渲染的换行长期不符);② 修**字重漂移**——`FOLIO_TITLE_FONT` 写 `600` 而 CSS 写 `700`(拍板 B 四级 = 卷首 700),测宽与渲染不同源,已对齐; ③ 清 stub 卷首高魔数 `72` 改真测高(缩到视口外的卷回场时纸的上缘会跳,且远档地志标签锚点 `regionTop − folioH` 在 stub 与非 stub 卷之间不一致)。 · **弃**:A 案「归版心」(玉徽与眉行并作一行、左钤右字——更省、卷首高降 23px,但丢「钤印居中天头」的仪式感); C 案「去装饰」(砍玉徽与「兰台 ·」、档行升 kicker 置题字之上——最省最不易再歪,但丢玉徽);四行改左齐版心(原型手势是居中天头,不退回)。 · **钉值(故意规格变更,显式声明)**:`tests/paper-visual-decisions.test.ts` 卷首 describe **整体改写**,并从「只钉 4 项 token」补成 **CSS ↔ FOLIO_TOKENS 全项对映**(旧测漏钉 eyebrowH/subH/padBottom/yuweiH/titleMarginTop/subMarginTop 六项——改了没人拦); 新增 `tests/paper-folio-height.test.ts` 五例**行为测**(版心封顶 / 窄流区退为 streamW − 32 / 换行真的计入高度 / 单行总高 = 固定结构 + 一行 + headGap) ——源文本钉值 + 行为面两条腿,补上「钉值全绿而行为错」这个最坏情形(本批修的两条 bug 正是这一类); 新增 `tests/paper-folio-date.test.ts` 六例(规格源原值「二〇二六年八月廿二日」为黄金用例 + 本地时区不漂天 + 坏值不编造); `tests/paper-new-volume.test.tsx` 一例随签名改(`placed.width - 32` → `placed.width`)。 · **洞见(供后续批次)**:① CSS 注释里写完整选择器子串会撞钉测 `ruleBody` 的 `indexOf`(2026-09-02 坑记档同源;本批避让法 = 注释只写「玉徽/眉行/题字/档行」中文名与带 ` {` 的完整选择器,不写裸 class 名); ② **几何契约的镜像若由调用点手写派生式(`width - 32`),必然漂移**——收进被测函数内部才是单一权威源;③ 「源文本钉值」只能证字面量没被偷改,证不了行为——配一条行为测才闭环。 · 一次性原型台留在 `prototype/folio-head-ab.html` + 读数栏 + `folio-head-ab.NOTES.md`(prototype/ 已 gitignore,不入库) · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest **3230 passed 3 skipped** / vite build 通过 - 2026-09-17 · 坞位 · 用户提问「创作坞能不能做成可以拖动的」→ 四问自裁(坞位归属槽主人 / 让位带取代坞高上报 / 抓手 = 书眉行 / 自由浮动 + 吸附 + 双击复位)· **选**:坞位成视图偏好(`localStorage lantai.composer.pos`,null = 无覆盖 = CSS 版心居中坐底)、坞书眉行为抓手(交互件自己接手势)、拖动全程磁吸四锚位(左右缘 / 版心中轴 / 经典底带 96 / 最底缘)、双击坞头复位、让位带 `--composer-band`(视口底 → 坞顶线)驱动四家消费面重算; **弃**:坞位入工作区画布状态(视图偏好不是工作区数据,同小地图 pref 族);给 PaperDockContext 加回调让坞自报坞位(坞本体该一字不知——事件冒泡到槽、槽主人接手势,宿主面 faceDeps 基线零动,产物仍可只换产物);拖动期 `preventDefault`(会连带影响 dblclick 跨引擎互操作,复位手势优先;防误选交 `user-select:none`)。 · **拆账**:旧 `--composer-h-live`(坞自报坞高:ComposerDock 的 ResizeObserver + 两处 CSS 消费)整条拆除——让位带是槽主人的几何,一处权威源,浮动态才正确;**但外壳 CSS 内嵌在 exe 里不能热更**(`shell.css`/`plugin-windows.css` 仍读旧 token),故过渡期由槽主人代发旧 token 一版,**拆除条件 = 下一次整包重编**(一般教训:删跨层 token 必须与消费它的那一层同批落地)。 · **零漂移证据**:默认位带 = `--composer-rise + 坞实测高`(与旧配对式逐字同值 ⇒ 目次带映射区/可见域、小地图默认位、递牒卡、插件 dock 四处默认外观零改动);两个 toc 测试只改字段名 + 数值表达式,**断言数字逐字未动**。 · **边界(刻意不做)**:让位件之间互不躲让、坞不自动躲让位件(坞拖到上半屏时让位件停在半屏 = 让位带上限 55vh / 目次带封顶 3/4 可视高);坞不做边框吸附动画;坞头不加一次性眉批提示(grab 光标 + 用户已知)。 · **交付形态**:只打三个产物热更(compose-dock / paper-shell / paper-minimap → `target/release/_up_/src-ui/dist-plugins/builtin/hologram/`),不重编 exe(app 在跑)。 · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest **3275 passed 3 skipped** / build(含 30 产物)/ doc-check 全绿 - 2026-09-17 · 坞位修订(用户三条实机反馈,**翻案注明理由**)· ① 目次带不让位 · ② 拖动与划词打架 · ③ 加拖动锁(用户方案:桌面歌词式)· **① 翻案**:上一批让「四家消费面全按坞的实际位置让位」,用户裁「目次带似乎没必要做让位」——**选**:目次带只按**出厂底带**(96 + 坞实测高)算映射区/可见域,坞拖到哪都不压缩导航带(坞是用户自己摆的浮窗,导航带不该跟着缩);**弃**:目次带跟随坞位(过度让位——平白把导航域交给一个用户自己摆的东西)。口径分家落地为 `composerDock: { bottom, height }` 原样下发,让位带(小地图/CSS 让位件)与出厂底带(目次带)各自派生。 · **② 冲突根治(两层)**:坞上按下会带出**原生选区**,而纸上挂着 document 级 `selectionchange`(`use-paper-strips` 的选中浮钮)→ 拖坞 = 纸上划词 + 浮钮乱冒。**锁定态**坞是普通 DOM(不接手势,冲突不可能发生)+ **解锁拖动期** `` 挂 `pp-composer-dragging` 全页禁选并清既有选区(松手即撤)。 · **③ 拖动锁(用户方案,桌面歌词式)**:坞顶外缘一枚 hover 浮现小钮(文案 = 点下去会发生什么:`移` ↔ `锁`,同「拟文/停」单钮语言;浮在坞顶外缘故不进坞布局流、不撞翰/律)——**默认锁定**(坞对鼠标零响应:不改光标、不接手势、划词照旧 ⇒ 同时根治「谁都不知道这东西能拖动」与误拖);解锁后**整坞**(除交互件)是抓手 + 全坞抓手光标 + 锁钮常显;锁态落 `lantai.composer.unlocked`。坞顶之上预留 26px(`COMPOSER_PILL_H` 入上夹紧),免得坞拖到最上时小钮压进书眉。 · **实现纪律**:锁与手势仍全归槽主人(paper-shell 的 composer-float/use-composer-float),坞本体(compose-dock)一字不知 ⇒ 宿主面 faceDeps 基线零动,本批仍是**只换三个产物**热更。 · **钉值**:新增 `stage4-toc-titlebar-band` 用例「坞浮起不让位:坞位变→刻痕逐字不变,坞高变才动」;`paper-composer-float` 扩到 7 例(默认锁定不可拖 / 点解锁 / 整坞起拖 / 拖动期禁选类 / 锁态持久 / 交互件不起拖);`composer-float` 扩到 19 例(拖动面判据·锁定态一律 false / 锁记忆毒化容忍 / 上夹紧含锁钮占位)。 · **踩坑记档**:新写的高基数选择器(`.pp-composer-slot.pp-composer-unlocked .pp-composer input` = (0,3,1))会把文件后面三条低基数 input 细规罩死——biome `noDescendingSpecificity` 三连警告;**子选择器一律裹 `:where()` 归零基数**(既压过坞体继承规则,又不遮蔽后续细规)。 · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest / build(30 产物)/ doc-check 全绿;交付 = 三个产物热更(exe 不重编) - 2026-09-17 · 拖块边缘自动滚屏(用户报「从会话拖出块钉在画布上,要挪到很上方/很下方,只能拖一下→滚→再拖」,点名「有没有玩过 RTS」)· **病灶**:拖块跟手只吃 `mousemove`——视口不动,块影永远落不进当前视口之外,远距离移位退化成「拖→滚→再拖」的循环。同一张画布上,拖选早在 2026-09-07 就有边缘自动滚屏(`autoPanVector`),**拖块域没接**——不是新能力缺失,是同类手势只接了一半。 · **选**:**RTS 缘滚同族**——指针进视口四缘 36px 感应带(含越出画布:`autoPanVector` 越界封顶 1.5×)即每帧平移视口,**指针静止在带内也持续滚**(常驻 rAF 循环,回带内自然停摆),块影每帧钉回指针下;曲线与带宽**复用 `canvas-math.autoPanVector`**(拖选自动滚屏同一真源、零新参数);拖块起手 = **手动接管视口**(取消在途定位飞行 + 清挂起定位,与滚轮/拖画布/缩放同纪律——否则在途飞行跟手抢 pan)。 · **弃**:给拖块另立一套滚屏参数(两条曲线各自漂,迟早手感分家);用闭包 `view` 算块影与落点(滚屏期间 pan 每帧变 ⇒ 块影脱手、松手钉跳位);把 `view` 留在 effect 依赖里(平移每帧换值 ⇒ 每帧重建 effect,cleanup 会把滚屏循环掐断)。 · **连带(同源收口)**:拖拽域 effect 依赖表去掉 `view`,块影与**松手落点一律读 store 现值 view**——落点与块影必须同一把尺子;拖动期滚轮平滚造成的脱手一并治好(任何 pan 源都被同一条帧循环复位)。 · **边界(刻意不做)**:纸条拖拽 / 流区移位 / 宽度手调未接(本批只用户点名的拖块;同族手势若要,复用同一循环即可,勿各写一套)。 · **钉值**:`tests/paper-viewport-ux.test.tsx` +2(贴下缘:指针静止也滚 + 横轴未入带不动 + 松手钉落在块影处;已钉块贴上缘:一次手势把钉挪到很上方)。**反证已验**:拆循环 → `expected 0 to be greater than 60` 红;滚屏但不跟手 → 落点差 46/150px 红(容差 30 = 至多两帧滚屏量)。测试用**等待式**攒滚屏量(rAF 帧数随机器负载浮动),不对速率下断言。 · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest **3284 passed 3 skipped** / build 绿;宿主面 faceDeps 零动(`autoPanVector`/`useCanvasViewStore` 早已在册)⇒ 无需重编 exe,产物域只 paper-shell 一件 - 2026-09-17 · 拖动锁二版(用户打回一版:「太难看了」+「hover 之后点不到,鼠标还没挪过去就消失了」)· **一版病灶(我的设计缺陷,非实现 bug)**:把锁做成「槽里浮在坞顶外缘的 hover 小钮」——① 钮浮在坞**外**、与坞之间有缝 ⇒ **揭示靠悬停坞体、命中又得靠已揭示**(互为前提)⇒ 指针一离开坞体钮先消失,再挪过去就没有东西可点;② 浮方块自带纸底+细框,与坞的语言(翰/律 纯文字)不合 ⇒ 丑。 · **二版选**:**归坞的书眉工具行**——`.pp-dock-tools` 第三枚 `.pp-tool-btn`(`移` ↔ `锁`,排 翰/律 之前,那一对内容入口保持相邻),**常显可点、零悬停机制**,样式与翰/律 同款(纯文字 / hover 朱砂 / 选中 `.open`);上夹紧随之回到「书眉 + 屏缘」(不再为浮钮预留 26px)。**弃**:脱盒浮现(揭示与命中互为前提必死锁)、给锁钮单独造视觉(坞已有工具语言,别发明第二套)。 · **归属变化**:锁态与写面仍归槽主人(paper-shell),坞经 `PaperDockContext.composerLock` **能力位**渲染那枚钮(宿主不给 = 整枚不出现,只重载单个产物的偏斜窗口不炸——能力位纪律同 token 账本「不实现 = 无读数,不炸链路」)。宿主面 faceDeps 基线仍零动 ⇒ 仍可只换产物。 · **教训入册**:**控件的悬停揭示区必须与它的可见区同盒**;否则「揭示」与「命中」互为前提。宁可常显(翰/律 一直就在那),不做「脱盒浮现」。 · **钉值**:`composer-dock-header` +2(能力位:给了才渲染 + 移/锁 文案与 aria-pressed 与 .open 选中态 + 点它只回调不自己写;不给 = 整枚不出现);`paper-composer-float` 假坞照能力位渲染同款钮(端到端考「锁定不可拖 → 点解锁 → 整坞起拖」)。 · 门禁:tsc 0 / biome ci 0/0(本批文件)/ 相关 7 个测试文件 57 例全绿 / 干净 worktree 全量 + build - 2026-09-17 · 拖块松手判据重写(用户实机报「从会话流里拖一个块出来,暂时不松手直接挪视口,挪到位置之后松手,被拖动的块并没有出现并钉在我想要的位置上」——上一批边缘滚屏放开手感后,**旧判据的两个病灶从「偶尔」变「必现」**)· **复现(jsdom 真实 PaperPanel 穿全层,非推测)**:拖块(原位)→ 指针进下缘带滚屏 70px → 松手 ⇒ `pins = []`、无钉块、无 ghost——落点被当「回槽」**静默取消**。 · **病灶(一条判据,两处)**:旧判据 `|落点左缘 − 流区中轴| ≤ 400`,纵向无界。① **横向不对称**:720 宽的块,左缘要在中轴 ±400 内 ⇒ 块中心向右得跑 760px 才算带外,而向左只需 40px——**往右拖到纸外的桌面上松手仍判「回槽」而静默取消**(用户报的正是此路);② **纵向无界**:横向在带内时纵向往哪拖都算回槽,沿同列滚到纸外松手同样被取消。 · 附一条隐性裂缝:渲染面的「回槽预览态」(`pp-drag-returning`)当年**另自算一套**(`|dragX − 中轴| ≤ 400`)——视觉与规则各说各话(预览态与松手判据同源于「带」但不同式子,判据一改必分家)。 · **选**:判据改为据**来源原位**量(「回槽」的语义 = **放回原来那一格**,不是「落在带里」)——横向偏移 ≤ **自身半宽**、纵向偏移 ≤ **2 个块距档**;**渲染面预览态与松手判据共用同一函数** `blockReturnsToFlow`(视觉与规则一把尺子,此不变量入册)。 · **弃**:据「纸」量(块中心在窄带内 ∩ 块顶在纸上下缘之间)——会话长时同列滚到半途仍在纸上 ⇒ 用户场景照旧被取消(等于没修);且**眉批撕出族的原位在正文右缘外的眉批栏(世界 x≈384,本就在纸外)**,据「纸/带」量会让「拖回眉批栏 = 取消」失效(据原位量同时治好这桩)。 · **连带**:来源卷找不到(`region` 缺)时不再判回槽——判据立不住就别静默吞掉用户的落点,落钉可见可收回(错误不静默);渲染面不再自算 band(少一处漂移源)。 · **钉值**:`tests/paper-viewport-ux.test.tsx` +4(判据纯函数矩阵含眉批原位 / 向右搬出半宽 + 滚屏 → 落钉在块影处 / 同列纵向搬离 + 滚屏 → 落钉 / 眉批撕出:拖回原位 = 取消拔钉、搬远 = 落钉);早前两例的坐标按新语义重挑(旧坐标踩的是旧判据的不对称)。**反证已验**:函数体改回旧公式 → 4 例红(`expected undefined to be truthy`)。 · **教训入册**:**判据要据「用户语义的原位」量,不要据「抽象几何带」量**——带是原位的代理,代理一旦被放开的手感(滚屏/远距)拉开距离就失真;且**任何「预览态」必须与「落定判据」共用同一函数**,否则假绿灯出现在用户眼前。 · 门禁:tsc 0 / biome ci 0/0(794 文件)/ 全量 vitest **3291 passed 3 skipped** / build 绿;宿主面 faceDeps 零动 ⇒ 仍可只换产物(paper-shell 一件) - 2026-09-17 · 坞底 / HUD 化 · 用户提「创作坞透明常与画布文字重叠,要不要做 HUD(非激活全透明)」→ **用户看过诊断后裁定「先不动吧,不是什么问题都必须要去解决的」**——本条只记病根与配方,本批不做工;日后翻案从这里取。 · **病根(不是透明度问题)**:`.pp-composer { background: transparent }` 是 2026-09-01「退匣」拍的,当时理由是坞还占一条**全宽布局行**、带底色像屏底死带;**同日坞已改浮层**(不占布局流)⇒ 那条理由**当天即失效**,而底色没跟着回来 ⇒ 画布正文与坞内文字同纸叠字。再调透明度救不了:透明 = 两层墨互糊,不是「不重叠」。 · **备而不做的配方**:① 回底 + `backdrop-filter: blur()`(玻璃语言仓库已有先例:命令面板 `.pal-box` 的 `--glass-hi` + `blur(16px) saturate(1.15)`)——「背后糊、前面锐」才是 HUD,也是唯一真能消灭两套字打架的手段;② 非激活**降档**淡出(有下限 ~50%,不归零),且**草稿非空 / 流式运行中 / 聚焦一律不淡**;③ **全透明那一档判死**——读数/草稿/控件消失,与拖动锁一版「看不见就点不到」同族。 · **若日后翻案,注意**:坞是插件产物(paper-shell / compose-dock),改它照样可以只换产物热更,不需重编 exe。 - 2026-09-17 · 边缘滚动立为原生功能(用户:「这个所谓的边缘滚动系统,我能不能正经把他做进软件,我觉得还挺好用的,在设置页放一个开关,放一个灵敏度调节」)· **前史**:同日两批先把它从「拖块域自写一条 rAF 循环」补齐,又发现拖选域**另有一整套**——本批正式收成子系统,不再一处一手感。 · **选**:`plugins/builtin/paper-shell/edge-scroll.ts` 单点三件事——① **策略**(基准带宽 36 / 限速 26 / 灵敏度区间 0.5–2.0、缺省 1,唯一真源);② **设置订阅载体**(挂载读一次 + 保存广播重读;手势帧只读 ref,不当场 JSON.parse);③ **帧循环 hook** `useEdgeAutoScroll`(起手势给「取指针 + beforePan/afterPan」,松手即撤)。曲线仍是 `canvas-math.autoPanVector`(纯几何,早已收显式 band/maxSpeed 参数)。 · **灵敏度语义**:一个滑杆 = **整体强弱**——滚速线性(× sens)、感应带宽温和同向(× √sens),即「越灵敏 = 起滚越早 + 滚得越快」。两轴分开调会做出「一碰就滚但很慢」这类错位手感,故合成一档;带宽/限速的绝对值仍是代码常量(要改手感改那一处,不动 UI)。 · **接入面(三族手势)**:拖块/钉块/眉批(use-paper-drag)、拖选文字(use-paper-viewport)、拖纸条 + 抽纸条 lift(use-paper-strips)全改吃同一循环。**beforePan / afterPan 分两口是刻意的**:拖选要「先延后滚」(延伸读已提交布局,与旧 tick 同序),块影/纸条影/ghost 要「先滚后复位」(按新 pan 才不脱手)。 · **顺带收口**:纸条域两处**闭包旧 view** 病灶(`toWorldInCanvas` / 纸条影)改读 store 现值——滚屏期间否则 ghost 与落点算的是虚构世界点(与拖块域同族,见上批判据条目)。 · **设置面**:`settings.canvas.edgeScroll = { enabled, sensitivity }`——**不设 DEFAULTS 值**:旧存储无此字段 = 读侧兜底「开 + 1.0」(与面板显示口径一致),写侧只在用户动过之后才落字段;面板位置 = 设置 → 显示 → 画布(开关 + 滑杆,复用 sp-checkbox-label / sp-slider-row 既有控件语言,零新 CSS)。 · **弃**:策略常量留 `paper/canvas-math.ts` + 新宿主面出口——那会改 host-surface 指纹 ⇒ 产物拒载、必须重编 exe;而 `autoPanVector` 早已收显式参数,策略落插件域即可换手感,**宿主面零动**(两产物 face.json 与运行位逐字节同源,已对拍)。面板滑杆的 min/max 与缺省是两个**展示**数字(跨插件不可 import——插件自包含契约),越界值由读侧夹取,故两处同改。 · **连带修复(同节病灶)**:设置面板「滚轮行为」原来**整体替换** `canvas` 节 ⇒ 一改就把刚存的 edgeScroll 抹掉;改为展开既有节(考官:改滚轮行为后 edgeScroll 仍在)。 · **钉值**:`tests/edge-scroll.test.ts`(策略读面 3 例:缺省 / 开关 / 映射与夹取)+ `paper-viewport-ux.test.tsx` +4(开关关掉:不滚但落钉判据不变 / 灵敏度行为面:同一入带深度 0.5x 不起滚·2.0x 起滚 / 拖纸条:滚屏 + 松手写回滚动后世界位 / 抽纸条:滚屏 + ghost 跟手 + 成条)+ `settings-panel-save-split` +2(面板写面 / 同节字段不互冲)。 · **反证已验**:策略忽略设置 → 开关与灵敏度两例红;抽纸条、拖纸条各自拆接线 → 对应例红(`expected 0 to be greater than 60`)。 · **测试侧硬教训(记档)**:假选区的 `removeAllRanges` 原是**空实现**,而真机 lift 揭起会清空选区(拖选自动滚屏据此自动解除武装)——空实现让两条路径同时滚,探针因此给出假绿灯;已把假选区补成忠实行为(清空后 rangeCount/isCollapsed 真的变)。 · 门禁:tsc 0 / biome ci 0/0(796 文件)/ 全量 vitest / build(30 产物)绿 ⇒ 交付 = 热更 paper-shell + settings-domain 两个产物(exe 不重编) - 2026-09-17 · 悬停即滚(边缘滚动第二批;用户:「诶,等一下,边缘滚动既然都做了,为什么不支持直接滚动视口」——即「**视口自己滚,不必先按住一个块**」,RTS 相机标准形态)· **选**:同一子系统加 `useHoverEdgeScroll`(挂载点 = 视口域):指针停在画布边缘(入带驻留 120ms)→ 视口自己滚;策略/曲线/灵敏度/总开关与拖拽族**共用**,不另立一套。 · **三处刻意差异**(都不是疏漏,是两类场景的差别):① **只在画布内滚**——拖拽族允许越出画布继续追(1.5× 封顶),那是「把手里的东西带出去」;悬停族照办就成「跟随相机」(指针挪去侧栏/书眉,画布永远滚不停)。② **任一鼠标键按下即让位**(`e.buttons !== 0` 拒判 + 捕获面 mousedown 立即 disarm)——拖拽手势自带循环,两套同时跑 = 双倍速;按下键那一刻的语义本来就是「我在操作内容」而非「我在挪镜头」。③ **交互面之上不滚**(创作坞/目次带/小地图/按钮/输入件/纸条/宽度柄/角柄/文类签)——否则想点按钮、想在输入框打字,画布会自己跑掉;**`.pp-block` 刻意不豁免**(RTS 的镜头就是贴地图边缘走,纸面即地图)。 · **入带驻留 120ms**:悬停族没有「按住」这个显式意图,用驻留补上——路过边缘(例如去点创作坞)在 3–5 帧内穿过感应带,驻留足以过滤;真停下要滚的人感知不到这 0.12s。 · **默认关(本批唯一的关键取舍)**:画布铺满正文,「读的时候把鼠标停在屏底」是极常见姿态,默认开会让内容自己跑掉——故 `edgeScroll.hover` 缺省 false,设置面板第二枚勾选(总开关开着才露出),与「用户知情开启」配对;这也是它和拖拽档(缺省开)口径不同的原因。 · **顺带回答另两种读法(免去用户再问一轮)**:拖拽途中**直接用滚轮滚视口**本就可用,本批补上考官(拖拽中滚 240px 视口、块影不脱手、松手落点仍 = 块影处);**中键/空格拖动平移**未接(要就说,十行内)。 · **钉值**:`edge-scroll.test.ts` +1(悬停档缺省关 + 毒化值不静默开);`paper-viewport-ux.test.tsx` +5(悬停滚:无按键也滚 / 离开边缘即停 / 缺省关同姿态不滚 / 交互面之上不滚 vs 纸面上滚——同一姿态 A/B / 按住键让位;另有滚轮直滚视口 + 块影不脱手一例)。 · **反证已验**:悬停钩子不挂载 → 两条正例红(`expected 0 to be greater than 40/30`);豁免表恒不匹配 → A/B 例红(`expected 542 to be 600`)。 · 门禁:tsc 0 / biome ci 0/0(796 文件)/ 全量 vitest **3306 passed 3 skipped** / build(30 产物)绿;宿主面仍零动 ⇒ 仍只热更 paper-shell + settings-domain 两产物(exe 不重编) - 2026-09-17 · 悬停档**缺省开**(用户实机报「好像没生效呢?」——**我的判断失误,不是实现 bug**)· **实机取证(CDP 只读探针,脚本留档 `D:\tmp\lantai-probe\cdp-probe*.mjs`)**:① app 跑的就是我那份面板——设置 → 显示 → 画布确有那两枚开关,`拖拽到边缘时自动滚屏` checked=true、`指针停在边缘也滚(无需按住)` **checked=false**;② `localStorage.hologram_settings.canvas` 只有 `{wheelMode:'pan'}`——**`edgeScroll` 字段压根不存在** ⇒ 这两个开关**从未被保存过**(面板是手动保存制,勾了不点保存不落盘);③ 产物通道(127.0.0.1:14570)服务的 `entry.js` 与我的热更产物 hash 逐字节相同 ⇒ 产物确实在用(加载器 DEV=false 走磁盘通道),「没生效」不是交付问题。 · **翻案(缺省关 → 缺省开)**:首版把悬停档判为缺省关,理由是「画布铺满正文,读的时候鼠标停在屏底会让内容跑掉」;实机结论是**这个理由的代价远小于「用户根本发现不了功能」**——而且该档的误触面早被三处约束压住(画布外不滚 / 按键让位 / 交互件豁免 + 入带驻留 120ms)。故 `edgeScroll.hover` 缺省改为开(`raw?.hover !== false`,与总开关同口径:毒化值也按开),开关保留——不想要的人关掉即可(面板文案同步改为「不想要就取消勾选」)。 · **连带(实机几何取证)**:**目次带整条豁免 = 右缘永远不滚**——实机量得 canvas 宽 2560(右带 2524–2560)、目次带 2496–2560 整条压住;改为**只豁免卡片按钮**(`button` 本就在豁免列),带上的墨迹/缝照滚(「贴右缘滚一眼标记往哪走」正是导航带该有的用法,而瞄准卡片时不会滚)。**创作坞 / 小地图整块豁免保留**:实机量过二者都不压任何感应带(创作坞坐底带之上 96px、小地图亦在带上)⇒ 零代价、且都是「瞄准面」。 · **判据抽纯函数** `hoverEdgeEligible`(hook 与考官共用同一函数)——防止上一批「预览态与落定判据各写一套」的同族裂缝再现。 · **钉值**:`edge-scroll.test.ts` +2(判据两例:正文/画布内可滚、画布外不可滚、目次带容器可滚而卡片豁免、纸条豁免 / 开关·悬停档·按键三处约束)+ 悬停缺省口径改写;`paper-viewport-ux` 的「缺省关」例改写为「缺省即生效(不需要任何设置)」;`settings-panel-save-split` 口径改(缺省全开 → 显式关得掉且落盘)。 · **教训入册**:**默认值也是产品决定**——「把风险交给默认关」在小众开关上成立,在用户点名要的能力上等于没做;判断依据应该是「误触代价 × 可撤销性」对「发现成本」,而不是单看误触。 · 门禁:tsc 0 / biome ci 0/0(796 文件)/ 全量 vitest **3308 passed 3 skipped** / build(30 产物)绿;宿主面零动 ⇒ 仍只热更 paper-shell + settings-domain 两产物(exe 不重编) - 2026-09-17 · 右缘悬停不生效(用户:「右缘这边还是不生效,没那么复杂,目次带有这么宽在这里,为什么非要考虑目次带呢,还是说你的边缘触发区域非常的宽」——**用户的追问是对的,真病灶在更底下一层**)· **实机逐点取证**(CDP 只读探针 `cdp-probe7.mjs`:`elementFromPoint` 逐点 + 合成 mousemove 后读 `.pp-world` transform): 右缘 y 取中,x = 2555 / 2540(距右缘 5 / 20px)命中 **`nav.pp-toc` 本身**(不是卡片)→ 视口**不动**; x = 2520(40px)命中 `button.pp-toc-anchor`(卡片)→ 不动;x = 2495 / 2470 / 2430(65 / 90 / 130px)命中正文 `p.pp-md-p` → 不动(**这三处是正常的**:带宽只有 36px,2524 才进带); **对照组**底缘 x=400 → **动了**(⇒ 悬停档本身工作正常,缺省开也生效)。 · **真病灶(不是豁免列表,是我判据里的硬条件)**:`hoverEdgeEligible` 要求「指针底下的元素属于 `.pp-canvas`」——而**目次带是 `.pp-root` 下的覆盖件,压根不在画布 DOM 里**(probe 链:`nav.pp-toc → div.pp-root → body`)⇒ 把鼠标贴到屏幕最右(真机就是这条带)一律判「不在画布上」✗。上一批我改的「不整条豁免目次带」因此完全是空转——**改错了层**。 · **选**:**贴边浮件视为画布本体**(`HOVER_ALLOW_DOCKS = '.pp-toc'`)——目次带是贴边 64px、属画布边缘的一件,不是「别的面板」;它上面的**卡片是 `button`**(已在豁免列)⇒ 瞄准卡片时不滚(卡片随世界滚动,一滚就点不中),而带上的墨迹/缝照滚(用户贴屏最右的操作正落在这段)。画布外的**其它**宿主/弹层仍不滚(设置面板/递牒卡/插件窗——它们盖住画布时不该让画布在背后乱走)。 · **判据不再据「DOM 包含」而据「画布本体 ∪ 贴边浮件」**——DOM 包含是个错误的代理:画布的可见边界不等于 `.pp-canvas` 的元素边界(覆盖件就是反例)。 · **带宽没动**(用户问「是不是你的触发区域非常宽」):仍是 36px(沿用 2026-09-07 拖选自动滚屏原值)。 · **测试侧硬教训**:上一批的纯判据把目次带**塞进 `.pp-canvas` 里**造 DOM ⇒ 用例绿灯而真机红灯(假绿);本批把合成树改成真机结构(目次带/弹层是 `.pp-canvas` 的**兄弟**,`veil` 作反例)——**造测试 DOM 必须照抄真机层级**,否则考的是一棵不存在的树。反证已验:去掉 `HOVER_ALLOW_DOCKS` 分支 → 新用例红(`expected false to be true`)。 · 门禁:tsc 0 / biome ci 0/0(796 文件)/ 全量 vitest **3308 passed 3 skipped** / build(30 产物)绿;宿主面零动 ⇒ 仍只热更 paper-shell + settings-domain 两产物(exe 不重编) - 2026-09-17 · 顶部浮件(**标题栏拆除批**)· 用户:「我做完了这个边缘滚动之后,标题栏变得很碍事,标题栏是不是可以考虑取消掉,按钮其实可以从标题栏挪出来,然后把这个标题栏删了,让上边缘滚动这个动作变得更合理一些,现在操作起来真的奇怪」· **病灶(不是手感,是布局)**:书眉 `.pp-topbar` 是 **56px 布局行**(flex 列第一行)——它把画布顶缘从窗口顶推开。而边缘滚动最自然的动作就是**把指针甩到屏顶**;屏顶那 56px 不是画布 ⇒ 悬停判据(`hoverEdgeEligible` 要求指针落在画布内)一律否掉,拖块贴顶也最多到 56。**上缘在用户视角里等于没有边缘滚动**——前两批全在调带宽/灵敏度/豁免表(都是下游),真病灶在这条布局行。旁证:测试里的 `stubCanvasRect` 一直把画布 rect 的 top 写成 0(真机是 56)⇒ 用例永远看不到这条病,**假绿一整批**。 · **选**:**书眉整条退役,控制件落成右上一枚覆盖件浮件**(`.pp-chrome`,`.pp-canvas` 的**兄弟**、不进布局流)——画布铺满整窗(顶缘 = 屏缘,四缘感应带对称);浮件内容 = `画布`(抓手)+ 缩放 −/读数/+ + 状态字 + 设置 + 回首页 + 窗口钮(**搬家不是删除**,相对次序与旧书眉一致);几何 `top 8 / height 40 / right 80`(= 目次带宽 64 + 16),带高 56 = 8 + 40 + 8;视觉 = 纸底 + 弱线 + `--elev-raise`、**不透明**(半透明会让画布正文与浮件文字互相糊字,同「坞底 / HUD 化」条病根)、**常显**(零悬停揭示);浮件兼任**窗口拖动热区**(非交互件 = `画布` 二字与件间空白,走 `app/window-drag.ts` 原生通道)。 · **弃**:① **保留书眉 + 悬停/接近自动隐藏**——指针甩到屏顶时先弹出书眉,抢的正是那个动作;且「揭示区与命中区一分开就互为前提」(拖动锁一版先例);② **顶缘留一条 8px 拖动带**(把原病灶局部复活:那片像素点下去是挪窗口,且它照样吃掉感应带);③ **把新 token 落 tokens.css**(那是**壳域**——`main.ts` 打进 bundle,改它必须重建 exe;几何留在产地域,本批才能走「改插件源码 → 构建产物 → 应用内重新加载」这条主路径,见 docs/dev-workflow.md);④ 顺手把 `--bar-h` 留成僵尸 token(已零消费面 ⇒ 删;删它对运行中的旧 exe 零影响:产物不再引用它)。 · **连带(几何同一批收口,五处)**:目次带 `top: var(--bar-h)` → `top: 0`(组件 `TOC_TOP = 0`,带体坐标 = 页面坐标,2026-09-14 那次「整体下移」随之取消);书脊架 `.sr-rack` 与案卷侧栏 `.ss-sidebar` 的 `top` → `0`(左缘整列多出 56px);一次性眉批 `.pp-hint-canvas` 从「书眉下缘 + 20」上提到「屏顶 + 20」;坞上夹紧与小地图默认位仍是 56(改称「顶部浮件带」——浮件在右上,坞压上去会把窗口钮盖死,而它是 decorations:false 下唯一关闭入口)。 · **已知代价(如实入账,用户可据此翻案)**:① 顶缘感应带在浮件占位那段 x 区间(右对齐;典型宽约 470px、最长约 560px——状态字在本批同批从 320 收到 220px,全文照旧可点开读)里不可用——浮件本体之上的悬停**不滚**(它是「别的面」,同弹层口径);要「浮件背后照滚」只需把 `.pp-chrome` 加进 `HOVER_ALLOW_DOCKS`(三行,判据已就位)。② 画布视图不再有屏级顶线(旧书眉底线是浸墨③的三处之一)——视觉上顶部不再分区,浮件走弱线 + 浮起。③ 窗口拖动只能从浮件抓(另有系统级通道:任务栏 / Win+方向键 / Alt+Space);首页顶栏 `.sh-head` **保留**(首页不是画布,没这条诉求)。 · **钉值**:`tests/stage4-toc-top-band.test.tsx`(原 `stage4-toc-titlebar-band` 改名——带体从屏顶起 + 浮件几何四处同源:CSS `8/40/80/64` ↔ 两处 TS 镜像 56 ↔ 测试基准,**由测试代行「改一处必红」**,因为几何刻意不进 tokens.css);`tests/paper-viewport-ux.test.tsx` +3(结构:书眉不存 / 浮件是画布兄弟 / 控制件一件不少;行为:**屏顶那 36px 落画布上滚 vs 同一姿态落浮件上不滚**;浮件抓手拖窗口而按钮不吃拖窗口、双击最大化);`tests/edge-scroll.test.ts`(判据合成树照真机结构加 `.pp-chrome` 兄弟项 + 新用例「上缘感应带在屏顶」,RECT top 56 → 0);`tests/titlebar-drag-region.test.ts`(`pp-topbar` 零声明 + 浮件接共享实现——**注释里的历史沿革不算声明**,判据要挑声明面);`paper-visual-decisions`(墨阶锚点:画布书眉底线退役,浮件走弱线);`composer-float.test.ts` / `paper-composer-float.test.tsx`(常量改名 `COMPOSER_CHROME_H`,上夹紧数值与判据未动);`status-line.css`(`.pp-chrome .sl-chip` 上限 320 → 220px,本批唯一为「浮件别太宽」做的收窄)。 · **教训入册**:**测试里的几何替身必须与真机一致**——`stubCanvasRect` 把 top 写成 0 而真机是 56,于是「上缘边缘滚动」这条真病在两批测试里都不可见;**布局行是功能性家具**:一条 56px 的 flex 行足以让一个功能的整个方向失效,而它在截图里只表现为「一条正常的标题栏」。 · 门禁:tsc 0 / biome ci 0/0 / 全量 vitest / build(30 产物)绿;宿主面零动(faceDeps 无增删)⇒ **交付 = 热更产物**(paper-shell / compose-dock / canvas-nav / paper-minimap / settings-domain),exe 不必重编 · **交付踩坑(用户当场报「热重载根本没生效」——我的错,全部记档入 landmine 第九批 H1/H2/H3)**:① `npm run build:builtin-plugins` 只写 `src-ui/dist-plugins/`,而**运行中的 release exe 只认它的资源根** `target/release/_up_/src-ui/dist-plugins/builtin/hologram/` ⇒ 必须逐文件拷过去(对拍口径 = SHA256;实测拷前通道给的 `entry.js` 仍是含 `pp-topbar` 的旧 hash 61B3613A…、拷后 = 含 `pp-chrome` 的新 hash 5476698218…)——`docs/dev-workflow.md` 原三步漏了这一步,本轮已补;② **本批是 CSS 大改,而 CSS 根本不在热更面上**:产物域那句 `__LANTAI_FACE_ARTIFACT__` 判定因 esbuild define 未命中而恒早退(实测 `link[id^="lantai-plugin-css"]` 计数 0)⇒ 插件 CSS 只经 vite 进**壳 bundle**,**任何 CSS 变更都必须 `cargo tauri build --no-bundle` 重建 exe**——我先前写的「不必重编 exe」对 CSS 是错的(只改 TS 的历史批次看不出来)。⇒ **交付口径订正:本批 = 重建 exe**(关掉兰台后 `cd src-tauri && cargo tauri build --no-bundle`) · **实机验收(CDP,脚本 `D:\tmp\lantai-probe\cdp-probe8…15.mjs`)**:重载窗口 + 进入画布后取证——`hasTopbar=false`、画布 `rect.top=0`(旧为 56)、浮件 `{position:absolute, top:8px, right:80px, height:40px, 宽 500px, 纸底+弱线+elev-raise}`、`chromeInsideCanvas=false` 且 `chromeSiblingOfCanvas=true`、目次带 `top:0`、书脊架 `top:0`、状态字 `max-width:220px`;**真输入**(`Input.dispatchMouseEvent`)指针置屏顶带内 y=18 → `panY 195792 → 196858`(**上缘悬停滚动生效**,即本批要买的行为)而同一姿态置浮件中点 → `panY` 不变(浮件豁免),指针收回画布中部即停。取证用的一张临时注入 link 仅为当次观感(见 H2),**正式交付仍是重建 exe** - 2026-09-17 · **回锚认卷 + 失联即收**(用户报「自从做了这个边缘滚动之后,偶发画布纸面不加载,啥也不渲染」;问「什么时候空白」→ 用户答「**进了工作区 / 按了回锚就空白,没做任何动作**」——这一句把主凶从「滚飞」改判到「落点」)· **取证链(CDP 只读探针 18–29,脚本留档 `D:\tmp\lantai-probe\`)**:① 现场在跑:`.pp-world` 的 transform 一路跑到 `translate(2798, 84010)`,而**卷内容在 world y ≤ -28,630**(sid 1 流区盒 [-143,832, -28,630])⇒ 屏幕上一块都没有;② `canvas.json` 里 view 与三卷锚点:`panY=84010`(我还用探针推到过 224,011),`spread` 三卷 `anchorY ≈ -28,700`;③ 按 Home(真键盘事件经 CDP 送不到,改用页面内合成 `KeyboardEvent` —— 应用**确实处理**了:`defaultPrevented=true`)后视口世界区间 = `[-2045, 151]`,`blocksInView=0` ⇒ **回锚自己就落在空白**;④ 定量:指针停在屏顶带内 **1,444 px/s 线性无衰减**(10s = 14,443px)⇒ 约 50–70 秒可把视口送出全部内容;⑤ 排除崩溃:把视口推到 `worldTop=-351,256`,`.pp-canvas/.pp-world/.pp-desk` 全在、零异常(只是空地);⑥ 真凶落定:`viewForAnchor` 只收视口宽高,把**世界 (0,0)** 对到屏幕锚位——而卷锚是**最新块底边**(流向上长),用户三卷都已漂到 -28,700 ⇒ 按原点落锚 = 停在卷外 28,700px。 · **选(V1 主修)**:落位/回锚**认卷锚**;**回锚(Home)与首屏落位**一律传**活跃卷锚**(裁决序 = 活跃卷 → 首个摊开卷 → 世界原点=旧口径兜底);回锚另与滚轮/缩放/拖拽**同纪律**:先取消在途定位飞行 + 清挂起定位(否则飞行会覆盖回锚)。**算式落点(交付路径倒逼的决定)**:`paper/canvas-math.ts` 属**壳域**(产物域经宿主桥 `mods.faceDeps` 取它)⇒ 改它必须重建 exe,而当时**另一个窗口正在同一棵树里改 `src/agent/**` + `src-tauri/src/cdp*` + `Cargo.toml`(17:07–17:13 在途)**:重建 exe 会把他在途代码一起编进去(且可能编不过)。故算式落**产地域**纯函数 `plugins/builtin/paper-shell/landing.ts::panForAnchor`(与壳域同式),本批**只换产物**即生效;代价是两处同式,由**跨域对拍**兜住:`tests/paper-landing.test.ts` 把「锚在原点」这一档与 `canvas-math.viewForAnchor` 逐值比对(漂了就红)。 · **弃**:给 Home 另立「回原点」双键(用户要的是「看得见我的卷」;方位感仍可靠平移获得);改壳域 `viewForAnchor` 的签名(对,语义上更该这么做——但本批交付路径不允许,见上;**同日技术债批已把它反向结清**:壳域那份 `viewForAnchor` **作为死抽象删除**(唯一生产调用者就是刚改掉的落位),落位语义此后只在 `landing.ts` 一处——不必再等重建 exe)。 · **选(V2 顺手拆)**:失控滚屏的兜底提到**四族共用的那一层**——`useEdgeAutoScroll` 加 `blur` / `visibilitychange(hidden)` / `document.mouseleave` ⇒ 立刻停帧循环(悬停档早有同一纪律,拖拽族一直缺)。**弃**:只在四个手势钩子里各加一遍(同一纪律写四遍=迟早漂)。**未修的一半**:失联后手势本身仍挂着(拖块停在拖拽态)——另立一笔,不在本批。 · **用户裁定(2026-09-17,当场拍板)**:两条**都不做**——原话「这两个遗留不管了,没必要」。残留行为如实记在 landmine 第十批 V3/V4(含候选修法),日后要改不必从头查。 · **如实入账(未修,已裁定不做,见上)**:① **野视口会被持久化**(`canvas.json` 里出现过 84,010 / 224,011;恢复优先于落位 ⇒ 下次进来还是空白);② **悬停档没有尽头**(1,444 px/s 一路滚到卷外,即使 mouseup 没丢也如此)——两条都属产品取舍(要不要「恢复时判无卷则回锚」/「滚到内容边界即停」),留档待你拍。 · **钉值**:`tests/paper-viewport-ux.test.tsx` +3(⑨ 回锚认卷两例:**卷锚 -28,700 时 Home 之后必须看得见卷**——修复前红,报的就是用户症状「视口世界区间 [-704, 96] 内一块都没有」;卷锚在原点时与旧口径一致 / ⑩ **拖块到带内后只发 blur、不发 mouseup ⇒ 必须停滚**——修复前红 `expected 392.0 to be 553.8`);`tests/paper-landing.test.ts` +3(纯数学:与壳域旧口径逐值对拍 / 卷锚贴下缘上方 margin / 用户现场 -28,700 在旧口径下被推出 12 屏外)。 · **教训入册**:**「锚」是一个会漂的语义,不是一个常量**——卷锚随内容向上长,任何「按原点算落点」的旧口径都会随卷长而腐坏(本次腐坏到 28,700px)。**同族的交付纪律**:一个改动落在壳域还是产地域,直接决定「能不能只换产物」——壳域改动在**同树多窗口并发**时会互相绑架(本批被逼把算式下沉到产地域,就是这条的实例)。 · **门禁 / 交付**:tsc 0 / biome ci 0/0(800 文件)/ 相关 4 个测试文件 50 例绿 / 产物重建绿;**交付 = 只换产物**(`paper-shell/entry.js` 拷入 exe 侧资源根,face.json 未变=94 键、宿主面零动,故 exe 不必重编、也**没有**碰他窗的在途 Rust 代码) · **实机终验(重建产物后启动兰台,CDP 探针 `cdp-verify-home*.mjs`)**:进工作区(活跃卷 sid 5)→ 合成 `keydown(Home)` → 活跃卷最新块底边距**视口下缘 97px**(设计值 96px,误差 1px)、可见块 **3** 个(修复前同一现场:Home 之后视口世界区间 `[-2045, 151]`、可见块 **0**)⇒ 症状不再复现。附带须知:**全量 vitest 有 3 例红,全部来自他窗在途改动**(`event-catalog-doc`:他窗 `src/agent/**` 行号漂移 / `request-images`:他窗 `request-images.ts` 改到一半 / `seam-contract-version`:契约指纹未更新)——我已把误 regen 的两份生成物(`docs/agents/event-catalog.md`、`open-surface-contract.md`)回退,**那三例的绿灯归他窗**(他们 commit 前要跑 `npm run gen:catalogs:event` + `npm run gen:contract-fingerprint`) - 2026-09-17 · **选区政策全局化:默认不可选,正文自证可选**(用户报「有太多不该触发文字选中、划词操作的地方并没有做对应的处理,导致很多地方的操作不顺手」)· **病灶(结构性,不是某一处漏了)**:全仓 16 份 CSS 只有 8 条 `user-select`,且全是「谁出事谁补一条」——坞拖动期 / 纸条 / 小地图 / 书脊行 / 插件窗题条各写一次。补一处漏一处:拖动扫选、双击选词、Ctrl+A 把整壳收进选区在**其余所有面**上照旧发生;而纸上挂着 document 级 `selectionchange`(选中浮钮 + 划词朱线),任何一次扫选都可能唤醒画布上的划词动作。审计另抓出一条结构事实:`.pp-chrome` / `.pp-composer-slot` 是 `.pp-canvas` 的**兄弟**(不是后代),旧 `.pp-canvas{user-select:none}` 从来就没覆盖过它们——「逐面补」这条路本来就走不通。 · **选(语义反转)**:**界面是界面,不是可复制的文档**——`html` 默认 `user-select: none`,放开面收成两处:① 输入件(`input/textarea/select/[contenteditable]`,祖先 none 会连坐表单件拖选);② 正文容器自持 `.pp-block{user-select:text}`。块内**结构件/交互件**另立一条 `:where()` 收族撤回 none——旧账是逐类枚举,漏网实证:`.pp-resize` 宽度手调柄、块内 `button` / `summary` 全在枚举外。连带拆除 5 个文件里被取代的逐处补丁(含 `html.pp-composer-dragging` 的全页禁选——成了空操作,规则撤、类保留服务抓手光标)。 · **选(第二道守卫:起手面判据)**:`user-select:none` 只挡「从该面起选」,挡不住「按住家具扫进纸面」——浏览器把选区锚点**夹到最近的可选内容**,家具起手的拖拽在锚点上与真划词无法区分(本仓自己的实测在 paper-minimap 的 preventDefault 注:拖小地图会选中画布文字)。**弃**「给 7 个拖拽面逐个补 preventDefault」(审计建议的路子):那会顺带掐掉 mousedown 的 focus、与 dblclick 跨引擎互操作打架(坞那边已有入册教训),且散成 7 处迟早早漂。改在**一处收口**:纸壳 capture 面记「本次按住是否起于 `.pp-block`」,浮钮与划词朱线共用该判据;块内输入件(准奏卡意见框)另由 `isEditableSurface` 挡。**例外一处(补了 preventDefault)**:插件浮窗题条(`PluginWindowFrame`)——它是**页内**拖动(mousemove 移 DOM),指针会横穿纸面,是审计列的七个面里唯一真能扫过整张纸的;其余六个要么走 Tauri 原生移动循环(`window-drag.ts` 的窗口拖动:OS 接管后页面根本收不到指针,扫不出选区)、要么活动范围被自身家具圈住(侧栏行 / 书脊 / 目次带 / 纸条),且划词动作已由起手面判据挡住。**代价明账**:纯键盘选区沿用「上一次按下的面」——先在块里点过即照常认,冷启动直接 Ctrl+A 不认(全选不是划词)。 · **弃**:给「可复制的信息面」(设置错误文本 / 引擎路径 / 工作区路径 / 状态日志 / 模型名)逐个放开——那是**枚举**,正是本轮要治的病;正确范式是本仓已有的「抄」钮通道(`use-block-ops` → `core.copyText` 单点),要补按钮另立一笔。**未做(如实入账)**:纸条正文仍不可选——**刻意**(整张纸条是拖拽把手,放开可选 = 按下去变扫选、纸条拖不动),理由已写进 `.pp-strip` 注;toast 不可选但 `.pp-toast-host` 是 `pointer-events:none`,鼠标本来也划不到。 · **钉值 / 门禁**:`tests/paper-viewport-ux.test.tsx` +3(划词消费面守卫考:⑪ 起手在家具上、选区锚点被夹进块内 ⇒ 朱线不落、浮钮不弹;⑫ 起手在块内、**同一选区**照常落线弹钮——两例只差「按下点在哪」,互为考官,拆掉守卫⑪必红;⑬ `isEditableSurface` 真值表:可编辑控件内(含块内输入件)为真、正文/按钮/null 为假。harness 增 `stubRangeRects`(**必须打在 `Range.prototype` 上**:消费面存的是 `cloneRange()`,实例级补丁管不着)+ `bounding` 参数(浮钮按 `rect.width > 0` 定 fabPos);踩坑一则:起手点若落在选区矩形内会武装 A 路 lift,它 `removeAllRanges()` 把选区清掉、消费面自然全空——假选区的 `rects` 不传才是「只考划词」)——全仓 `biome ci` **0/0(817 文件)** / 全量 vitest **340 文件 3464 例全绿**(含本批 +3) / `vite build` 绿;`tsc --noEmit` 尚余 3 例,全在**他窗在途**的 `src/ui/chat-session.ts`(卷名重构线 `label: string → string | undefined` 改到一半,与本轮无关——本批 8 个改动文件 tsc 零错) · **交付口径**:`foundation.css` 属**壳域**(`main.ts` 静态 import 进 app bundle)⇒ **本批必须重建 exe**,只换插件产物热更不生效(同 tokens.css 那条纪律)。 - 2026-09-18 · **窗口不记最大化 + 首页标题栏双击失效**(用户报「为什么我的软件现在不会记住窗口是否最大化,并且似乎首页的标题栏双击缩放窗口的功能也失效了」;要求只读排查)· **只读排查结论:两条症状无共同根因**。 ① **状态落盘被硬退抢跑**:`tauri-plugin-window-state` 全仓唯一的落盘点在 `RunEvent::Exit`,而壳层在窗口 `Destroyed` 里 `std::process::exit(0)`(防僵尸子进程的既定设计)——tauri-runtime-wry 的次序是「窗口监听器先跑 → 之后才 `ExitRequested` → `ControlFlow::Exit` → `LoopDestroyed` → `RunEvent::Exit`」⇒ 正常关窗**永不落盘**。三条物证互证:`.window-state.json` 只在「应用还在运行时被系统关机」的两次里、**关机那一秒**被写(09-15 04:12:24 / 09-16 18:34:49,后者与 System 日志 `1074 User32` 同秒;同一份 `ui.log` 分段显示其间十余次应用自身退出一次都没写);文件内容停在 `maximized:false` + `x/y=-8,-8`(= 最大化时的外框角位,与实机 `GetWindowPlacement` 的 restore rect 逐字段对上)⇒ 每次启动都在左上角还原成未最大化的 1000×700。**污染源在插件侧**:它的 `Moved` 监听器更新 `x/y` 时没有 `is_maximized` 守卫(`Resized` 分支有),最大化那一下的位移被当成「普通位置」记下——本仓只能靠「在正确时刻写一次」绕开,改不了上游。 ② **双击判据建在不会发生的事件上**:09-14 那批以「幽灵标题栏」为由退役 `-webkit-app-region: drag`(**那时拖动与双击都是 OS 原生行为**),改成 `pointerdown → plugin:window|start_dragging` + `dblclick → toggle_maximize`。而 `start_dragging` 是 **OS 模态移动循环**(tao `ReleaseCapture()` + `PostMessage(WM_NCLBUTTONDOWN, HTCAPTION)`)——第一下就把鼠标交出去,这一击的 mouseup 不再进页面(旁证:tao 自己在 `WM_EXITSIZEMOVE` 里补发合成 `WM_LBUTTONUP`);两次点击各开一次循环、两枚 mouseup 全被吃掉 ⇒ Blink 凑不齐一次完整 click ⇒ **`dblclick` 一次都不产生**。该批实机验收逐条都是拖动、唯独没有双击 ⇒ 回归潜伏四天。实机核对(只读探针):运行页 `.sh-head` 的 React props 两条 handler 都在(接线无误)、OS caption 带已消失(`WM_NCHITTEST` 在 y=4…700 全回 HTCLIENT)、窗口样式 `0x15CF0000` 带 WS_MAXIMIZEBOX(**不是样式问题,是消息到不了**)。 **选(①)**:`CloseRequested` 分支显式 `save_window_state(StateFlags::all())`——那一刻窗口还活着(几何与最大化态都读得到),且三条关窗路径(窗口钮 / 前端 `watchWindowClose` 拦截后 destroy / 系统关窗)都先经过它;`Destroyed` 的硬退一字不动。**弃**:(a) 在 `Destroyed` 里补保存(那一刻 HWND 已销毁,`update_state` 读 `is_maximized/inner_size/outer_position` 会 `?` 掉整次保存);(b) 拿掉 `exit(0)` 让事件循环自然收尾(语义更正规,但牵动既定设计,收益与风险不成比例);(c) 每次 move/resize 落盘(写放大,本仓不需要)。 **选(②)**:**双击由 `pointerdown` 自己数**——同点位(±6px,对齐 OS 的 `SM_CXDOUBLECLK`)+ 450ms 窗口内的第二下 = 双击 → `toggle_maximize`,且**第二下不再进 OS 拖动循环**(否则拖动与最大化互相打架);`onTopbarDoubleClick` 保留为「页面收得到 dblclick 的平台」的**同一对点击去重兜底**(两条路只算一次)。判据收在 `app/window-drag.ts` 单一真源,两个标题栏接线与宿主面三处导出**一字不动**(宿主面零动 ⇒ 基线免重生成,也不动 `PaperPanel.tsx`——他窗当时正在改它)。**弃**:(a) 壳层放开 caption 让 OS 接管拖动+双击(正是 09-14 因幽灵带退役的形态,且实测当前 WebView2 下页面收不到 caption 命中);(b) `start_dragging` 改「移动超阈值才交给 OS」(更接近原生,但 dblclick 仍不来,替代不了自数);(c) 两处各写一份判据(第三份真源)。 **钉值**:新增 `tests/titlebar-gesture.test.ts`(9 例 jsdom 行为考:单击=拖 / 双击=最大化恰一次且第二下不再拖 / 慢于窗口=两次单击 / 位移超容差=两次单击 / 三击不连判 / 交互件整对豁免 / **两条路只算一次** / dblclick 单独到达仍成立 / 无 Tauri 运行时安全)——**旧实现下 3 红 6 绿**(实测:红的是三条新契约,绿的是不许变的行为,形状 = 整增而非改造);新增 `tests/window-state-persist.test.ts`(3 例源码契约钉值:插件在册 / CloseRequested 落盘且失败可见 / Destroyed 仍是硬退);`tests/titlebar-drag-region.test.ts` 头注改述 + 2 例钉值。旧用例零改动(`paper-viewport-ux` 的双击例照旧绿:dblclick 单独到达时兜底生效)。 **未实测的一环(如实入账)**:真机「第二下 pointerdown 会不会真的送进页面」属 OS 消息层,jsdom 够不着;本仓押「第一下能进 = 第二下也能进」(今天的拖动就靠 pointerdown 工作)。真机验收清单:最大化 → 关窗 → 重开仍是最大化(并看 `.window-state.json` 的 mtime 是否随每次关窗前进);首页与画布顶栏真双击最大化;真拖动仍跟手;真单击不最大化。 **交付口径**:① 在壳域(`src-tauri/src/main.rs`);② 的判据 `app/window-drag.ts` 亦属壳域(`SessionsHome` 静态 import 进 app bundle)⇒ **两条同一批、必须重建 exe**(关掉兰台后 `cd src-tauri && cargo tauri build --no-bundle`)。 - 2026-09-18 · **出处引导:钉住块的「从哪来」**(用户报「这些块没有一个视觉引导——拖下来之后完全不知道这东西从哪来;会话流中的占位不在视口里,根本起不到任何引导作用」)· **机理(现象背后两条)**:① 流自锚点**向上**生长(`layoutFlow` 自底向上累积、最新块贴锚点、`regionTop` 单向增负)⇒ 洞随新墨越漂越远,而钉留在原地;② 渲染按视口窗口化(`visibleFlowWindow`)⇒ 洞不在视口里时**连 DOM 都不存在**。「从哪来」于是没有任何可见答案——用户那句「占位不在视口里」正是第二条机理。 **选(两条腿 + 一个手势)**:**出处行**(页边注第三行「摘自 卷名 · 状态字」,**常显**——出处是页边注的本职「这条注疏对着哪段正文」,且常显 = 不依赖任何视口内目标)+ **引线**(hover 钉块 → 世界坐标朱砂发丝直线,钉缘接洞缘;**洞离屏时线照样出屏 = 方向即来路**;一屏一线防面条)+ **溯源**(点出处行 → `flyToPoint` 落洞中线 + 洞点名一拍,1.6s 自散)。状态字四态:活钉无字 / `不在卷内` / `未摊开` / `已删`(**已删不可点**——不发起必然落空的定位/摊开,2026-09-10 收口纪律)。 **弃**:(a) 常显引线(钉多即面条,先看 hover 档够不够用);(b) 反向引导(流内洞位标「已钉在画布」+ 一点飞到钉——对偶方向,用户没提,留后手);(c) 出处行另立浮件(层次法:签条族住纸内件档,页边注就是它的位置);(d) 卷名实时向磁盘要(要异步,还要为已删卷兜底——建钉冻结与 `snapshot` 同一条「公共物不连坐」语义即够)。 **卷名权威链**:活卷读活卷名(`r.label`)→ 孤儿钉读建钉时刻冻结的 `pin.source.label`(可选新字段,旧 `canvas-pins.json` 照读)→ 档号兜底(`volumeDisplayName`,禁调用点散写)。超长卷名在**纯层**截断(10 字 + …,状态字不受截断影响)。 **引线选边**(净空优先):洞全在钉左 → 钉左缘接洞右缘;全在右 → 钉右缘接洞左缘;**横向相叠** → 两侧都取左缘(相叠时洞的右半被钉盖住,指向它等于没指,故线往左出去、不横穿钉身)。 **连带修(同批查出,非本功能)**:飞行动画**混钟**——`flyToPoint`/`glideViewTo` 以 `t0 = performance.now()` 起算、`now` 取 rAF 回调时间戳,两钟不同源时 `t` 为负 ⇒ `ease` 越走越负、`t < 1` 恒真 ⇒ **rAF 循环永不终止、视口一带一路飞出内容之外**(jsdom 实测:now 4968 vs t0 6268 ⇒ t = −5.4、单帧 panY 位移 −17 万 px,四帧内到 −167,062)。改 `progressOf` 单一实现:起点取**首帧 rAF 时间戳**(同一把钟)+ 进度夹 [0,1](单调 ⇒ 必然收敛);真机两钟同源时两者等价(**行为零变化**)。 **钉值**:新增 `tests/paper-provenance.test.ts` 15 例(纯层文本/截断/不可点 + 引线三种选边 + 接线与 CSS 字面量);`tests/paper-viewport-ux.test.tsx` ⑪ 段 3 例行为(出处行常显写卷名 / hover 挂线·移出即撤·端点对世界几何 / 点行溯源落洞中线 + 洞点名)——溯源例同时是混钟修复的回归考官(旧实现下视口飞到 −16 万 px,必红)。门禁:tsc 0 / `biome ci` 821 文件 0-0 / 全量 vitest 绿 / convergence 通过。**真机验收六条见 plan §6**(owner:用户)。 - 2026-09-18 · **引线重做:从「连线图」回到一支笔**(用户判一刀那版「一根直线直连虽然没啥问题,就是感觉有点劣质」——判断成立)· **病根不在线,在语言**:一刀版是**世界坐标的一根等宽直线**,两端贴死钉缘/洞缘——那是**连线图**语汇(接线/流程图),不是纸上的东西。劣质感的三味:等宽(无起收)、贴死(插头感)、一笔到底的直线(无手迹)。 **选(判例内转录,不发明)**:本仓早有一支更高级的笔——**划词朱线**(`paper/sel-ink.ts` + `.pp-sel-ink`,2026-09-02 立、用户拍板过:纸不动只落墨)。引线整支改抄它:逐点正弦微伏(±1.2)+ 定种子相位(`selSeedOf(钉 id)`——**同钉恒同线**,重渲染/平移不闪)+ `smoothPath` 手绘平滑(该函数本批由私有转对外共用:**同一支笔不各写一份**)+ **恒定墨宽**(该判例的**明文字律**:**手感来自微伏不来自粗细变化**)。四点按引线几何改写、每处记理由:① 层改**屏幕坐标**(同 `.pp-sel-ink`)——墨宽不随缩放变(世界 1px 在 zoom .3 下 = .3px,等于没画;一刀版靠 `non-scaling-stroke` 补的正是这一课,但那只救描边救不了几何);② 微伏走**弦的法向**(划词横线用竖向即可,引线可朝任意方向,纯竖向微伏在纵线上等于没有);③ 叠一层**垂**(重力,只吃横向跨度——纯纵向的丝不垂,两端同轴没有可垂的余量):`min(L×0.06, 18) × clamp(|dx|/(0.35L))`;④ 起笔**留白 6px**(飘出来,不插在盒子上)+ 收笔**朱点**(「句读点朱」遗意:**线是引,点是落**;划词的收笔挑钩是「离笔」,引线到站故以点收);⑤ 微伏包络取 `sin(πt)`(**两端收零**:起笔留白与落点都要干净——划词是着重线,两端照抖)。 **弃(记录以防回漂)**:(a) **等宽填充笔锋**(起笔粗收笔尖的实心笔道,我第一念)——与判例明文字律直接冲突,且实心填充做不了描线动效;(b) **双笔 echo**(划词的淡墨第二笔)——那是**短线**语汇(一行字下),长引线上会读成双线/毛边;(c) **描线动效**(dashoffset 把线拉过去)——hover 瞬时件加动画,钉多时每次划过都要等一次落笔,改 `--snap` 档不透明度渐显;(d) 垂度改成「垂向 +y 恒定」——横向跨度为零时也垂 = 纵丝侧弯,物理上不通。 **钉值**:`tests/paper-provenance.test.ts` 由 15 → 17 例(引线段整组重写:选边三态 + 起笔留白量 + 两端微伏收零·点数随长度 + 垂只吃横向跨度·纵丝不垂 + 定种子同钉同线 + 朱点 = 落点);`paper-viewport-ux` ⑪ 引线例改考**屏上投影**(笔道 `d` 起笔落点对 `worldToScreen`、朱点 cx/cy 对洞缘投影——屏幕坐标层的接线由此钉住);CSS 钉值改述(`fill:none` / `stroke-width:1.4`(比划词 1.7 细半档:丝不是着重)/ 圆头 / 屏幕层 `inset:0` + `z-index:4`(纸与块之上、坞 5 与浮件之下)/ 弃 `non-scaling-stroke`)。门禁:见同批上一条。 - 2026-09-19 · **钉住块与纸条换装:从「小号的纸」回到便条**(用户报「这两个钉在画布上的东西,视觉上怎么看都不好看,而且文字填的很满」)· **探查先于意见**:搭一比一 A/B 台(`prototype/pin-strip-ab.html`——真 `tokens.css`+`PaperPanel.css`+真纸纹资源,`--pp-*` 变量由 `type-tokens.ts` 现导),并**采样台面像素**代替眼判。三条病灶带数: ① **墨占 100%**——流内 720 墨借 1440 流区纸的左右各 360 白边;钉到桌面上之后那份白边不存在了,而 `.pp-block` 是 `padding: 0`(注疏范式:块只是墨),`.pp-pinned` 只补了底/纹/影/裱边带 ⇒ 只剩 4px 裱边带顶着字(纸条 12/10 内距 = 95%)。「填满」是算术结果,不是感觉。 ② **常驻件全挂在纸外**——文类签 + 出处行 `left: -128px`、竖排「钉住」签 `right: -36px`、收回钮 `top: -30px`:流内时那 360px 页边正是它们的家,钉住后「页边」没了。且竖排签是 hover 才显形——钉住是常驻状态,静息态反而没有任何身份标记。 ③ **材料只有剂量差**——钉块与流区同 `paper-sheet` 纹理、同四层物理包边配方(只是 7px 带缩成 4px),纸条连纹理都没有。像素实测:桌面 `204,198,189` vs 钉块纸 `215,211,207`(Δ11)⇒ **影成了唯一线索**;而规格书 §11 海拔表原文是「纸内件(块/纸条/签):**无投影**,靠遮挡+界栏线+选中线表达」,致死四动作里就写着「万物皆浮 / 混材质」。09-05 pin-strip-rework 把纸内件当「小号的纸」做,越过了自己立的法且规格书未同步。 **选(用户拍板「甲+丙」)**:**甲·留白**(纸内白边:钉块 34/44/38、纸条 10/12→18/20;文类签/序号/出处行收进纸内成一行**报头**,弱规线分隔;竖排「钉住」签退役,身份改**常显方墨点**——D2 方点语言,且不占朱砂)+ **丙·便条**(`--paper-deep` **实色无纹** + **贴平无落影**)⇒ 三分材质:桌面有纹(场)/ 流区有纹(纸)/ 便条素纸(纸片),层级靠纸色与白边读。纸内件唯一配影的时刻 = 拖拽携带态(`--elev-raise` 压印族,§11 规则①已列「拖拽幽灵」)。 **弃**:**乙·剪片**(去落影 + 纸色深一档)——**被自己的数据否掉**:实测那个纸色 `207,202,193` 与桌面 `204,198,189` 只差 3 阶,直接糊在桌面里;这条负结果同时解释了当初为什么会走到「加影」(在米色桌面上,同色纸 + 无影读不出物件)。连带弃「继续调影剂量」整条路(三档影 = 万物皆浮的配方)。**弃**「拖拽携带态也长白边与报头」:几何一律不动(抓手偏移敏感 + settle 一拍盖住落钉那一刻的重排),只换纸色与影。 **翻案注记(09-05 批部分翻案,翻案理由如上)**:竖排「钉住」签(原型 `.pin-hint` 转录)**退役**——它把常驻身份押在 hover 上;纸内件配流区同款接触落影**判死**——§11 原表已写「无投影」,本批是回归不是新法。**保留不动**的是 09-05 的行为面:松手定夺、带显形、落点预览、纸条两击确认、一次性眉批。 **连带(同批查出,非本功能)**:① 纸条题签由常显朱砂 `--seal-deep` 回落 `--ink-3` + 方墨点——每多一张纸条就多一处**常驻红**,与 §10 法则 3「每屏至多一处红」相抵(朱砂留给两击销毁确认态 = 人的动作);② 纸条补**来源行**(`.pp-strip-src`「摘自 卷名」)——`PaperStripSource` 原本只有 messageId/partIndex/offsets,**没有卷名**,本批加可选 `label` 快照(抽取那一刻写入 `volumeDisplayName`;拷贝语义:源卷改名不追改,与块级钉的活卷名出处行是**两套语义**,旧存档无字段则整行不渲染);③ `STRIP_H_APPROX` 120→150(白边 + 报头抬高了纸条结构高,叠放探测同步)。 **钉值**:`tests/paper-visual-decisions.test.ts` 钉住/纸条段**整组重写**(故意规格变更,显式声明)——旧三条(物理包边轻量档 / 竖排签 / 纸条物理缘轻档)整删,新五条(便条白边与无影 / 纸内报头 + token+measure 三处齐全 / 纸条同族 + 题签墨阶 / 来源行快照 / 携带态几何不动 + settle 只声明 translate);新增 `tests/paper-markdown.test.ts` +3 例(**钉住态几何高镜像**:= 纸内白边 + 报头 + 按收窄测宽;流/钉两态各持一条缓存——拔钉后不许读到钉住高)。 **测量镜像(本批真正的暗礁)**:`PinnedGeom.h` 走 `measureBlockHeightCached`,白边与报头是**钉住态独有的竖直增量**——不镜像则剔除矩形比真身矮,块尾滑到视口边**整块消失**、小地图框偏小。治法:主函数按 `b.state` 分支(`pinnedBlockHeightCached`:RO 实测优先——实测读的是钉住 DOM 的 border-box,白边与报头已含在内;静态镜像族按 `w − padH×2` 收窄测宽 + 白边 + 报头),cache 键加 `#pin` 后缀与流内条目分家。**宿主面零新增出口**(未动 `faceDeps`、未重生成基线)。 **交付口径**:`PaperPanel.tsx/css` + `use-paper-strips.ts` 属**产地域**(磁盘通道,可热更),但 `paper/measure.ts`(钉住态分支)与 `paper/type-tokens.ts`(`pin` token 组 ⇒ `--pp-ch-pin-*` 注入)属**壳域**(⚠ 2026-09-26 批 9c-4 起二者已随 `paper-shell` 产物 ⇒ 改它们**免重建 exe**;本条是当时形态的历史记录);产物单独热更到旧 exe 上不会报错(宿主面键集未变,封印不响),但 `--pp-ch-pin-*` 缺席会让 `padding: var(...)` 整条声明失效、白边静默塌成 0(A/B 台复现过一次,故记在此)。 - 2026-09-19 · **消息块动作行的悬停可达性:从「块外缝隙里」收回「块内尾带」**(用户报两条:「鼠标还没挪过去就消失」+「来文块的按钮和后续文字重合」)· **探查先于意见**:搭真 CSS + 真 Chrome 走位台架 `prototype/msg-ops-hover-ab.html`(A 栏复刻旧几何、B 栏现网;`msg-ops-hover-probe.mjs` 逐点走位出数),旧几何实测三数—— ① 指针停在**块底 +1px 的缝里**:行 `opacity 0` / `pointer-events none` / 命中落回 `.flow`; ② 再挪到**动作行正上方**:仍 `opacity 0`,命中是**下一块的正文** `.pp-md-p` —— **揭示靠 hover、命中又要靠揭示(互为前提),按钮永不可命中**(与 §9.2 坞锁钮一版同病,那次是「浮在坞外有缝」,同一条教训第二次上门); ③ **来文块越界**:块下只有 `ANCHOR.userTailGap` 8px,19px 的行越出块底 **13px**(握把 15px)压住下一块的题签与首行——用户看到的「重合」就是算术结果。 **选**:**甲·缝并进容器 padding**(行盒顶边贴块底,多出的 2px 是透明桥面——视觉呼吸不变、hover 链不断)+ **乙·来文块的行落块内尾带**(花押行之上 2px:块体之内 ⇒ 零死带、零越界,尾带 30px 塞得下 19px 的行,余 9px);握把(`.pp-branch-grip`)走**同一条纪律**,但它是带边框的实盒 ⇒ 缝用 `::before` 桥面补。 **弃**:① **把 `userTailGap` 8 → 28**(改的是**纸的节奏**:花押那 30px 尾距本来就在块内,为一条 hover 行去加宽来文后的留白,是拿版面还交互的债);② **隐没态留 `pointer-events: auto`**(让透明按钮自己当桥)——2026-08-31 刚摘掉的「透明按钮吃块下点击」会原样回来,且缝里仍会闪一下。 **钉值**:新增 `tests/paper-msg-ops-hover.test.ts`(5 例)——钉**结构**(贴块底 / 不许回 `calc(100% + 2px)` / 来文块落块内 / 隐没态不吃指针 / hover + focus-within 揭示面在册),不钉像素;并**用 token 真源算一遍尾带算术**(行底偏移 `asterismLine + 2` + 行高 19 ≤ `asterismLine + asterismMarginTop`,且 `userTailGap < 行高` 是「非落块内不可」的理由)。改按钮字号/padding 必须重跑台架并同步行高常数(文件里写明了)。 **交付口径**:改的是**插件 CSS**(`paper-shell/PaperPanel.css`)⇒ 按 landmine H2「产物里的 CSS 从不生效」,**必须 `cd src-tauri && cargo tauri build --no-bundle` 重建 exe**(先关掉在跑的兰台);只热更产物无效。 - 2026-09-19 · **退出守卫:关窗时有会话在跑先问一句**(用户报「工作区退回到首页是有一次提示的,但是从工作区直接关软件完全不提示,感觉不是很对」)· **病灶(两条路径不对称,而两个钮是挨着的)**:回首页有确认(`PaperPanel` 关闭守卫 → `ConfirmDialog` → `leaveToHome`),紧挨着它的窗口 ✕(`WinControls`)没有——关窗路径(`shell/rows/persistence` 的 `watchWindowClose`)只做「退出落盘 → destroy」,正在跑的那一轮被直接终止且用户零感知;手一抖点到 ✕,应用就没了。 **选(用户拍板:只有会话正在跑时才拦)**:空闲关窗照旧直接退(会话与画布本来就会自动落盘,弹层只是多一次点击);有卷在跑才升起确认——**真正不可挽回的只有「跑着的一轮被终止」这一件事**。**弃**:(a) 只要在工作区里就弹(与回首页对称,但空闲时多一次点击);(b) 每次关窗都弹(最可预期,代价是每次退出都点一下)。 **判据**:`countRunningSessions()` = 在册句柄 + 该卷 `exec.isRunning`(账本随句柄;子 Agent 不入 `agentSessionState`,其父卷未收尾即在跑)——与纸面运行态(`useRunningSessions`)同义。取消 = 本次关窗作废(窗口留着,`_closing` 不置位,下次点 ✕ 重新问);弹层在场时再点 ✕ 并入那一次,不越过用户 proceed。 **系统关机不走本路(查过上游源码,非推测)**:tao 0.35.3 显式不处理 `WM_QUERYENDSESSION`(`event_loop.rs` 有「until we introduce … Tauri's ExitRequested」注释),故弹层不会阻塞关机;关机仍由 `pagehide`/`visibilitychange` 兜底入口接。 **钉值**:新增 `tests/exit-confirm-guard.test.ts` 6 例(无卷在跑=直接退 / 有卷在跑=拦下且不落盘不 destroy / 取消作废且再问 / 确认=落盘→destroy / 弹层在场不重复 / 跑完后再关窗不拦)——走生产单点 `bootPersistence` 的关窗入口,不复制编排逻辑。 **交付口径**:全部落在**壳域**(`app/App.tsx`、`app/ExitConfirmDialog.tsx`、`state/exit-guard-store.ts`、`shell/rows/persistence.ts` 均静态 import 进 app bundle)⇒ **本批必须重建 exe**(关掉在跑的兰台后 `cd src-tauri && cargo tauri build --no-bundle`),只热更插件产物不生效。 - 2026-09-19 · **目次带加宽:给边缘滚动让出一条跑道**(用户「由于边缘滚动的落地,我需要再次加宽我的目次带,因为会有误触的问题」)· **病灶(两条面抢同一条带)**:边缘滚动的右缘感应带(基准 36px,贴屏最右)正落在目次带上,而带体只 64px 宽 ⇒ 带内几乎处处是感应带——「用带」(hover 读带 / 点带即跳 / 拖滑块)与「贴右缘缘滚」互为误触:指针在带右半部停够 120ms 就起滚(读带时视口自己跑),反过来贴屏最右缘滚时又会顺手弹 hover 卡,一记误点就把视口跳到别处(点带即跳是整条带生效的)。 **选(加宽 = 把导航面整条让出感应带)**:带体 64 → **104px = 内容列 64 + 缘滚跑道 40**。内容列(新元素 `.pp-toc-col`)承载**全部导航面与交互**,宽度**与旧带体逐字同 64px** ⇒ 带内既有几何(墨迹缩放比 / 刻痕 / 阶段锚 / 滑块 / hover 卡)零漂移,加宽买到的只是「整条带向左挪 40px」= 锚与感应带之间的余量由 2px 变 42px。带体右 40px 是**缘滚跑道**(`TOC_RUNWAY_W` ≥ 基准带宽)——贴屏最右那条感应带从此整条落在跑道上。跑道**惰性**:交互判据(`insideCol`)只认内容列 ⇒ 跑道上按下不 scrub、mousemove 不弹卡(点击只被吞掉,不吞就点穿到纸上划词),而悬停照旧算画布(`HOVER_ALLOW_DOCKS` 不动)⇒ 右缘照旧缘滚。顶部浮件右距同批 80 → 120(= 带宽 + 16)。 **弃**:① **把带体整条移出感应带**(右缘离开屏缘,右 40px 交还画布)——那 40px 会露出纸并被点穿(划词/落点都落在纸上),且导航带不再贴屏缘,「右缘即导航带」的读法散掉;② **跑道也算导航面**(保「点带即跳」全宽)——正是本批要根治的误触;③ **按灵敏度动态调跑道宽**(感应带随 sens 变宽)——视觉跟着设置滑杆跳,且交互面与可视面开始分家(还要新宿主面通道,不值)。 **边界明账**:灵敏度拉满时感应带 ≈51px,会吃掉内容列**右缘 11px 的 scrub 余量**(锚/刻痕只占左 26px,任何档位都不在感应带内——钉值钉住这条);窗口收窄到 880px 时带体占 104px(≈12%),比旧 64px 多压正文 40px(用户真机 2560 宽,本批不做响应式收窄)。 **钉值**:`tests/stage4-toc-top-band.test.tsx` +2 例(几何:组件常量 ↔ CSS ↔ 算术三处同源 + 跑道 ≥ 基准带宽 + 拉满灵敏度不碰导航件;行为:跑道按下不 scrub / 不弹卡,内容列照旧点带即跳与指哪读哪)。**变异验证**:把 `insideCol` 判据短路掉,行为用例当场红(旧实现 1/1 红 → 新实现全绿)。 **交付口径**:组件(`compose-dock/TocStrip.tsx`)属产地域可热更,但 CSS(`paper-shell/PaperPanel.css`)按 landmine H2「产物里的 CSS 从不生效」在**壳 bundle** 里 ⇒ **必须 `cd src-tauri && cargo tauri build --no-bundle` 重建 exe**(先关掉在跑的兰台)。 ⚠ **本条「识别层零漂移」那半已被同日下一条(甲案)取代**——控制层(刻痕/锚/滑块/卡)的零漂移结论不变,识别层(墨迹/未读区/活线)改为铺满整条带。 - 2026-09-19 · **目次带加宽 · 同日续批:识别层改铺满整条带(甲)**(用户看完像素对照后一句「你觉得这看起来对劲吗」→ agent 出三栏对照图并**自定**甲)· **病灶(不是坏,是空)**:用户贴来带体截图问观感;我把截图逐像素量了一遍(114×1182)——带体 105px 贴屏、控制列 64、跑道 40 且**零墨迹**(46098 像素里只 12 个偏暗像素,最大暗 12/255 = 纸纤维)、识别层缩放比未动(剪影最远到 band-x 48 = 文本栏右缘 × 64/1440;若被拉宽会到 ~78)。**功能全对,但读作「带子空了一半」**:105px 里墨迹只占 48px,右边 57px(16px 控制列余量 + 40px 跑道)是空的——根因是我上一批把**识别层也钉死在 64px**(图「零漂移」),于是加宽只买到「整条左移 + 一条空跑道」,没买到「更大的识别面」。 **选(甲:识别层吃满整条带)**:**识别层(墨迹 canvas / 未读区 / 活线)移出控制列、按带体满宽铺**——画布 `clientWidth` 64 → 104 ⇒ 剪影横向 ×1.625(48 → ~78px,横向分辨率同涨,扫读更清;三者都是 `pointer-events:none` 纯识别面,越进跑道不涉命中);**控制层(刻痕/锚/滑块/卡)仍在左 64px**;两者之间立一道**界栏线**(`.pp-toc::after`,`left` = `TOC_COL_W`、`color-mix(--ink-4 65%)`(α≈0.20)、`pointer-events:none`、z-2 压在识别层之上而让 z-3/z-4 的刻痕与锚照旧清晰)——**「看着能点其实不能」正是误触的另一面**,界栏线把可交互边界说清楚。跑道惰性判据(`insideCol`)一个字没动。 **弃**:① **乙·跑道画成页边**(控制列不动,跑道加界栏 + 底色淡一档)——最保守,但 105px 里仍有一块不承载信息的宽度,「加宽」白买;② **丙·带体收窄**(64+38=102 / 56+40=96)——只是把空的地方缩小,识别面反而更小;③ **滑块跟着铺满带**(VSCode 式)——滑块是**可拖控件**,控件伸进惰性跑道 = 又造一个「看得到抓不到」的区(保留在控制列内,其右缘与界栏线同轴,自成边界读数)。 **钉值**:`tests/stage4-toc-top-band.test.tsx` 加宽批首例 +③ 界栏线契约(`left: ${TOC_COL_W}px` + 不吃指针)+ 结构断言(墨迹画布是带体子件、**不在**控制列里;滑块在列里)——结构断言就是甲案的考官(把 canvas 挪回列内即红)。**真 CSS + 无头 Chrome 探针实测**:canvas.clientWidth **104**、unread/活线 104、控制列 64、滑块 56、锚 26、界栏线 `left=64px/1px/α≈0.20/pe=none`、跑道恰 **40.0px**,控制层与加宽前逐字同值。 **交付口径**:同上一批(CSS 在壳 bundle ⇒ 重建 exe)。 - 2026-09-21 · **目次带甲案的归因更正 + 界栏线摘除**(用户「我从来也没拍板过『界栏线』,是某个 agent 窗口自己决定的」→ 用户看证据后拍板「摘线 + 改记录,识别层铺满保留」)· **病灶(记录失实,不是代码)**:上一条把甲案(识别层铺满 + 界栏线)记成用户拍板,而**同一批的交接清单**(`docs/plans/README.md` 该行)把「④ 甲案观感:识别层铺满 + 界栏线分界是否合意、界栏线浓淡是否合适」列为**待用户体感确认**——批内自相矛盾。用户原话只有一句**提问**(「你觉得这看起来对劲吗」),此后「三栏对照图定案甲」是 agent 自己定的(物证:`D:\tmp\toc-band-probe\options.png` 21:45 生成,commit `dc58cdc3` 21:56 落地,中间无用户选择记录)。commit message 与规格书 §13 的「用户看像素对照后定/拍板」= **把待验收项升格成用户裁定**。 **存档旁证**:`.lantai/sessions/` 全部会话日志里 09-19 **20:37–22:00 一段一条用户消息都没有**(17:11 直跳 22:06),四批(关窗守卫 / LOD / 加宽批 / 甲案)全落在空档里 ⇒「用户拍板」在存档面**无可核对依据**;被引为加宽依据的那句原话亦只存在于 agent 自写文件,日志中一次未现。 **选(用户 2026-09-21 拍板:摘线 + 改记录,识别层铺满保留)**:① **摘掉 `.pp-toc::after`**(规则整条删除,不留尸体)——该线**零功能**:跑道惰性由组件 `insideCol` 判据(夹在 `TOC_COL_W` 内)决定,与线无关;② 归因改回事实,落点六处:本账本上一条 + `lantai-design-spec.md` §13 两处 + `PaperPanel.css` 带体头注 + `TocStrip.tsx` 头注与两处常量注 + `tests/stage4-toc-top-band.test.tsx` 两处注释;③ **识别层铺满保留**,与甲案其余内容同降为**待用户验收**;④ **提交史不改写**——`dc58cdc3` 的 message 保留原样(改它要 rebase 掉其后全部 commit 的 hash,代价与收益不成比例),失实以文档面更正为准。 **弃**:① **只改文档不摘线**——线本身就是那条假归因的产物,留着等于让记录与界面继续分家;② **连加宽批一起回退**(带体收回 64px)——跑道是边缘滚动落地后的误触根治,与本条无关,用户只否认界栏线;③ **改 commit message**(同 ④)。 **钉值**:`tests/stage4-toc-top-band.test.tsx` 加宽批首例 ③ 由「界栏线落在控制列右缘且不吃指针」**反转为「CSS 里不得再有 `.pp-toc::after`」**;行为面用例(跑道惰性 / 内容列照旧)逐字不动——它们正是「摘线 = 零行为变化」的考官。 **交付口径**:**本批恰好落在「必须重建 exe」的第一条边界上**——`dev-workflow.md`「生产包热更 · 三条边界」条 1:**删** CSS 规则不算数(首帧壳 bundle 里留着插件 CSS 的旧拷贝,产物 link 只能覆盖不能抹除)⇒ 想看见线真的消失,必须 `cd src-tauri && cargo tauri build --no-bundle`(先关掉在跑的兰台,exe 占用会 os error 32)。**文档所载的绕法(保留规则改中性声明以便热更即刻生效)本批不取**:那会在 CSS 里留一条死规则,与本仓「不留注释尸体」相抵,而摘的只是一件观感件——不值得为省一次重建留尸体。 - 2026-09-21 · **卷号收显示:号不再到处报**(用户「这个世界上根本没有 Agent 软件会到处显示会话的编号」)· **病灶(号 = 身份,不是名字;四处却在名字旁边再报一次)**:① 侧栏行机读注记 `Nº 12 · 8 块 · 1 小时前`——卷名就在上一行;② 书脊 hover 小卡(与 ① 同一个 `sessionMeta` 的第二个消费面);③ 血缘牌/行 title 与血缘卡机读行的 `父卷 Nº 15`——父卷名已承接指代;④ 创作坞书眉 hover `案卷 ${id}`——**对有名卷也硬报号**,且裸用 `id` 绕过 `volumeDisplayName`(违单一真源)。前三处是 P5 双视角当天追加物,**无规格依据**。 **选(2026-09-21 用户拍板 A+B 的 A 面)**:退掉 ①②③④ 的重复号(血缘卡「父卷不在场」标题改走 `volumeDisplayName('', id)`——号留在**名字位**,不再重复报);**保留两处「号即身份」**:书脊档号 `.sr-num`(题名两栏截断后唯一可靠的身份,独立规格 §334)与卷首眉行(恰出现一次,2026-09-16 拍板)。**无名卷的号即其名**——显示兜底(侧栏行名 / 卷首题字 / 书脊题名 / 墨层地志标签 / 出处行 / 窗口标题 / 墨量册标题 / 权限卡徽标 / 案头签条)**全留**。诊断 / toast / 状态字**一律留号**:那些调用点手里只有 `number`、没有卷名(`running: number[]`、`failed[].id`),退号 = 报错说不出哪一卷。 **弃**:① 连兜底显示一起退(无名卷的卷名位会一片空白——「退掉显示兜底」不可行,只能退「重复报号」);② 退书脊 `.sr-num`(索书号用法,两栏截断后无身份可认);③ 退卷首眉行(推翻 2026-09-16 拍板)。 **已知代价(诚实栏)**:按号检索仍命中(`filterRows` 的 `String(r.id).includes(q)`),但行上不再显示号 ⇒ 输入 `12` 得到一行名字,**匹配理由不可见**(现无高亮/片段机制)。接受:placeholder 的承诺是「能搜到」,不是「看得见号」。 **钉值**:`tests/canvas-nav.test.ts`(`sessionMeta` 期望串去 `Nº`)、`tests/session-sidebar-tree.test.tsx` 与 `tests/session-sidebar-views.test.tsx`(title 只留「枝 / 自父卷分出」、卡机读行只留「N 块 · 枝自它分出」);`tests/paper-c8-spine.test.tsx` 的「档号恒显」**逐字不动**——它正是「书脊档号不可退」的考官。设计件 [`../../archive/session-line/volume-number-governance-plan.md`](../../archive/session-line/volume-number-governance-plan.md) §2。 **交付口径**:A 面三处落在插件产物(canvas-nav / compose-dock / paper-shell),B 面(发号账)落在 `src/ui/chat-session.ts` = **app bundle** ⇒ **本批整体要重建 exe**(关掉在跑的兰台后 `cd src-tauri && cargo tauri build --no-bundle`);只热更插件产物不够。 - 2026-09-22 · **左缘边缘滚动失灵:书脊列压住左缘感应带**(用户「靠了,边缘滚动的左侧边缘失灵了,估计是和新的书脊栏逻辑冲突了」)· **病灶(滚轮批的连带代价,不是曲线/带宽)**:左缘感应带 = [0,36],而书脊列 = [0,72] 全高、脊块占 [6,68] ⇒ **整条带压在列内**。滚轮批(`dda062f2`)把 `.sr-rack` 的 `pointer-events` 由 `none` 改成 `auto`(热区 = 整块板,修「滚轮落在书缝不滚列」)之后,贴屏最左命中的由**画布**变成**列板面** ⇒ 悬停判据(`hoverEdgeEligible` 要求指针落在画布内或贴边浮件上)一律否掉,左缘在用户视角里等于没有缘滚。**回归窗口可复原**:改之前 `.sr-list` 未声明 `pointer-events`(随列 = none)⇒ 最左 6px 内距带 / 书缝 / 末脊之下空白都穿透到画布 = 左缘照滚;滚轮批一次性关掉这三处。 **选(判据侧解耦,CSS 一字不动)**:列的**板面与书缝**算画布(`.sr-rack` 进 `HOVER_ALLOW_DOCKS`),**脊块 `.sr-spine-main`(点=定位 / 拖=落位 / hover=出小卡)与 hover 小卡 `.sr-card` 进 `HOVER_EXCLUDE`**——「地图 / 瞄准面」按手势语义分,而不是按「是不是画布 DOM」分(同目次带卡片口径:卡片是 button 故本就在豁免列)。滚轮批买到的热区(契约 8)**逐字保留**。 **弃**:① **整列算画布**(不豁免脊块)——鼠标一上书脊画布就自己跑(「跟随相机」),而脊块是三个手势的瞄准面;② **给列加一条 36px 左跑道**(把脊块整条右推、列 72 → 108px,照目次带加宽批的形态镜像)——这是**可见的版面改动**(用户刚在四批里定完书脊形态),本轮不动它;若用户体感「6px 太窄」,那是下一个 A|B 题(几何合同 + 验收台判据已在 `tests/paper-c8-spine.test.tsx` 与 §12.1 定值里,改动面清楚);③ **把左带的参照系从屏缘改到列的右缘**(只让列右侧 36px 起滚)——用户的手指动作是「甩到屏左」,那样左缘仍是「贴死屏左不滚」。 **钉值**:`tests/edge-scroll.test.ts` 加左缘用例(真机层级:坞 > 列 > 案卷扣 button + 脊列 > 脊槽 > 脊块 div[role=tab] > 题签,加 hover 小卡与展开态侧栏)——断言列板面/内距带/列底空白可滚,脊块/题签/案卷扣/小卡/侧栏不可滚;**变异验证**:把 `HOVER_ALLOW_DOCKS` 撤回只留 `.pp-toc`,该用例当场红(`expected false to be true`),其余 7 例零漂移。 **交付口径**:改动在 `paper-shell/edge-scroll.ts` = **插件产物** ⇒ `npm run --prefix src-ui build:builtin-plugins` + 应用侧自动重载即可(实机验过:重建后 6s 内行为翻转,无需重建 exe)。**实机取证**(`prototype/_probe-edge-left.mjs --stim`,连运行中 WebView 的 9222 口、真 mouseMoved、收尾滚轮回补视口到 ±1px;**`prototype/` 在 .gitignore 内,探针不随仓库分发**):rAF 101fps / hasFocus=true / 带外噪声地板 x=74/400 恒 Δ=0 ⇒ 读数可信;修前 x=2/5/20/40 各停 500ms 全 Δ=0,修后 x=2 → +909、x=5 → +1164、脊块 x=20 与题签 x=40 恒 0、右缘跑道 −958 / 上缘 +1032 作阳性对照。 - 2026-09-22 · **匣脚引线:坞的版口钮 → 活卷的纸脚**(用户提案「我一直以来对于多会话卷的激活态的设计都没做好……让创作坞带一个锚点,用引线连接当前选中的会话」;一版落地后用户当场打回卷端落点「你这个引线能挂在页尾吗…………你挂在第一条用户输入那不是乱了套了」;**标题原写作「同日拍板『两端扎实体 + 常显·淡 .55 + 可点溯源』」——其中「可点溯源」系 agent 自记,用户 2026-09-24 否认,见本文件同日「匣脚引线纯指示化 + 归因更正」条**)· **病灶**:活卷的信号全在纸上——接触落影加深一档(切卷瞬间「拿纸」过冲)+ 卷首规线左端一枚 56×3 朱砂短横(**只挂活跃卷**,「红在哪卷即活卷」);坞这头把卷名写在书眉行,却与纸上任何一卷之间**没有任何可见联系**。坞自 09-17 浮动化之后两边各自在屏上走,「坞报的卷名指哪一张纸」只能靠读者自己连线。 **一版(本账已翻案,留档防回漂)**:卷端接在**卷首规线左端那枚版口钮**上,理由是「红对红,一线相连 ⇒ 天然只指活卷」。**错在把两种标记混为一谈**:天头那枚钮是「**哪一卷活跃**」的标记,不是「**这一卷在哪儿**」的位置标记;且它正压在标题块与**第一条来文**的接缝上——线读起来像在指第一条来文(用户原话即此)。一版还顺手把「卷首常年在屏外」(人在读尾,线长期指向屏外的一方)当成优点写进了理由,实为另一处病灶。 **选(二版定案)**:**坞端 = 版口钮**(坞顶左端那条 56×3 朱短横 = 匣口,全坞唯一暖色件,锚在既有实体上不新造);**卷端 = 活卷的纸脚**(版心左缘 × 卷底边)——与枝边那条腿同族:**扎在纸自身的材料缘上**(受光/背光缘与裱边带交汇处),不落任何一块字。选纸脚三条各记理由:① 它才是「这一卷写到哪儿」的那一端(卷轴锚线 = 最新块底边,纸脚再低一个底距 = 「墨将落此处」下方那段留白),读者与坞平常都挨着它;② 天头那枚钮已被「活跃标记」征用,再兼位置标记就与第一条来文抢读;③ 读尾时纸脚就在坞上方几十像素(一版那条线则长期指向屏外的天头)。两端各在既有单一真源:坞侧 = `composer-float.composerAnchorOf`(槽主人实测坞位与坞高,坞本体一字不知),卷侧 = `dock-tether.regionFootAnchorOf`(版心宽走 `measure.folioHeadWidthFor`——顺手把「注释里这么叫、代码里却内联」的那条式子抽成了真函数)。常显(结构不是瞬时手势,同枝边那条腿);墨阶与枝边同半档 .55(**原文此处还有「+ 可点(受墨带 → 飞到线的那一头=本卷纸脚,同『点线溯源』判例);…hover 抬 .9」——2026-09-24 归因更正后整批摘除**:受墨带 / 点击 / 焦点态 / 抬墨两档,见本文件同日条)。 **笔的两处补全**(判例原文 = 「控制点 = 端点 + **锚面法向** × 弦长 × 0.25」,且那条公式「只有下限没上限」——前两条腿的锚面都是竖面,故法向写死水平、只搬了上限):① `TetherPen.normals` 两端**锚面外法向**(匣顶朝上 / 卷底边朝下,**按锚面定、不按相对方位现算**——方位一变就改法向,「目标落在匣身背后」那一档的线会整段钻进匣里被盖住,绑定当场隐形);② `TetherPen.minArm` 臂长下限 `TETHER_SPLINE_MIN = 48`——取值由台架读数定而不是手感:抬起的幅度 ≈ 0.75 × 臂长,而**重力垂**上限 18 会把它吃回去,下限 24 时净抬起只剩 **2.6px**(等于没抬),48 ⇒ 净抬起 ≈ 18px,一眼看得出线离开了那条规线。**缺省值恒等于旧行为**:既有两条腿的 `d` 串逐字节不变(测试 diff 为零 = 零漂移的最强证据)。 **弃**:① **接天头版口钮**(一版原案,见上「一版」);② **新加一枚坞缘锚点圆点**(照抄「面对面选边」)——坞的*边缘*不是实体、锚点还会随相对方位在左右缘之间**跳**,正犯锚点批那条病灶(「没有一个固定的锚点来连接引线,感觉奇怪」);③ **线指「落笔点」**(坞 ↔ 正在写的那一处,比纸脚再上一个底距)——那儿是**动作行/湿墨**的领地(块尾悬停行与石青方点都住那一带),且会成双点噪声;纸脚那张空纸边更干净;④ **hover 才显形**(把「哪一卷活着」这条常驻信息藏进 hover,正是本批要治的病);⑤ **坞端锚点取坞缘中点**(不接任何东西,纯几何点)。 **钉值**:`tests/paper-provenance.test.ts` +5 例(缺省逐点等于旧行为 / 竖法向两端切线竖直 / 按锚面不按方位(翻转档)/ 下限托起 / 下限不得越过弦长比例臂长且退化点归零)+ 接线与样式钉值 1 例;`tests/composer-float.test.ts` +4 例(坞锚两种坞位 / 坞高变 / 与 CSS 字面量对拍);`tests/paper-dock-tether.test.tsx` 新文件 7 例(真 PaperPanel 穿全层:两端扎实体**且卷端在卷首底线之下** / 切卷改指 / 坞被拖走线随坞 / 无活卷 / 案头态 / 活卷在屏外线照样出屏 / 点线溯源——**末例已于 2026-09-24 随行为退役删除,首例尾巴反转为「不可点」**)。既有两例按**腿**收窄(`.pp-pin-layer` / `.pp-branch-layer`——屏上从此恒有一条常显线,那两条「不 hover 不落笔」「无枝边不落笔」判据说的是各自的腿)。 **边界明账**:翻转档(纸脚落在匣顶线之上 = 坞压在纸身上)出笔仍朝上、两端各按自己的锚面 ⇒ 中间成 S(不好看但确定,且不下潜进匣身);近水平档(纸脚与匣顶线同高)由下限托起,不再贴成第二条规线;坞压在活卷上时线在匣后(坞 z 6 > 线 z 4 ⇒ 被挡,属「坞压住内容」既有边界);LOD 远档不渲染卷首而锚点不受影响(纸脚 = 流区盒底,恒在)。 **交付口径**:改动全在**插件产物**(paper-shell 三个文件 + 新 `dock-tether.ts`)+ `paper/` 共享笔(`provenance.ts` / `measure.ts` 打在产物里)⇒ `npm run --prefix src-ui build:builtin-plugins` 即可,无需重建 exe;不新增 faceDeps 键(宿主面指纹不动)、compose-dock 一字未改、不碰 `src/agent/**`(不触发 convergence)。 **真机待验**(owner:用户):① 默认位(坞版心居中坐底、活卷居中)那条近垂直线是否够读、是否碍眼;② 常显 .55 档在真纸上是否合意(不合意可换 hover 才显,或改墨阶);③ 切卷瞬间「旧线撤 + 新线淡入 + 朱笔划界」是否读得出「绑定换了」;④ **坞拖到别处**时线随坞拉长好不好看;⑤ **活卷在屏外**时线指的方向是否真的指得对路(原判据「点线飞过去应落在纸脚」随受墨带于 2026-09-24 摘除,改由目次带/跳键走卷核对);⑥ 纸脚落点是否合意(**二版就改在这里**——若仍嫌它碍事,下一个候选是「纸的左缘下端」而不是版心左缘);⑦ 与枝边线在同一卷附近并存时是否打架。 - 2026-09-23 · **钉住块质感:从「排印件」到「纸片件」(三轮台子:边界 → 物种 → 质感)**(用户「我钉在纸面的卡片样式真的有点丑陋」→「看起来就是不像实物,没有质感的」→ 点破参照系「假如我们在做一个纸片手绘质感设计网站的卡片,假如我们在做一个风格化的游戏的卡片UI,会做成这样吗,明显不会」)· **病灶(三种语言都不占)**:钉住块已经离开流,不再是排印件(09-19 批给它收了纸内白边与报头,那半是对的);但它身上也**一点物件的语言都没有**——无框、无纹、无影,只剩一条顶缘内高光。它卡在「排印件」与「物件」之间,所以怎么调都别扭。**09-19 批病灶③「材料只有剂量差」的解法走反了**:当时把纹理当干扰删掉(同 paper-sheet 纹理只差 11 阶色 → 实色深纸无纹),而纹理恰恰是质感的**来源**。 **三轮探查(每轮只动一个层级的变量)**: ① **`pin-edge-ab` · 边界怎么读**。四案只动边界手段(硬边轻 ink-4 / 硬边重 ink-2 / 深纸 --paper-margin / 压印影 --elev-raise / 四角方点)。**实测**:现状 **1.11**,深纸只到 **1.187**,其余各案数字全等 1.11 —— **边界 ≠ 对比度**:线/影/标记不改纸色却给出**离散边界**,色差只给**渐变过渡**,1.11 这一档在带纹理的底上必然被吃掉。**无纹理探针**(桌面 background-image 关掉重拍):现状照样读不出边界 ⇒ 纹理不是主因,1.11 本身不够。**调色差路线就此弃**。 ② **`pin-species-ab` · 物种**。换参照系后把变量拉到物种级:票券(外框 + 两道撕口虚线 + 票根,出处行从报头挪进票根)/ 票券+打孔 / 图版(外重线 + 内衬细线的双线框)/ 索引卡(标题栏实线 + 通篇横格线)/ 裁切标记(四角 L,版面外侧)。**实测:五案对比度全是 1.11**(纸色一分未动)⇒ **物性来自线与结构,与明度无关**。**打孔坑**:孔填桌面色,而桌面色与卡片只差 1.11 ⇒ 孔本身隐形,可见性全靠孔的**墨环**(第一版只填色,孔整个消失)。 ③ **`pin-texture-ab` · 质感**。把质感拆成三个成分分别加:**纹**(paper-sheet 实拍纤维纹,尺寸压 900px)/ **包边**(四层物理包边 `inset 3px 4px 5px var(--sheet-lit)` + `inset -2px -3px 6px var(--sheet-shade)`)/ **落影**(`--shadow-sheet` 硬偏移族,无模糊)。**实测**(computed style 读出):无质那格 `backgroundImage: none`,完整配方那格 `2px 3px 0 rgba(38,34,28,.07), 4px 6px 0 rgba(38,34,28,.035)` + 包边两值齐备。 **选(用户 2026-09-23 拍板 ③)**:**图版(双线框)+ 纹 + 包边 + 落影**。四成分各司其职:纹是**地基**(无纹则后两者白搭,它让卡片与桌面成为「两种纸」而不是同一张纸的深浅);包边给**厚度方向**(左上有光、右下有影);落影是最强的**实物信号**(硬偏移两层压出「一张纸压在另一张纸上」)。纹走 `paper-sheet.jpg`,桌面走 fiber + grain 两张粗纹 ⇒ **两种纸,不是剂量差**。 **弃**:① **④ 去框版**(纹+包边+落影但拿掉双线框)——材质已能说清「一片纸」,但本物种的身份就是「图版」,框是它的身份;② **票券 / 索引卡 / 裁切标记**(第二轮候选,全部留在 `pin-species-ab.html` 可回取);③ **调色差**(乙·深纸 1.187,治不了);④ **09-19 的「实色深纸无纹」**(本条**显式翻案**:纹理是质感来源不是干扰;该批的纸内白边与报头**保留**)。 **翻案明账**:`lantai-design-spec.md` §11「纸内件(块/纸条/签):无投影,靠遮挡 + 界栏线 + 选中线表达」——钉住块**不是纸内件**(它已离开流、躺在桌面上),落影按「**纸片件**」适用 `--shadow-sheet` 族。§11 该句需同批改写并注明本日期。 **钉值**:待施工(`tests/paper-visual-decisions.test.ts` 钉住段整组重写:双线框几何 + 纹资源解析 + 包边两值 + 落影族引用;旧三条「实色深纸无纹 / 贴平无落影」显式作废)。 **交付口径**:待施工。**注意 `PaperPanel.css` 按 landmine H2 在壳 bundle 里 ⇒ 必须 `cd src-tauri && cargo tauri build --no-bundle` 重建 exe**(先关掉在跑的兰台)。三份台子与走查脚本在 `prototype/`(.gitignore 内,不随仓库分发)。 **真机待验**(owner:用户):① 纹的尺度(900px)与浓淡在真纸上是否合意(现版偏重,纤维与杂质点都看得见,特写像大理石);② 双线框 + 包边 + 落影三者叠加是否过载;③ 落影在密集布局(多块相邻)时是否互相打架;④ 纸条(`.pp-strip`)是否同批跟同一套语言(本批未定,第二轮台子里有四案可看)。 - 2026-09-24 · **机读位复原:机器文本换真等宽(用户拍板 B,翻案 09-10 的「非等宽对齐」代价)**(用户三连:「问题就不是格式啥的了,是字体」→「如果现在用的是 MiSans 的话,看起来不像啊,看起来这几种块的字体明显更粗糙」→ 选定 B「中文也要等宽」)· **病灶两层**:① **真 bug**——UA 样式表对 `` 有**直接**规则 `font-family: monospace`,直接规则压继承,所以 `
` 上声明的 `var(--f-mono)` 从来没到过真正画字的 ``:纸面代码/引文/命令输出一直用**浏览器默认等宽**(中文落宋体·NSimSun、西文落 Consolas 一类)——2026-09-10 换装 MiSans 之后这个错位才显形。
  取证方式 = 把当前构建的 CSS 丢进真实 Chromium,量 `pre` 与 `pre code` 两条 computed font-family:前者 MiSans、后者 monospace(代码查看器倒是早先自己局部绕过了:`.pp-viewer-code-pre code { font: inherit }`)。
  ② **代价条款翻案**——09-10 换装明写「非等宽对齐为拍板接受的代价」,本轮用户选择**付体积换对齐**。
  **选**:**`pre code { font: inherit }` 收成全局口径**(foundation.css;父层没声明就按正文继承,不再落 UA 等宽)+ 机读位换 **Noto Sans Mono CJK SC**(OFL 1.1 随包自托管,`src/assets/fonts/NotoSansMonoCJKsc-Regular.otf` 15.63 MB,**中文也等宽**,只带 Regular——粗体走合成,同「MiSans 伪斜已拍板接受」口径)+ `--f-mono` 与 `FONT_STACKS.mono` 逐字同值(测高/渲染两把尺子必须是一把,新增守卫)。
  **弃**:① 只修 bug 保持 MiSans(= 代码用比例字体、永久不对齐,等于把 09-10 的决定执行到底);② 西文等宽 + 中文回退 MiSans(体积零涨但中文不对齐,用户明确要中文也齐);③ 沿用系统等宽(不随包 = 换台机器就变脸,与「字体随包」纪律冲突)。
  **代价明账**:dist +15.6 MB;粗体是合成的(要真粗体再加 16 MB,未取)。
  **连带**:`--f-mono` 197 处引用全部受益(脚注/程文/表格/查看器/JSON 面);与同日前序的抄录文类回归(`1ec01b65`)合起来才是完整的一刀——前者给机器文本**身份**,本批给机器文本 **face**。

- 2026-09-24 · **匣脚引线纯指示化 + 归因更正**(用户:「你等下的,我从来也没有拍板过引线本体要做成按钮,什么叫『可点溯源』,我从来也没说要做这个来着其实」)·
  **病灶(记录失实,不是代码)**:本账本 2026-09-22 条把「**可点溯源**」写进标题括注当作用户拍板,`lantai-design-spec.md` §9.3 定案第 3 条与 `HISTORY.md` 同批照抄。三条判据说明这条归因站不住:① **用户原话是疑问句**(「为什么我的创作坞在选中一个会话卷的时候,这个引线是可以选中的,怎么搞的这是」)——在他眼里这条线**不该是控件**;② **批内自相矛盾**:同一批的真机待验收清单(`docs/plans/README.md` 匣脚引线行)逐条列的是「线够不够读 / 墨阶 / 切卷读感 / 坞拖走 / 屏外指向 / 纸脚落点 / 与枝边打架」,**从未把「可点」列为待验收项**,反倒把它当既成事实写进第⑤条判据——与 09-21 界栏线条**同型**(待验收项被升格成用户裁定);③ **存档面落空**:`.lantai/sessions/` 全量 `user/message` 事件 168 条中含「引线 / 按钮 / 选中」者 **0 条**,agent 侧文本里也搜不到「版口钮 / 匣脚 / 受墨带」(命中全落在 09-24 读文档那一段)⇒ 该批的施工会话在本存档里**不在册**,账本引作依据的用户原话在存档面无从核对(同 09-21 先例:被引原话只存在于 agent 自写文件)。
  **选(用户口径:引线是指示不是控件)**:① 摘掉本腿的**受墨带**——`role="button"` + `tabIndex={0}` + Enter/Space + `onClick`(飞到线的那一头=纸脚)连同 `onDockTrace` 整条删除;② 摘掉随之而来的两档提升(`hover` / `focus-visible` 各一条兄弟选择器规则),整条删除不留尸体;③ 整层改 **`aria-hidden="true"`**(同 `.pp-pin-layer` 那条瞬时腿):线不进无障碍树、不进 Tab 序、不吃指针,只指示「这一匣对着这一卷」;④ 归因改回事实,落点七处:本账本 09-22 条三处(标题括注 / 定案尾 / 待验⑤)+ `lantai-design-spec.md` §9.3 三处(来由 / 定案 2 与 3 / 证据)+ `PaperPanel.tsx` 与 `PaperPanel.css` 头注 + `dock-tether.ts` 头注 + `HISTORY.md` 新行;⑤ **提交史不改写**(同 09-21 先例 ④:改 `b5f12426` 要 rebase 掉其后全部 commit 的 hash,代价与收益不成比例)。
  **弃**:① **只改记录不摘受墨带**——「可点」本身就是那条假归因的产物,留着等于让记录与界面继续分家;② **保留可点、只摘键盘面**(留 `onClick` 去掉 `tabIndex`)——用户否认的是「把线做成按钮」,不是「按钮做得不完整」;③ **为省一次重建 exe 在 CSS 里留中性死规则**——不留注释尸体是既有纪律,何况本次删的规则因被匹配者消失而恒不命中(见交付口径)。
  **钉值**:`tests/paper-dock-tether.test.tsx` 由 7 例收成 **6 例**——末例「点线 = 溯源:飞到线的那一头」**整条删除**(行为退役 ⇒ 测试同批删除,禁止改造后放回原位);首例尾巴由「常显不是装饰:可点(受墨带)+ 有名字」**反转**为「层内无可命中/可聚焦子件(`[role="button"], [tabindex]` 皆无)+ 整层 `aria-hidden`」。`tests/paper-provenance.test.ts` 该条由「hover 受墨带抬回 .9」反转为「CSS 里不得再出现那两条兄弟规则 + TSX 里不得再出现 `flyToPoint(dockTether.sid…` 与那条 aria-label」。几何 / 锚点 / 切卷 / 拖坞 / 空态五组用例**零改动**——行为未变处零漂移,正是这批改对了的证据形状。
  **交付口径**:改动全在**插件产物**(`paper-shell` 两文件 + `dock-tether.ts` 头注)⇒ `npm run --prefix src-ui build:builtin-plugins` 后由应用自动重载即可见**行为**变化(受墨带随 DOM 消失 = 线不再可点、不可聚焦、hover 不亮)。**但本次删了两条 CSS 规则**:首帧壳 bundle 里留着插件 CSS 的旧拷贝(`dev-workflow.md` 热更「三条边界」条 1),产物 link 只能覆盖不能抹除——旧拷贝因被匹配者(本腿受墨带)已从 DOM 消失而**恒不命中**;要 CSS 面彻底干净仍须 `cd src-tauri && cargo tauri build --no-bundle`(先关掉在跑的兰台,exe 占用报 os error 32)。
  **同类第二刀(同日,用户追问「嗯?会话分支的引线也是可选中的?」)**:枝边那条腿(会话树「枝」,2026-09-19 批)**原也带受墨带**(`role="button"` + `tabIndex` + 点线飞回父卷分叉节点 + hover/聚焦抬墨两档),账上同样没有用户拍板依据(`docs/archive/session-line/session-tree-plan.md` §9「已拍板」表里只有删父连坐 / 分叉点语义 / 枝的 UI 词 / 旧枝考古四条,**没有它**,它只出现在实现表里)。随之整批摘除,并借机把**受墨带那族规则整族删除**(两腿一收,全仓再无消费面):`.pp-tether-hit` / `:hover ~` / `:focus-visible ~` / `:focus-visible` 四条规则 + 只服务它的 `.pp-branch-layer` 一条,一并删净。**代价明账(须记)**:屏幕上「跳回父卷分叉节点」的入口随之消失——卷首眉行那枚「枝」缀字是**纯文本、无动作**,侧栏枝视图只到「行/卷」粒度;要恢复须另立一个**真控件**入口(不复活引线按钮),本轮不擅自发明。测试面:`session-tree-canvas` 由 6 例收 **5 例**(「点线飞到节点」例整条删除),首例尾巴与 `paper-provenance` 族级钉值(受墨带三处规则开头 + TSX 里 `pp-tether-hit`/`onBranchTrace` 皆不得复活)接管「不可点」这条规格。
  **同类未清(已清)**:本条原写「枝边那条腿仍在用受墨带承接点击(待用户裁定)」——同日用户追问后一并摘除,**引线一律不可点**;再无同类尾巴。
  **落账**:commit `5b06ed86`(11 文件 / +142 −171;门禁四门全绿:biome ci 0 · vitest 401 文件 4292 例 · build · doc-check)。
- 2026-09-23 · **代码围栏文类回归:机器输出不再以「正文」块混进正文流**(用户报「为什么我现在正文里面会出现这样的未处理直接渲染的正文块」+ 真机截图)· **病灶**:上一批(`a0076c9f`)为救语法高亮把非差分围栏**回吐** markdown 段——高亮活了,**文类与块形态双失**:`git status` 输出 / 文件内容落 `.pp-md-code` **图码**形态(spec 明说那是「独立 `diff` 块之外幸存围栏的兜底面」——只该给列表/引用里的嵌套围栏),而块 kind 仍是 markdown ⇒ 文类签挂「正文 / AGENT」;一条回执里两块机器输出都顶着正文签。· **选**:围栏一律**独立成抄录块**(kind `diff` = 「抄录 / CODE」:3px 硬左线 + 米黄底图版 + `.pp-lang` 语言签 + 640 宽),块体按语言分流——真差分(diff/patch)走 +/- 着色,其余语言与裸围栏走 hljs 代码体(`.pp-diff-code`,`hljs-*` 墨阶映射的第三消费面);判据 `isDiffLang` 一处两用(转译层分流 + 渲染层分派)。两条路**几何同源**(同一 `
` + 同一语言行 + 同判据 measure;高亮只包 span)⇒ 测高零漂移。· **弃**:① 回吐 markdown 原案(文类双失的根因);② 塞进 `code`/程文 kind(那是**运行中的程序块**——默认折叠 + 属工作单元,会把答案里的代码收起来);③ mermaid 也独立成块(图渲染链路与代码块测高契约挂在 markdown 段的 `MdCodeBlock` 上,独立会与测高镜像脱钩)——mermaid 保留回吐,是唯一豁免。· **遗留**:抄录块的 `--pp-lim-preMaxH`(260px)内滚动帽是 tool/diff/code 共用的既有设计,长机器输出仍是「小窗」(真机截图里 git status 块被滚到底、头部四行看不见)——本批不动,另议。
- 2026-10-08 · **版心改「墨占纸半」:拉宽流区时正文与卷首同比放宽(原封顶 720 退役)**(用户实机反馈:「兰台会话流区里面的内容,在我手动拉宽整个流区的时候,宽度上限太低了」)·
  **病灶(不是审美分歧:封顶写在了错误的地方)**:流区宽自 2026-08-30 起可四角横向缩放(clamp [720, 2160]),但正文块宽 = min(块基准 720, 流区宽 − 240)——**宽流区下恒 720**(注释里叫「可读上限 720」);卷首版心同理封在 720(`folioHeadWidthFor = min(720, 流区宽 − 32)`)。用户拉宽那张纸一倍,墨一动不动——拉宽动作在版面上得不到任何回应(比例失衡到墨只占纸 1/3,与「1440 = 720×2」的初始定案背道而驰)。
  **选(比例守恒 = 初始定案的自然推广)**:**版心宽 = 流区宽 × 0.5**——真源 = `measure.ts` `COLUMN_RATIO` / `columnWidthFor`;流内块宽 = 版心 × (块基准宽 ÷ 720),满版心 / 夹注 0.86 / 来文 0.78 / 工具族 0.89 的从属比例一并守恒。卷首版心盒 CSS 镜像 `min(720px, 100%)` → `width: 50%`(左右内距 16×2 随式退役——版心 = 纸半时永无贴纸缘之虞)。默认 1440 纸下版心仍 720(**视觉零变化**,封顶拆除只在异宽处显形);拉满 2160 → 1080;收最小 720 → 360。
  **弃**:① 单纯抬高封顶值(960/1080 定值)——换个数字继续卡,拉到上限还得再喊一次;② 完全跟随(块宽 = 流区宽 − 240、无上限)——默认 1440 下正文立刻 1200(+67%),把用户满意的现状一并改掉;③ 只改正文不动卷首——2026-09-16「版心天头」立的同轴契约当场破。
  **连带**:① `folioHeadWidthFor` → `columnWidthFor`(消费面已从卷首扩到正文块,名字跟上);② `FOLIO_TOKENS.colW` 退役(版心不再是 token,是本比例的函数);③ **钉住块跳过缩放**(钉块在桌面、脱离流区,宽由 `pin.w` 定格;旧公式窄流区下会把钉块一起压扁——同批修正);④ 顺手修 `state/canvas-store.setRegion` 同值短路漏比 `width`(纯宽度变更被 anchor 比较静默吞掉——「错误不静默」同族)。
  **钉值**:`paper-folio-height` 契约按纸半重写(档位表 720→360 / 1440→720 / 2160→1080,拉宽变矮 / 缩窄变高);新增 `paper-column-width`(用户操作序列:默认 1440 值逐字节不变 / 拉宽两族 1.5× / 缩窄两族 0.5× / 挂载后拉手柄当场跟随 / 钉块定格 500 不动);`session-tree-canvas` 边界算式复核(父卷 extent 右缘随块宽 480→360 收窄,旧 panX −1100 越出 STUB_MX 900 余量 ⇒ 改 −1050,算式入注释)。
  **交付口径**:改动全在插件产物(paper-shell),宿主面 `faceDeps` 零动 ⇒ `build:builtin-plugins` 后应用自动重载即可见,**无需重建 exe**。**待用户实机验收**:拉到 2160 看正文/卷首/图表卡的宽度手感是否合意(嫌宽/嫌窄只需改 `COLUMN_RATIO` 一个数)。

- 2026-10-18 · **让位带换载体:不写 `:root` 内联,改写「只命中消费面」的一条规则(性能批)**(用户报:「『移』激活之后,创作坞的自由拖动过程非常的卡,很明显的一顿一顿的手感」)·
  **病灶(真机 CDP 取证,不是手感分歧)**:让位带 `--composer-band` 由 `use-composer-float` **每帧**写 `document.documentElement.style` 内联——未注册自定义属性落在 `:root` 上 ⇒ Blink 对**整棵文档树**重算计算样式。同机同窗(2560×1400 / 599 元素 / 2542 规则)每帧实测:空帧循环 9.9ms | `:root` 内联本变量 **61.0ms(RecalcStyle 59.3ms)** | 写一个**没有任何消费者**的 `:root` 变量 59.9ms(⇒ 与消费面多寡无关)| 坞自身 left/bottom 内联 10.0ms。真鼠标拖坞 5.4s:**28 次 64~70ms 长任务**、p99 67ms、帧率 75——纵向拖动期实为 ~16fps 的段落式位移,就是「一顿一顿」。
  **选**:值落在**一条只命中让位消费面的规则**上(`.psh-host, .pw-dock { --composer-band: … }`,`composer-band.ts` 自建自有、`dispose` 摘除)⇒ Blink 按选择器定向失效,实测 **0.97ms/帧**;后挂载的消费面(递牒卡/插件造物坞都是出没件)自动命中,不必挂 MutationObserver。变量名与消费面 CSS(`var(--composer-band, 兜底算式)`)一字不改——**只换载体,不换口径**。
  **弃**:① 拖动期冻结、松手才补一次(让位件与坞当场错位、松手跳变,与 10-15 动效法「消灭跳变」正相反);② 逐个元素写内联(0.30ms 更快,但后挂载者要额外补写);③ `@property` 注册(实测与注册无关,`inherits` 亦然);④ 把值写到 `.pp-root`(仍 34ms)。
  **钉值**:`composer-float.test.ts` 新增载体组(建/写/复用/**断连重建**/摘除)+ **名册 vs CSS 实读对拍**(`COMPOSER_BAND_CONSUMERS` 漏登记即红);`paper-composer-float` 与 `composer-dock-rack` 的让位带读数改**行为级**(照真消费者在 `.psh-host` 上读解析后的值)+ 钉「`:root` 上不得再有这个变量」。
  **交付口径**:改动全在插件产物(paper-shell 两文件 + 新增一件)⇒ `build:builtin-plugins` 后应用自动重载即可见,**无需重建 exe**。**修后同法实测**:帧率 100.1、p99 11.8ms、>50ms 帧 0、长任务 **0**。

- 2026-10-18 · **卷开合的动效:落纸 / 起纸(用户拍板「甲 · 入场 + 退场对称」)**(用户:「我在想,卷的展开收起是不是也应该做动效出来才行,现在纯粹是闪现」)·
  **病灶(真机+源码双向核实)**:**开卷** = 纸与字同一帧出现——`.pp-region` 基座只有 `box-shadow` 过渡,激活那两件(拿纸过冲 `pp-region-take` + 卷首朱笔划界 `pp-seal-draw`)是**激活**的动效、不是纸的入场;**合卷** = 区域当帧卸载(`space.collapse → core.closeSession` 把卷从 sess 表摘掉 → `regions` 随即不含它),零退场。且 `seenBlocksRef` 是 PaperPanel **实例级**集合 ⇒ 同一 app 会话里重开一卷连块的 `pp-enter` 都不播(连墨的入场也没有)。§15 的换景收口账收的是「侧栏↔书脊 / 设置页签 / 首页↔画布 / 会话换主」四项——**卷开合从来没立过项**。
  **选**:入场 = 纸淡入 `.pp-region.pp-spread`(`--m-sheet`)+ 墨微升 8px(既有块律 `--m-ink`);退场 = 入场逆写(整叶淡出 + 墨随纸沉 8px,**独立 `translate` 属性**——块定位用内联 transform,声明 transform 会复刻 2026-09-03「块飞到左上角」那次事故),窗满(260ms)才真卸载;窗内重开 = 撤销退场(元素同 key,按当下值掉头)。**纸律**:`.pp-region` 整叶只动 opacity,绝不声明 transform/translate(纸纹相位与 InkLayer 对位红线)。
  **弃**:① 退场不给窗、只让入场有动效(新造一处不对称——批 3b 为一模一样的形态吃过一整批返工);② 入场用 `@starting-style`(流区随虚拟化卸载/重挂 ⇒ 平移时纸面反复「凭空浮现」,§15「首页→画布」那条判据已钉死这条路);③ 入场类按帧发放(摊开卷后同帧还有好几趟重渲染——落位/焦点/测高回写,**实测被当场摘掉 = 浏览器根本没见到那个类**,故改成「窗」);④ 拖动期冻结/让位件跟着走的旧案(本批不动让位面)。**边界**:③ 收口表那两条裁定不变——纸面折叠体仍只能由让位表达、案侧栏折叠面仍是数据层操作。
  **代价明账**:合卷后 260ms 内,纸上的卷与侧栏「已合卷」节、目次带/小地图/匣脚引线有 260ms 视差(面板退场窗早有同一容忍);落纸窗内若该卷被虚拟化卸载再挂回,会重放一次落纸(一过性)。冷启动/恢复工作区首帧整批算「已落纸」(满屏纸一起淡入会被读成一次闪)。
  **钉值**:`tests/region-motion.test.ts`(8 例,纯窗:进窗时机/快照同一引用/窗内重开撤销/窗满摘除/多卷独立/首帧不落纸/**落纸类不被同帧重渲染摘掉**/两窗同长)+ `tests/paper-region-leave.test.tsx`(3 例,真挂 PaperPanel:合卷当帧 `data-leaving`+`inert`+块 `pp-leaving`+**读数面当帧就看不见它**;重开 = DOM 节点身份不变;重播 `pp-spread`/`pp-enter` 且窗满即摘)+ `motion-contract` 新条(`REGION_MOTION_MS` ↔ `--m-sheet` 等 7 项)。
  **交付口径**:全在插件产物(paper-shell)⇒ `build:builtin-plugins` 后应用自动重载即可见,**无需重建 exe**。

- 2026-10-18(续)· **卷开合力度定案:曲线才是主因(用户拍板「丙 · io + 墨 18px」)**(用户实机:「我实机看了一下,实话说,我感觉动效好像不太明显」)·
  **先修一处真 bug**:落纸窗按「卷首次**活跃**」发放,而开卷 = 摊开 **+ 视角飞行 260ms** —— 远卷落地时不在视口里,类在**屏外**就把动效播完了,镜头到时纸已稳稳摊着(用户读数 = 「还是闪现」)。改判据 = 「首次真在**视口里**」(横向 `visibleRegionIds` + 纵向新 `regionOnScreen`),`played` 记已播过的卷(平移扫过不重放 / 合卷离开才允许重播;空首帧不 prime,第一批恢复数据整批算已落纸)。commit `5aeeae22`。
  **再量幅度**:台架 `prototype/region-open-close-ab.html`(真 tokens + 真 `PaperPanel.css` + 真纸纹;五案同帧、`?play=1` 循环播、`?t=` 取单帧)+ `region-open-close-amplitude.py` 量「与落定帧的平均可见变化」(0~255,t=.2/.45/.7 三取):**甲 ease-out + 墨 8px=1.65** | **乙 只换 io=3.99(+142%)** | 丙 io+墨 18px=4.30 | 丁 io+墨 28px/0.34s=4.37 | 戊 丙+纸位移 14px=4.77。
  **判读**:`--m-ease-out` 在 t=.2 就走完 65%、t=.45 走完 94% ⇒ 名义 260ms、**实感 ~90ms**;落幅 8→28px 只再 +10% ⇒ **主因是曲线,不是幅度**(这也是「一上来就调幅度」会白花一轮的原因)。
  **选**:丙 —— 开合两向都走 `--m-ease-io`("对开"曲线本是给开合备的,§15 旧判据只许「两侧同时动」,本批按实测扩到「纸的出现/抽走」);墨落幅 8→**18px**、档 `--m-ink`→`--m-sheet`(与纸同档同曲线=一次动作),`.pp-block.pp-drop` 在落纸窗内**取代** `pp-enter`(同一属性两条动画整表替换)。
  **弃**:甲(实机已否)/乙(只换曲线,局部落幅仍是 8px 的「抽动」)/丁(28px 只比丙多 +1.6%,却更慢)/**戊(纸本体位移 14px)—— 要翻案「`.pp-region` 任何帧不得声明 transform」那条红线,用户本轮没点头,留作下一档**。
  **钉值**:`motion-contract` 的「卷开合两窗」条改为钉「两向 io + 墨 18px + `pp-drop-in` + 卷首同落/同沉 + 纸本体不得声明 transform/translate」;`paper-region-leave` 的「重开重播」改钉 `pp-drop` 且**不得同时挂** `pp-enter`。
  **交付口径**:全在插件产物(paper-shell)⇒ `build:builtin-plugins` 后热更,无需重编 exe。

- 2026-10-20 · **目次带 v4:从「滚动条 + 空带」到「目次栏 + 书口墨影」**(用户「目次带的 UI/UX 需要进行一次迭代,现在还是太简陋了……你来看看有什么可以做的」——**本批是 agent 提案,用户尚未验收**)·
  **病灶(前两条是实测的结构/代码问题,不是审美分歧)**:① **hover 卡塌成竖条**——旧 CSS 只有 `max-width: 260`、定位 `right: calc(100% + 10px)`,在 64px 控制列里可用宽为负,shrink-to-fit 把卡压成 **36.1×249.1**(真 CSS 台同构量得;用户没报过,因为卡根本没有可读性)。② **满宽墨迹是一堵墙**:2026-09-19 甲案把识别层铺到 104px,90 屏长卷里整条带被墨填满,左 64 只剩 26px 的刻痕/锚,右边 40 是空的缘滚跑道——「空了一半」的病灶没解决,只是从「空跑道」变成「空左栏 + 墨墙」。③ **没有目次的读法**:只有匿名横线(无编号/无当前阶段),半透明纸底让纸下正文透上来,带体读作一块浮层而不是一件家具。
  **选(原型三案对比后自定;`prototype/toc-band-v4*.html` / `toc-detail.html` / `toc-real-css.html`,.gitignore 内)**:**两栏 + 编号 + 纸捻**——识别层收回右 40(**翻案 2026-09-21「铺满保留」**),左 64 让给 1px 竖脊 / 阶段规 / 编号 / 纸窗滑块;墨影**右对齐**、族色染剪影但按族增益(人 1 / 工具程文 0.62 / 图表 0.42)、墨量 `0.2 + 0.8×density`、**不留页层缝**;带体改**不透明纸底**(左 paper → 右 paper-deep 48%)+ 硬左缘 + 受光/背光缘,带脚一枚竖排「目次」小签;卡 **268px 定宽** + eyebrow + 2px 语色条 + 右缘缺口,翻转阈 96。
  **弃**:① 甲(满宽墨迹 + 编号并置)——墨墙未除;② 乙(28px 纸捻签条 + 满宽墨迹)——签条与墨墙互相抢;③ 2px 族色缘线(贴 seam 的彩色细线)——形似 2026-09-21 用户否认的界栏线,弃;④ 2px 条 + 1px 页层缝——1x 下是扫描线噪声(原型 1× 实测)。
  **代价明账**:翻案 09-21 的「识别层铺满保留」;长卷剪影横向分辨率 104 → 40px(靠右对齐的参差 + 编号补足);带体不透明后压住纸下正文 104px(原也读不到,但视觉上更实)。
  **钉值**:新 `tests/stage4-toc-v4.test.tsx` 6 例(卡定宽回归 / 两栏 / 编号自适应 + active / 卡片语色 / 纸窗抓手 / 骨架惰性)+ ink 层 `density` 例;旧 `stage4-toc-top-band`(加宽/跑道/摘线)与 `stage4-toc-stage-anchor-layer`(可点/装饰分家)**几何与裸行为逐字未动**——只改了卡片文本断言(行为变更:正文拆成 eyebrow + body)。
  **交付口径**:组件(`compose-dock`)可热更;CSS(`PaperPanel.css`)在壳 bundle ⇒ 真机看新样式须 `cargo tauri build --no-bundle`(landmine H2)。
  **真机待验(owner:用户)**:① 两栏翻案是否合意(编号占左栏、墨影只 40);② 墨影浓淡(族增益与 0.2+0.8×density);③ 编号密度(长卷自适应省号够不够读);④ 不透明纸底 + 硬左缘 + 自挂纸纹是否够「纸捻」;⑤ 纸窗滑块 + 右缘抓手是否好抓。
  **v4.1 实机修订(2026-10-20 晚,用户真机三条)**:① **「墨影并不存在」**——canvas 是 replaced element,CSS `width:auto` 用**固有宽 300**(不是解 left/right),组件按 `clientWidth=300` 右对齐画,墨影整条到屏外;**改死宽 40**(`TOC_W − TOC_COL_W`)。② **「纸捻材质没生效,纯色底」**——canvas 态 `foundation.css` 隐去文档级 grain(`body:has(.pp-root)`),首版只给 48% 渐变 + 1px 缘;**纸口拉到 78% paper-deep + 2px 受光/背光 + 10px 内影 + `::before` 纸纹**(同书脊列四层配方;`z-index:-1` 在底色上、子件下,**不是界栏线**)。③ **「目次字样拿掉」+「顶部也留空隙」**——带脚小签 CSS/DOM 双删;`STRIP_TOP` 4 → **56**(= 顶部浮件带高 8+40+8),与底对称留白,刻痕盒顶 52。**钉值同步**:v4 断言 `.pp-toc-ink` 含 `width: 40px` 且不含 `width: auto`、无 `.pp-toc-colophon`;`stage4-toc-top-band` 改钉 `STRIP_TOP === TOP_CHROME_BAND`(56)与 `STRIP_TOP − MARK_HALF === 52`。
  **落账**:`npm run build` 0 · 全量 vitest **428 文件 / 4546 例全过** · 改动面复跑 11 例全过 · `biome ci` 0 errors/0 warnings(2 条既有 info)· `doc-check` ok。**未 commit**(用户未要求)。

- 2026-10-21 · **创作坞 P0 精修:五条硬缺陷先落(用户「开P0」)**(用户判「基本 UI/UX 已经不错,但停留在不精致」;agent 逐状态实机体检后提出 P0/P1/P2 三档,用户取 P0)·
  **病灶(全是实测量,不是审美分歧)**:① **空输入也挂原生滚动条**——`autoGrow` 只写 `scrollHeight`,border-box 下 `clientHeight` 少 1px(实测 39/38),叠上 `foundation.css` 的 `* { scrollbar-width: thin }`(Chromium 121+ 标准属性压过 `::-webkit-scrollbar`)⇒ 白条带上下箭头常驻;② **空印假主动作**——空输入时「拟文」仍是全坞最重墨块,`onSend` 第一行 `if (!t) return`;③ **浮层出屏**——坞浮动化后可停上半屏,八本浮层仍写死 `bottom: calc(100% + N)`,实测坞在 y=120 时墨量册 `top:-159px`,标题/读数整块看不见;④ **选中语言第三色**——`.ms-item.selected` 用 `--seal-soft` 粉洗(§11 明令退役),且选中行无朱砂左脊;⑤ **热区偏小**——移/翰/律 21×23、墨/役高 22,单字钮无 `aria-label`。
  **选**:① 输入框 `autoGrow` 补 `offsetHeight - clientHeight` 再夹 144;输入框 `scrollbar-width:none` + WebKit 隐藏;删全局 standard 属性侧(纸面自定义条全应用复活)。② 空印改空心禁用(`--ink-4` 边 + `--ink-3` 字、去 `--shadow-anchor`),`title` 改「先落笔,再拟文」;有字回墨印,运行中空输入仍由停钮接管。③ 槽主人(`useComposerFloat`)按坞顶判 `composerPopSide`(上半屏 ⇒ down),下发 `data-pop-side` + `--dock-room-up/down`;`PaperPanel.css` 统一换向(4/6/8 间隙分组保留)+ `max-height: min(70vh, 原上限, 所选侧余量)`——**坞本体一字不知**。④ 选中行归队 `--sel-wash` + `inset 2px 0 var(--seal)`;`selected:hover/active` 仍走 `--paper-deep` + 脊(两层信号)。⑤ 伪元素 `inset:-4px` 撑命中面(`.pp-dock-tools` gap 6→8 防叠压;模型触发器 `min-height:28px`),移/翰/律与墨/役补完整 `aria-label`。
  **弃(留 P1,需用户拍板)**:字号下限(模型名 9px / 分组头 9px / 律册键 11px)、朱砂红预算(厂商 16px 实心红块)、左侧轴线(标题 x=911 vs 输入正文 x=997)、模型触发器 150px 截断、文件 chip 石青蓝、翰/律/役 的 IA 重排——这些是视觉口径,不在 P0 偷跑。
  **钉值**:`tests/composer-p0-polish.test.ts` 9 例(CSS/接线)+ `composer-dock-rework.test.tsx` 空印禁用 1 例 + `paper-composer-float.test.tsx` up/down 1 例 + `composer-float.test.ts` 朝向纯函数 2 例。**部署面**:`composer-dock` 产物可热更;`PaperPanel.css` / `foundation.css` 在壳 bundle ⇒ 真机看新样式须重建 exe。

- 2026-10-22 · **创作坞 P1 视觉系统:字号下限 / 红蓝预算 / 左轴 / 模型名 / 纸签**(用户 P0 重建验收「看起来没啥问题」后「开P1」;两条预告需拍板的项按下述取舍自定)·
  **病灶**:① **主次倒置的字号**——模型菜单机器 id 10px 比人读名 9px 还大,且 9px 落在「瞎眼档」;分组题 9px 全大写 mono;律册键位 11px 石青;引路径 10px 淡墨;文件签 10px 石青框(浏览器 tag 语汇);② **朱砂通胀**——16px 实心朱砂厂商方块是坞内最响的红之一,把「全放」底线/拟文印/版口钮/引线的朱砂语义冲淡;③ **三条左缘**——标题/设置行 x=911,输入正文 x=997(引/夹顶开 88px);④ **模型名读不全**——150px 定宽把「DeepSeek V4.1 Flash (latest)」截成「DeepSeek V4.1 Fl...」;⑤ **字号缩放只作用于一半**——输入框/标题吃 `--font-scale`,模型/权限/思考/墨/役写死 px。
  **选**:① 模型菜单 name 12/600/ink-1、id 10/ink-3、分组题 11/600/ink-2(song、去全大写/0.2em 字距);「视」8→9;律册键 12/ink-2、引路径 11/ink-2、文件签 11、脚注/图例/账目副行 10→11;设置行全部吃 scale。② 厂商章改纸色底 + ink-2 字 + 1px ink-4 框(分组头 14 同款)——红只留人的动作/身份件。③ 输入行 DOM 重排:`textarea → 附件/附图 → 引/夹 → 拟文`(翰/引浮层仍 absolute,不入轴)。④ 模型触发器 150→215,名称抬 600/ink-1。⑤ 文件签改纸签(11 mono/ink-2/发丝框/纸色底,hover 转朱砂);律册键与翰快捷键去石青;组合芯片只读 ink-3→ink-2。
  **弃(留 P2)**:不动版心/三行制/设置行归堆/朱砂主动作;不重排翰/律/役 的 IA;模型菜单 300×260 几何不动(内容变高后照常滚)。
  **钉值**:`tests/composer-p1-polish.test.ts` 8 例(字号/主次/红蓝/缩放/焦点)+ `composer-dock-row-order.test.tsx` P1 左轴 1 例(textarea 首个布局件、引/夹在其右、拟文最右)+ `model-selector-compact.test.tsx` 目录外 provider-scoped id 去前缀 1 例。**部署面**:模型菜单/组合芯片/ComposerDock 产物可热更;`PaperPanel.css` 在壳 bundle ⇒ 真机看字号/纸签/左轴/厂商章须重建 exe。

- 2026-10-22 · **创作坞 P2 信息架构:翰归全局面板 / 律分组 / 役空态收口**(用户 P1 验收后「开P2」)·
  **病灶**:① **翰是第二份命令清单**——坞内 `.pp-slash` 无搜索框、无分组、只列 slash 命令,而 Ctrl+K 全局面板已有搜索 + 分组 + 动作/插件命令;两处同源(listCommands/executeCommand)却两套呈现,用户点翰得到的比 Ctrl+K 少。② **全局面板是观测台材质**——`--glass-hi` + `backdrop-filter: blur(16px)`,与纸壳「不透明纸 + 发丝线 + 墨影」不是同一个世界。③ **律 13 行等权平铺**——键位/释义不分场景,读起来像一张表单。④ **役空态说了三遍「在役」**——`0 在役 · 0 已了` / 大号 `0` + 在役 / 段题「在役」/「本卷无在役」。
  **选**:① 翰只做 `setPaletteOpen(true)`(全局面板 = 搜索/分组/动作与插件命令);坞内 `menuOpen`/`effectiveSlashQuery` 整组删除,`/` 仍走内联斜杠面板;全局面板回纸(去 glass/blur,`--paper` + `--rule-head` 头线,组题 11/600 去大写,行 13,脚/kbd 11)。② 律分四组(输入/附卷/画布/纸面),组题 = 6px 方墨 + 10px/600/0.18em,组间弱线;行数据逐字保留。③ 役零在役只出「本卷无在役」+ 一行「子代理与后台命令会在这里出现」;大号读数/计数/段题只在 `running > 0` 时渲染;头部计数只在有在役或已了时出现。
  **弃**:未改 `/` 内联面板的键盘路径;未改翰/律/役 触发钮与热区;未改全局面板的动作源(listActions + session commands + plugin contributions)。
  **钉值**:`composer-dock-desk.test.tsx` 14 例(翰只开全局面板、不再生 `.pp-slash`;`/` 仍走内联并执行;律四组题名)+ `composer-dock-work-ledger.test.tsx` 12 例(空态一句 + 去处说明 + 无大号 0/无「在役」段题)+ `composer-p2-ia.test.ts` 5 例(pal-box 回纸/去 blur、组题/行/脚字号、翰接线、役空态接线)。**部署面**:ComposerDock/WorkLedger 产物可热更;`shell.css` 与 `PaperPanel.css` 在壳 bundle ⇒ 全量真机须重建 exe。