| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(backup): 全库备份的默认文件名不再带空间名(原来会写着「数友标尺」,内容却是整套)+ 时刻改本地时间 现场(owner 2026-10-19 真机):默认名 shuyonote-数友标尺-2026-10-19-02-50-26.zip。 两处都不对: ① 名字里出现**当前活动空间名**(api.getWorkspaceName())—— 而 export_backup 导的是**整机全库**(meta.db + **所有**空间库 + 附件)⇒ 名字说"只备份了数友标尺",内容是全部 ⇒ 误导; ② 时刻来自 toISOString()(**UTC**)⇒ 北京时间 10:50 会被写成 02-50,差 8 小时。 修法:改中性名 shuyonote-backup-<本地时刻>.zip(与自动备份同前缀),时刻用本地 getFullYear/getMonth/... 拼;顺手删掉那处无用的 getWorkspaceName 读取。 判据:backupButtonName.test.ts 三条 —— ① 文件名不许带空间名/不许读 getWorkspaceName、必须是 shuyonote-backup-${stamp}.zip;② 不许出现 toISOString、必须取六个本地时间字段;③ 备份内容仍是全库(仍调 api.exportBackup(path)、界面仍写「全库」)。 读数:tsc 0;test-report 65 条门禁全绿。 | 19 小时前 | |
fix(crdt): 外部写后播种 CRDT 状态,并阻止旧会话回写(R155) - applyDraftAndRefresh:落库后用 stateForExternalWrite 播种 page_crdt,回读校验并写 apply.log - Editor:外部写 3 秒窗口内 / 会话已卸载时跳过陈旧状态落盘(防约 150ms 回写覆盖) - useExternalDrafts/externalDrafts:独立页窗口不再应用外部草稿,只按需重载 - 新增 seedExternalWrite 执行体与判据;r155Seed 注释更新为「已接线」 | 2 天前 | |
fix(crdt): 外部写后播种 CRDT 状态,并阻止旧会话回写(R155) - applyDraftAndRefresh:落库后用 stateForExternalWrite 播种 page_crdt,回读校验并写 apply.log - Editor:外部写 3 秒窗口内 / 会话已卸载时跳过陈旧状态落盘(防约 150ms 回写覆盖) - useExternalDrafts/externalDrafts:独立页窗口不再应用外部草稿,只按需重载 - 新增 seedExternalWrite 执行体与判据;r155Seed 注释更新为「已接线」 | 2 天前 | |
feat(export): 编辑器工具栏加「一键导出 Markdown + 附件(.zip)」 **为什么**:V1.1 那笔只把 zip 导出挂进了**命令面板**两格 ✗ —— 而 owner 最初要的就是 **编辑器工具栏那一键** ✓(1.92.13 的"导出为 Markdown"就在那儿 ✓)。这一笔把同一个能力放到同一处 ✓。 **加了什么**: `` · EditorToolbar.tsx::exportMarkdownBundleFile —— 与既有 exportMarkdownFile **并存** ✓: 同一份页面快照(api.getPage ✓)+ 同一层取正文(docJsonOfPage ✓,⛔ 不在组件里写存储列名 ✗) ⇒ 调 exportMarkdownBundle.ts::exportPageBundleToZip ✓(zip = <标题>.md + assets/<hash>.<ext> ✓) · ⋯ 菜单里新增一格「导出为 Markdown + 附件(.zip)」 ✓(纯 .md 那格**一字未动** ✓) · i18n:editor.exportMarkdownZip 中英各一条 ✓ ` **判据(本机实测)**: · tsc --noEmit **0** ✓ · exportMarkdownBundle.test.ts 16 + exportMarkdown.test.ts 7 ⇒ **23 passed** ✓ · check-doc-content-access **exit 0** ✓(新代码经 docJsonOfPage 取正文 ✓) · check-web-commands ✓(⛔ 没新增后端命令 ✗ —— write_binary_file 是现成的 ✓) ⚠️ 如实交代(与 V1.1 那笔同一批未验项 ✓):**桌面壳真实落盘没实跑** ✗(dialog.save + write_binary_file` 只有单测替身 ✓);**Web 真实下载**也没实跑 ✗(保存对话框在浏览器里是系统文件选择器,自动化点不到 ✗)。 ⇒ 这两条要 owner 在真机点一次 ✓;一旦有问题,报错会**如实显示成"导出失败:…"**(不静默 ✓)。 | 2 天前 | |
feat(sync): 跨网订阅面板收口 —— 中继只讲连接,许可证读数搬到订阅一节;补粘贴框;版式整理(owner 拍 A +「美化」) A 的理由(owner:「中继和跨网订阅不是一回事?」):中继是**通道**(连上没有),订阅是**资格**(能用多久),两者靠"租约"接起来。旧界面拆两节、各说一遍"你还没配" ⇒ 同一件事说两次;而且「中继许可证」那一行与订阅状态是同一张卡的两半读数。 改动:① RelayStatusSection 只留连接 + 重新检查(许可证读数搬走);② LicenseSection 接管"我能用多久"(五态胶囊沿用 is-ok/is-warn/is-bad/is-muted 那套颜色语义),并在**确有新信息**时补一句「中继侧还读不到有效期」;③ **修掉重复**:没配发卡站 ⇒ 整块只留一行(用后端那句 why,不再自己拼前缀);④ **补上粘贴框**(旧文案让人"粘贴"、界面却没有输入框),解析失败按码说人话;⑤ App.css 加 20 行版式(不新造颜色)。 判据:license/uiText.test.ts 10 条;relayStatus.test.ts ③ 改成钉"许可证读数已搬走 + 连没连上仍要说"。 读数:license 46 条 · relayStatus 4 条全绿;tsc 0;test-report 65 条门禁全绿。 | 1 天前 | |
feat(export): C 弹窗合并 —— 两个新入口(「导出当前页…」「导出本空间…」)+ 一个带预估的导出对话框 owner 的 C 方案:命令面板里原有四条导出命令,用户得先想"我要哪种形态"。现在另给**两个统一入口**, 点开同一个对话框:先看**预估**,再勾三件事,由执行层一把导完。 ⛔ 四条旧命令**一条没删**(owner 真机验过新入口再收 —— 不做"先删后补" ✓)。 - 新浮层 components/MarkdownExportDialog.tsx: · ☑附件(打包 zip)/不勾 ⇒ 只产出 .md;☐元数据 YAML(title/id/kind front matter); ☐纯 .md 平铺(不按页面树建目录) · 预估行用现成的 estimateBundleText(新增 estimateExportScope 供数据:不读附件字节、只问列表; 大小未知的照实另说,⛔ 不当 0 ✗) · **登记进返回栈** useOverlayLayer("markdownExport", …) + 滚动锁 —— check-overlay-registry 28/28 ✓ (容器类名复用 .confirm-overlay / .confirm-box 的既有几何,⛔ 不新增未验的 -overlay/-popover ✗) - 新执行层 lib/exportMarkdownDialog.ts:读哪些页 → 弹保存对话框 → 写 zip / 写 .md → 说人话; 不带附件时正文里的 attachment:// **原样留着**并在消息里报数(⛔ 不改成坏链接 ✗) - lib/exportMarkdownBundle.ts 加三个**可选**能力(缺省 ⇒ 老行为逐字不变 ✓): planBundle({flat, yaml}) / flatPaths() / yamlFrontMatter() + pageFileHeader(); prepareBundle 导出(返回 files);estimateExportScope;startExportProgress / bundleMessage 对外开放 - 两个入口在 plugins/builtinCommands.ts(只打开浮层,⛔ 不碰执行逻辑 ✗);App.tsx 常驻渲染浮层 - 判据:lib/exportMarkdownDialog.test.ts(zip/纯 .md/平铺/YAML/取消/失败 共 11 条)/ lib/exportMarkdownBundle.test.ts +8 条(flatPaths、yaml 头、预估去重与未知大小、清单列不出来)/ store/exportDialog.test.ts 4 条 / components/markdownExportDialog.test.tsx 5 条 (真渲染:**返回栈里登记了**、预估行、勾选项原样传给执行层、关闭后不留幽灵层) ⚠️ 移动端几何:本弹窗复用 .confirm-* 那套已量过的几何,但**验收脚本没有单独打开它** ⇒ 属未验证项(不是"验过了"✓)。 | 2 天前 | |
feat(ai): LLM Wiki 草稿可「采用为页面」—— 只新增一页、自带派生标记与来源;生成/采用计数上本机 口径:采用是唯一写库的一次点击(createPage,不 update/delete 任何已有页);页脚「派生,非出处 | 模型 | 时间」、覆盖度、来源清单随正文落库;打 llm-wiki 标签。失败如实报错且草稿不动。计数落在 localStorage(只本机、不上报),面板显示采用率 —— 需求 §8「采纳率」那行从此可量。 | 2 天前 | |
feat(template): 模板卡片预览用模拟值替换占位符 + 支持 owner(创建时替换) | 1 个月前 | |
fix(editor): 照文档逐条按键,修掉两组静默失效的快捷键 问的是"文档里说的快捷键你能测吗",于是照 src/lib/shortcuts.ts 逐条按了一遍。结论是 25 条都能测——同时发现两组功能一直是死的,根因同一个:按键注册在 Lexical 优先级的 **最后一档**。 1. InsertShortcutPlugin(Ctrl+Alt+1/2/3/U/O/T/Q/C/L/M 共 10 条,文档「编辑器」组)把 KEY_DOWN_COMMAND 注册在 COMMAND_PRIORITY_EDITOR。Lexical 的队列是 CRITICAL > HIGH > NORMAL > LOW > **EDITOR(最后一档)**,而 Lexical 自己那支 $handleKeyDown(由 RichTextPlugin 在 **layout effect** 里装进编辑器)就在那一档, 且对**每一次** keydown 都 return true。插件在 useEffect(被动 effect,永远晚于 layout effect)里注册,于是永远排在它后面——同档的后来者一次都收不到事件。用户按 Ctrl+Alt+1 的表现是"什么都没发生"。改用 COMMAND_PRIORITY_LOW(与已经在用的 SlashMenuPlugin / ImagePastePlugin 一致)。 2. PageLinkSuggestPlugin 踩的是同一个档:[[ 菜单的 ↑/↓/Enter/Esc 全收不到,菜单开着 时按 Enter 不是选中候选而是换行——菜单等于只能用鼠标点。同因同修。 3. 顺手修掉斜杠菜单的分组标题重复:菜单按"同组相邻"推断标题(option.group !== lastGroup 才插一条),而后来追加的「帮助」落在「表格」之后,收尾顺序成了 …嵌入 → 基础 → 嵌入 → 引用,于是菜单里「基础」「嵌入」各出现两次(React 还报 duplicate key)。把这两条挪回 各自的分组块,分组改成连续。 测试(25 条全覆盖,都断言行为而不是"注册成功"): - insertShortcut.test.ts:真编辑器 + 真 dispatchCommand(KEY_DOWN_COMMAND, …),十条逐条 断言 preventDefault 与块类型/标签,外加守卫(带 Shift、缺 Alt 不许抢)。坑记一笔: handled **不能**当作"插件认领了"的证据——Lexical 那支总归会 return true,能区分 "我们认领"与"被吞掉"的只有 defaultPrevented。 - editorInputShortcuts.test.ts:Markdown 行首语法**逐字输入**(一次输入整串会被 Lexical "只处理刚敲的那一个字符"的启发式跳过,探针踩过一次)、/ 斜杠菜单(含分组标题不重复)、 Ctrl+F 查找条、空行空格开 AI(含"有字的行不许抢")、[[ 菜单 ↓/Enter 插入。 - overlayShortcuts.test.ts:Ctrl+K 开合命令面板、Esc 关浮层。 - src/lib/shortcutCoverage.test.ts(闸门):清单每一条都必须指到一个**真存在**的用例 (映射表里的用例标题要去那个文件里真的找得到,且在 it(...) 里);InsertShortcutPlugin 的 if (key === "x") 分支与文档「编辑器」组**双向**一一对应;src/editor/plugins 下不许 再把 KEY_DOWN_COMMAND 注册到 EDITOR 档。三条都用植入式变异实测过:加一条没人测的快捷键、 改掉被指到的用例标题、给插件加一条文档外的分支,闸门逐条报出来。 - src/test/lexicalWarnings.ts:只静音 Lexical dev 构建那条 updateEditorSync 警告(用 只挂 Lexical 自带 MarkdownShortcutPlugin 的探针确认过:不挂本仓库任何插件也照样打), 其余警告原样透出。 为什么此前没拦住:这两组功能**注册成功、清单也一致**,当时的全部检查(vitest 纯函数、 tsc、cargo test、门禁、作者 CLI)都不看它们有没有真的收到事件。 验证:vitest 294(+26,37 文件)、tsc、smoke-web 350、pnpm build、cargo test 165 全绿。 | 1 个月前 | |
refactor(mobile): 移动端外壳(第一刀:纯重构、零视觉变化)—— 为底栏铺路 owner 拍「移动侧边栏 → 底边栏(笔记/搜索/听/我的)」⇒ 拆三小刀,本刀是①纯重构:不加底栏/不加浮+/不删任何东西 ⇒ 零视觉变化。 · App.tsx 加 const wrapMobile = (body) => <div className="m-tabshell">{body}</div>;(:951)+ 两处各包一次(settings :1233/最后一支 :1250) · App.css 加 .m-tabshell { display:flex; flex-direction:column; flex:1; min-height:0 }(⚠️ 没加 padding-bottom —— 留白跟底栏同一刀) ⭐ 实现者否掉了 Lead 的「提成一个变量」、而且否对了:settings 支排在 aboutOpen/currentId 之前(阶段 2 定的), capture/search/home 在最后 ⇒ 合并挪位会改变行为(开着笔记时进设置会被阅读屏抢走)⇒ 改成外壳定义一次+两处各包一次 ⇒ 零行为变化、也没有第二份外壳。 判据(Lead 亲跑):tsc 0 ✓|类名门禁 ✓|死屏门禁 ✓ 可达 8/登记 10(与改前一致 ✓=本刀关键判据)| mobile-layout 70/0 ✓|mobile-views 249/0 ✓|三屏都还能进(Chromium 390×360 逐屏读数 ✓)。 ⚠️ 实现者自报两处自伤并修好(function App() 锚点/三元里写了 {} ⇒ tsc 抓到)。 ⛔ 不碰 SyncPanel.tsx ✓/版本/CHANGELOG/gen/** ✓ | 16 小时前 | |
refactor(mobile): 移动端外壳(第一刀:纯重构、零视觉变化)—— 为底栏铺路 owner 拍「移动侧边栏 → 底边栏(笔记/搜索/听/我的)」⇒ 拆三小刀,本刀是①纯重构:不加底栏/不加浮+/不删任何东西 ⇒ 零视觉变化。 · App.tsx 加 const wrapMobile = (body) => <div className="m-tabshell">{body}</div>;(:951)+ 两处各包一次(settings :1233/最后一支 :1250) · App.css 加 .m-tabshell { display:flex; flex-direction:column; flex:1; min-height:0 }(⚠️ 没加 padding-bottom —— 留白跟底栏同一刀) ⭐ 实现者否掉了 Lead 的「提成一个变量」、而且否对了:settings 支排在 aboutOpen/currentId 之前(阶段 2 定的), capture/search/home 在最后 ⇒ 合并挪位会改变行为(开着笔记时进设置会被阅读屏抢走)⇒ 改成外壳定义一次+两处各包一次 ⇒ 零行为变化、也没有第二份外壳。 判据(Lead 亲跑):tsc 0 ✓|类名门禁 ✓|死屏门禁 ✓ 可达 8/登记 10(与改前一致 ✓=本刀关键判据)| mobile-layout 70/0 ✓|mobile-views 249/0 ✓|三屏都还能进(Chromium 390×360 逐屏读数 ✓)。 ⚠️ 实现者自报两处自伤并修好(function App() 锚点/三元里写了 {} ⇒ tsc 抓到)。 ⛔ 不碰 SyncPanel.tsx ✓/版本/CHANGELOG/gen/** ✓ | 16 小时前 | |
fix(ui): 启动页的版号改由应用运行时填 —— 去掉那处**硬编码且已过期**的「1.92.6」(阶段 3 相关) 来由 ✓:阶段 3 侦察时读到 index.html:317 逐字 <div class="splash-version">版本 **1.92.6**(开发)</div> ✗ —— **硬编码**且**已过期**(当前 1.92.11 ✓)。它是**唯一**一个不随版本文件走的版号消费点 ✓ (其余消费点——UpdateBanner/SettingsDialog/AboutDialog/MobileAbout——都走 src/lib/links.ts:10 的同一来源 ✓)。 一、改法(⛔ 不引入第二份事实源 ✗) · src/main.tsx ✓:**模块作用域**(deferred module ⇒ DOM 已解析 ✓)加三行 ⇒ const sv = document.querySelector(".splash-version"); if (sv) sv.textContent = \版本 ${APP_VERSION}(开发)\; ✓ ⇒ 来源=既有的 APP_VERSION(src/lib/links.ts:10 ✓,读 package.json 的 version ✓) · index.html:319 ✓:那格改成**空占位** <div class="splash-version"></div> ✓ ⇒ **显示用版号字面量 = 0 处** ✓ + ⭐ 顺手**更新了它上方那段已过期的理由注释** ✗(原话"这里只能写字面量…会随发版漂移 ✗,要根治得动 index.html 以外的文件"✓ —— 那句**已经不再成立** ✓;留着它就是"两份真相源"的雏形 ✓) · ⚠️ 兜底(如实 ✓):**JS 没跑起来**(白屏/极慢)⇒ 那格是**空的** ✓ —— ⛔ 比显示一个**错号**好 ✗ 二、验证(真 Chromium ✓) `` early: 存在 ✓ 文本 = 「版本 **1.92.11**(开发)」✓(与 package.json 一致 ✓ —— 不再是 1.92.6 ✓) later: 不存在 ✓(splash 挂载后被摘掉 ✓ ⇒ 行为照旧 ✓) 静态:grep -cE '>[[:space:]]*版本 [0-9]+\.[0-9]+\.[0-9]+' index.html ⇒ **0** ✓ ` ⚠️ 途中两次**自纠**(如实记 ✗):① main.tsx 的锚点在文件里出现 **2 次** ✗ ⇒ 断言拦住、**没改上** ✗ ⇒ 一度是"**版号删了但没人填**"的半截 ✗ ⇒ 下一次调用立刻补完 ✓;② 补完时落进了 hideSplash() 开头 ✗ (=**摘掉 splash 前一刻才填** ✗ ⇒ 整个启动页期间那格是空的 ✓)⇒ 随后**挪到模块作用域** ✓。 两次都是**自检/读数**当场发现的 ✓。 三、判据(Lead 亲跑 ✓) · tsc 干净 ✓ / test-report **63 条**(⚠️ 只余那 **2 条版本**红 ✓ —— windows 侧发版中间态 ✓,⛔ 非本笔 ✗) · mobile-layout / mobile-views / mobile-overlays 见提交输出(⛔ 本笔改了 index.html=**app shell** ✓ ⇒ 三条都该跑 ✓) + check-mobile-screen-reachable ⇒ ✓ 干净` ✓ | 5 天前 | |
fix(启动卡死): Prism is not defined — 显式导入 prismjs 并设全球 Prism,满足 Lexical code-core 引用 | 1 个月前 | |
feat(mcp): 跨空间只读 —— 「只读(全部空间)」档 + pages_search/pages_list 的 spaceId(不动活动空间) owner 2026-10-18 选的 C 方案。起因是评估里那条"跨空间检索是硬伤":外部 agent 想知道 "焦煤的材料在哪",而实测要 6 次调用 + 2 次 spaces_switch 才能找到一篇已知存在的文档; 更糟的是 spaces_switch 要 write:pages ⇒ **只读令牌根本跨不了空间**,而切换还会改用户界面。 ## 授权模型:新 scope read:all-spaces(不进注册表权限) · 为什么不进注册表:check-capabilities 要求"每条权限至少被一条能力用到",而它是 **同一批能力上的附加条件**(两个能力的 spaceId 参数),放进去就是"死权限"✗; · 它是**令牌上的 scope**:只有面板「只读(全部空间)」那一档会给;插件 manifest **声明不了**(不在注册表里)⇒ 插件面照旧跨不了空间 ✓。 ## 档位:四档 → 五档 · McpLevel::ReadAll:读三项 + read:all-spaces,allow_write=false、write:pages 一定不在; · 换档会**收回**这个 scope(⛔ 不靠"以前给过"留着 ✗);换档照旧换令牌; · 面板加「只读(全部空间)」一档,文案说清"能读别的空间、仍然不能写、也不改你正在看的空间"。 ## 能力:spaceId(可选) · pages.search / pages.list 都加了这个参数;宿主走**独立只读连接**(open_space_conn), 活动空间与 with_read_conn 那条路**一个字节不动**; · 目标空间**必须先真的存在**(先查 meta):⛔ 不能先 open —— 那会给一个拼错的 id **新建空库** ✗; · 没有 read:all-spaces ⇒ permission_denied 并点名缺哪条(⛔ 不静默降级成当前空间 ✗); · MCP 信封里的 scope 取**这次真正搜的那个空间**(不是活动空间)——否则"搜 A 说 B"比没信封更糟; · 空结果提示:没给 spaceId 时,hint 里加一句"已获授权可直接带 spaceId"。 ## 前端(AI/插件那一面) · pages.search 带 spaceId ⇒ 走全空间检索(候选给到上限 200)再按 workspace_id 筛 (命令面没有"只搜某个非活动空间"的入口); · pages.list 带 spaceId ⇒ 走 api.listWorkspacePages;两边排序/字段与 Rust 一致。 ## 判据与读数 · Rust:cross_space_read_needs_the_scope_and_never_touches_the_active_space(无授权拒 / 有授权命中另一空间 / list / 不存在的空间 bad_arg / 信封读数是目标空间); the_five_levels_map_to_exactly_three_fields(五档表 + 换档收回 scope)。 全量 cargo test --lib:**1106 passed / 3 failed**(community_publish ×2 与 sync_stream, 均为既有问题)。 · TS:pagesSearch 的 spaceId(200 候选 + 全空间 + 筛)、pagesList 的 spaceId (走 listWorkspacePages)、面板五档文案 —— vitest 71 passed(本次三组);tsc 0 错。 · 门禁:capabilities / generated / doc-links / doc-content-access / mcp 四条 / kb-s1 / ontology 全绿。 ## 没做 · 审计行里加"读了哪个空间"(审计形状是 check-audit-shape 钉住的,改它要单开一片); 当前靠信封的 scope.spaceId 让调用方与日志能对上。 · 别名表、kind(容器页)、向量:仍按前一轮的结论等输入/读数。 | 1 天前 | |
refactor(vault): 锁屏文案精简(owner 拍 C「全都压」)—— 四句压成一句,七个要点一个不丢 owner 截图:「放弃打开这个加密空间?」那段**四句说一件事** ✗(换过去马上就能用/换过去只是先不打开它/ 解锁前读不出来/随时可以切回来)⇒ 压成**一句 + 一个问句** ✓。 五处(逐字照 Lead 给的改法 ✓): - ① 顶部: 本机笔记已使用端到端加密保护。输入口令解锁后才会加载内容。 → 本机笔记已端到端加密,输入口令后才会加载。 - ② 放弃打开那段:**四句 ⇒ 一句 + 问句** ⇒ …本机还有 {N} 个空间没有加密 —— 换过去马上就能用,不用输这里的口令;随时可以切回来。 ⚠️ {otherSpaces.length} 那个**具体读数留着** ✓ - ③ 忘记口令导语:口令不存本机、不上传服务器,只由你脑子(或密码管理器)保管。 → 口令只由你保管(不存本机、不上传服务器)。 - ④ 三条 <li>:各压到一行 ✓ ⭐ **三个要点一个都没丢** ✓(连服务器那份也打不开/唯一可能是开加密**之前**的明文备份/ 没有那样的备份 ⇒ **永久取不回来**) - ⑤ 脚注:砍掉"不设账号锁定"那半(用户没问过 ✓)⇒ 输错多少次都不会被锁死;每次慢是密钥派生(Argon2id)本来的代价,不是卡住了。 ⭐ **改动前后的字符数**(数的是这 5 段的**可见文字**,去掉 JSX 标签与缩进空白;脚本 _tmp/scratch/ecdict/count-lock-copy.cjs ✓): text ① 顶部 ② 放弃打开 ③ 导语 ④ 三条 li ⑤ 脚注 合计 改前 51 133 72 230 93 579 改后 43 99 63 165 71 441 -8 -34 -9 -65 -22 **-138(−23.8%)** 判据(写域内:lockScreen.test.ts + 本线既有的 vaultGate.test.ts ✓): - lockScreen.test.ts 新增一条:⭐ 要点一个都不许丢 —— ③「口令只由你保管」/⑤「输错多少次都不会被锁死」 /「每次慢是密钥派生」/「不是卡住了」/⭐ (c) **不可逆那半必须原意保留**(断的是「永久取不回来了」整句, ⛔ 不是只断"永久"两个字 ✗)/①「输入口令后才会加载」✓ + **既有**那条已经钉着 ④ 的三个要点(「同一把钥匙」/「开启加密之前导出的备份」/「永久」✓)⇒ 沿用 ✓ - vaultGate.test.ts 新增一条:② 的两条要点还在(「不用输这里的口令」/「随时可以切回来」✓) **先红后绿(逐字)** —— 一趟里做**两处**故意坏改: ``text 【先红】a) 把 ② 的「;随时可以切回来」**删掉**(=压过头)+ b) 把按钮前缀「放弃打开它,」**加回来**: $ npx vitest run src/vaultGate.test.ts ⇒ **[exit = 1]** FAIL … > 「放弃打开」那段:两条要点还在(不用输口令 / 随时可以切回来) AssertionError: 要点:随时可以切回来: expected '放弃打开这个加密空间?本机还有 1 个空间没有加密 —— 换过去马上就能用…' to contain '随时可以切回来' FAIL … > ⭐ 那排「去「名字」」按钮的形态:⛔ 不许把「放弃打开它,」前缀加回来 AssertionError: 按钮只留「去「<名字>」」: expected '放弃打开它,去「明文空间」' to match /^去「.+」$/ + ⭐ **既有**那条 a3) 按钮只留「去「<名字>」」… 也同时红了 ✓ ⇒ **按钮形态原本就有判据** ✓ $ [vitest exit = 1] text 【后绿】两处恢复后: $ npx vitest run src/components/lockScreen.test.ts src/vaultGate.test.ts ⇒ **[exit = 0]** | Test Files 2 passed | Tests 30 passed (30) $ npx tsc --noEmit ⇒ **[exit = 0]** residue=0 ✓(放弃打开它, 只剩那句**记录它被去掉**的注释 ✓) ` ⚠️ 如实说明两点: 1. ⭐ 我原本还给 (d) 写了一条新判据 ⇒ 红跑一遍发现**既有 a3) 已经钉住同一件事** ✓(它比我那版更全: 每颗带名字 + 数量=明文空间数 ✓)⇒ **删掉我那条重复的** ✓,只留一句指向 a3)` 的注释 ✓(⛔ 不重复造判据 ✓)。 2. ⛔ 那条 (b)「字符数降了」**没有写成断言**(把 579/441 这种数字钉进用例太脆 ✗)⇒ 按 Lead 要求**报数字** ✓ 不进判据 ✓。 | 9 天前 | |
feat(M16.1): Web 平台改用真实 SQLite(sql.js WASM), 核心笔记 CRUD 跑真实 SQL | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 19 小时前 | ||
| 2 天前 | ||
| 2 天前 | ||
| 2 天前 | ||
| 1 天前 | ||
| 2 天前 | ||
| 2 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 16 小时前 | ||
| 16 小时前 | ||
| 5 天前 | ||
| 1 个月前 | ||
| 1 天前 | ||
| 9 天前 | ||
| 1 个月前 |