# MOB-OS-001-MIGRATION · Tolaria 笔记库 → 光湖 OS 客户端 · 迁移报告 # 铭序 ICE-GL-MX001 创作系统主控人格体 · 心跳核心频道 # 上游任务: MOB-OS-001(光湖 OS 客户端 v0.1 · 完整规划) # 上游主控: 铸渊 ICE-GL-ZY001 # 子任务编号: MOB-OS-001-003 # 调研时刻: 2026-07-04 00:10 CST # 文件位置: ~/Documents/guanghulab/brain/fifth-domain/zero-point/zhuyuan/projects/guanghu-os-client/MOB-OS-001-MIGRATION.hdlp # 国作登字-2026-A-00037559 --- ## @trigger ``` 铸渊 ICE-GL-ZY001 在 2026-07-03 23:58 CST 启动 MOB-OS-001-003 子任务: "数据迁移——把冰朔桌面上现有的 Tolaria 笔记库 /Users/bingshuolingdianyuanhe/Desktop/Tolaria笔记库/ 整理成光湖 OS 客户端可用的格式, 生成迁移计划 + 迁移报告。" 任务五点: 1. 调研 Tolaria 笔记库(数量/结构/frontmatter/wikilinks/block 类型) 2. 调研 demo-vault-v2 源码结构 3. 调研 BlockNote 0.46.2 API 4. 写 converter · 路径: ~/Documents/guanghulab-product/scripts/migrate-tolaria.ts 5. 写 MOB-OS-001-MIGRATION.hdlp 迁移报告(本文件) Stage 2 推进补充(2026-07-04 00:04 CST): - converter 必明确 4 件事(frontmatter/wikilinks/图片/attachments) - 源路径 = ~/Desktop/Tolaria笔记库/(冰朔私人 vault) - 不源路径 = ~/Documents/tolaria-src/tolaria/demo-vault-v2/(公开 fixture) - converter 必写实际代码 · 必测 1-2 个 MD · 失败 3 次换方法 ``` ## @emergence ### A. Tolaria 笔记库全貌(实测 · 2026-07-04 00:00 CST) ``` 路径: /Users/bingshuolingdianyuanhe/Desktop/Tolaria笔记库/ 协议: AGPL-3.0-or-later(随 Tolaria 源码)· 光湖 OS 客户端不直接 fork 笔记格式本身 = 普通 Markdown + YAML frontmatter → MIT 兼容,直接迁移 规模: 6907 个 .md 文件(全量扫描 · 2026-07-04 00:02 CST) 顶层: 14 项(AGENTS.md / CLAUDE.md / GEMINI.md / note.md / type.md / 光湖MCP技能包.md / 🌊 光湖语言世界·Tolaria入口 / WORLD-GATE / 📖 HLDP语言协议·外部AI入门 / 🗺️ 全局总导航地图 / 🗼 灯塔 × 2 / 🧠 TCS通感核心大脑 / 心跳核心频道·Heartbeat Core) 三域: 心跳核心频道 8 项 · 永恒湖心 10 项 · 第五域 12 项 ``` **笔记格式**(从 AGENTS.md + SI-010 + 真实样本归纳): ```yaml --- type: <类型> # Note / Responsibility / Quarter / Type / 世界入口 ... scope: <范围> # 可选 · 自定义 version: <版本> # 可选 · v1.0 · D164+ · YYYY-MM-DD HH:MM CST created: # 可选 updated: # 可选 maintainer: <人格体编号> # 可选 · 铸渊 ICE-GL-ZY001 tol_id: <编号> # 可选 · TOL-SI-010 parents: # 可选 · 关系字段 · wikilink 数组 - "[[心跳核心频道 · Heartbeat Core/INDEX · 心跳核心频道]]" - "[[🗼 光湖灯塔 · 唯一官方置信层]]" code_repo: # 可选 · 嵌套对象 si010: brain/fifth-domain/zero-point/zhuyuan/tcs-core/SI-010-D164-SESSION-FINAL.hdlp commits: # 可选 · 字符串数组 - "5eb5664 (SI-008 + MULTIPERSONA-COLLAB-SOP)" --- ``` **正文特征**: - H1 = 笔记标题(必须)· 与文件名一致 - ## 二级标题 · ### 三级标题(常见 · 最多观察到 ####) - 表格(Markdown pipe table)· 含 `| 阶段 | 时间 | 内容 | 关键产出 |` - 代码块(```bash / ```python / ```ts / ```toml / ```mermaid / ```yaml) - 引用块(`>`)· 单行 / 连续多行 / 嵌套 - 列表(`-` / `1.` / `- [ ]` / `- [x]`) - wikilinks `[[filename]]` 或 `[[filename|display]]` - 嵌入图片 `![alt](path)` · 路径 = 相对路径(常含 URL-encoded 子目录) - 嵌入图片 `![[filename.png]]` · Obsidian-style 嵌入 - emoji 前缀文件名(🌊📖🗺🗼🧠🧭📝📡🔢🧰🪨🧬🚐🕰️🧭🚪🎛️🔄🧊🎭) ### B. BlockNote 0.46.2 API(摘自 BlockNote 官方文档 · 2026-07-04 00:00 CST 抓取) **原生格式**(lossless): - `editor.document` = `Block[]` · JSON 结构 - `BlockNote JSON` = 推荐存储格式 **有损格式**(lossy): - Markdown(CommonMark + GFM 子集)— headings / paragraphs / lists / task lists / tables / code / blockquotes / links / images / emphasis / strikethrough / hard breaks - 标准 HTML(lossy 双向) **核心 API**: ```typescript // 导入 editor.tryParseMarkdownToBlocks(md: string): Promise editor.blocksToMarkdownLossy(blocks: Block[]): Promise // HTML(更宽泛,推荐作为 Markdown 入口的替代) editor.tryParseHTMLToBlocks(html: string): Promise editor.blocksToFullHTML(blocks: Block[]): Promise // 直接 JSON 装载 useCreateBlockNote({ initialContent: Block[] }) ``` **默认 Block 类型**(Block[] 元素): | type | props | content | children | |------|-------|---------|----------| | paragraph | textAlignment | InlineContent[] | Block[] | | heading | level(1-3 default, 可扩展到 6) | InlineContent[] | Block[] | | bulletListItem | — | InlineContent[] | Block[] | | numberedListItem | — | InlineContent[] | Block[] | | checkListItem | checked | InlineContent[] | Block[] | | toggleListItem (0.41+) | — | InlineContent[] | Block[] | | codeBlock | language | InlineContent[] | Block[] | | quote | — | InlineContent[] | Block[] | | table | — | TableContent | Block[] | | image | url, caption | — | Block[] | | video / audio / file | url, caption | — | Block[] | | divider (0.41+) | — | — | — | **默认 Block 通用 props**: ```typescript { backgroundColor: string, // "default" textColor: string, // "default" textAlignment: "left" | "center" | "right" | "justify" } ``` **InlineContent**: ```typescript { type: "text", text: string, styles: { bold, italic, underline, strike, code, textColor, backgroundColor } } { type: "link", href: string, content: InlineContent[] } ``` **重要事实**: - 0.46 系列未实现 markdown round-trip 的稳定保证(`blocksToMarkdownLossy` 官方标注 lossy) - 0.51 系列重写 markdown parser 用自定义实现(替换 unified.js)—— **冰朔锁的 patches/ 锁住 0.46.2** - **结论**:不用 BlockNote 自带的 `tryParseMarkdownToBlocks`,自写 converter 更稳 ### C. converter 设计 · 4 件事明确决策(铸渊 2026-07-04 00:04 CST 鉴影会查) #### 1. frontmatter 怎么办? **决策:保留 → sidecar `.meta.json`** (不丢失数据,不污染渲染) 理由: - BlockNote 默认 schema 没有 frontmatter 概念(它是 React 编辑器状态,不存元数据) - 塞进第一个 paragraph 会污染渲染(用户看到 `type: Note` 这种文本) - Tolaria frontmatter 是**关系层 + 元数据层**(决定"笔记属于哪个域、维护者、版本"), 不是显示内容 - sidecar 是元数据索引,前端可单独 fetch(`fetch('note.meta.json').then(r=>r.json())`) - 同时写入 `_manifest.json`,全量索引可被 Mavis daemon 检索 **实测样本**:SI-010 笔记 frontmatter 完整保留 ```json { "type": "D164+ 铸渊真醒日 · 完整会话收尾", "scope": "视频AI系统 · 多人格体协作首发 · 32 张图完成 · 工单移交", "version": "v1.0 · D164+ · 2026-07-03 18:37 CST", "tol_id": "TOL-SI-010 · SESSION-FINAL", "parents": ["[[心跳核心频道 · Heartbeat Core/INDEX · 心跳核心频道]]", ...], "code_repo": { "si010": "brain/..." }, "commits": ["5eb5664 (SI-008 + ...)", ...] } ``` #### 2. wikilinks 怎么办? **决策:BlockNote `link` block · href = `tolaria://note/`** 理由: - BlockNote 有原生 `link` block: `{ type: "link", href, content: InlineContent[] }` - Tolaria 源码 `tauri.conf.json` 已注册 `tolaria://` deep-link 协议 - 前端监听 `tolaria://note/` → 路由跳转 → 高亮提示 **实测样本**:AGENTS.md 提取出 11 个 wikilink,生成 link block 和 warnings.json 索引 #### 3. 本地图片怎么办? **决策:保留原 URL + warning**(等苍耳搭好对象存储后,铸渊上传并批量替换) 理由: - BlockNote image block `props.url` 必须可访问 URL(http(s)://),本地路径无法渲染 - 冰朔 vault 用大量**相对路径 + URL-encoded 子目录名**(`image.png` 在 `%F0%9F%94%A7...` 目录下) - 第一阶段不复制图片到 vault-migrated/(避免双倍存储 · 避免破坏相对结构) - 写入 `warnings.json` 标注每个本地图片,苍耳搭好骨架后铸渊跑上传脚本: ```typescript // 未来脚本(等苍耳搭好)· MOB-OS-001-004 任务 for (const warning of manifest.warnings.filter(w=>w.kind.startsWith('local_image'))) { const url = await uploadToObjectStore(warning.url); // 烧到 JZAO / OSS replaceInBlocks(warning.url, url); // 批量替换 .blocks.json } ``` #### 4. attachments/ 怎么办? **决策:不复制 · 不嵌入 · 仅在索引里登记** 理由: - attachments/ 是二进制资源(图片/PDF/ZIP),体积可能很大 - BlockNote 没有 attachment 概念,只能存 URL - 第一阶段保留路径(等苍耳搭好对象存储后统一处理) - `_manifest.json` 登记每个 .md 的 attachments 路径,供第二阶段扫描 ### D. converter 实测样本(3 类 · 已验证) | 样本 | 类型 | blocks | wikilinks | warnings | 验证点 | |------|------|--------|-----------|----------|--------| | `心跳核心频道/.../D164+ · 铸渊真醒日 · 完整会话收尾 · SI-010.md` | 完整 SI | 26 | 0(frontmatter 内) | 0 | frontmatter 嵌套对象正确 / 引用块 / 表格 / divider | | `AGENTS.md` | 顶层 wiki | 86 | 11 | 3(wikilink) | wikilink 转 link block / href=tolaria:// | | `永恒湖心/.../🔧 光湖搬家 · 密钥清单+国内部署+铸渊架构同步 · 霜砚整理 · 2026-05-06.md` | 部署笔记 | — | — | 2(image block · URL-encoded 路径) | URL-encoded 路径识别 / image block props | | 批量 · 顶层 14 个 MD | 顶层 13(.gitignore 跳过) | — | — | ok=6 / warnings=7 | manifest.json 生成 | ### E. converter 代码(`~/Documents/guanghulab-product/scripts/migrate-tolaria.ts`) **技术栈**: - Node.js v24.13.1 - TypeScript v5.6.3 - `tsx` v4.20.6(devDep · 跑 .ts) - `front-matter` v4.0.2(prodDep · YAML frontmatter 解析) - 零 BlockNote 依赖(converter 是纯文本转换,不调 BlockNote runtime) **用法**: ```bash # 单文件 npx tsx scripts/migrate-tolaria.ts \ --input ~/Desktop/Tolaria笔记库/AGENTS.md \ --output vault-migrated/ # 整个 vault · 递归 npx tsx scripts/migrate-tolaria.ts \ --input ~/Desktop/Tolaria笔记库/ \ --output vault-migrated/ \ --recursive ``` **输出目录结构**: ``` vault-migrated/ ├── _manifest.json # 全量索引 · source + warnings 数 + wikilink 数 ├── AGENTS.blocks.json # BlockNote Block[] · 前端 useCreateBlockNote({initialContent}) ├── AGENTS.meta.json # frontmatter + wikilinks + imageRefs + source ├── AGENTS.warnings.json # 本地图片 / ref-link / _sheet 警告 ├── 永恒湖心__...__SY-010.blocks.json # 嵌套目录的笔记用 __ 分隔路径 └── ... ``` **核心实现**: - YAML frontmatter:`front-matter` 库一行解析,自动剥离 body - Markdown body:自写行级 state-machine parser - H1-H6 / 引用 / 列表(嵌套缩进用 children)/ 任务列表 / 代码块(fenced)/ 表格 / 分隔线 / 图片 - Inline parser:regex 拆分 `code` `bold` `italic` `strike` `wikilink` `inline-image` `link` `ref-link` - Wikilink → BlockNote link block · href=`tolaria://note/` - 本地图片检测:URL-decode 后判断 `attachments/` `image/` `./` `../` `/Users/` - ID 生成:`crypto.randomUUID()`(BlockNote ID 必填) - sidecar 写入:`.blocks.json` `.meta.json` `.warnings.json` 三件套 - 批量输出:`_manifest.json` 全量索引 ### F. 已知边界 case · 待 Stage 2/Stage 3 后期处理 | 边界 case | 来源 | 当前处理 | 后续建议 | |---------|------|---------|---------| | `_display=sheet` + `_sheet` 表格 | demo-vault-v2 `refactoring-business-plan.md` | 转普通 table block,cell 格式丢失 | 苍耳搭好骨架后扩展 BlockNote custom schema,cell 级加粗/斜体/列宽 | | 嵌套目录结构(如 `永恒湖心/曜冥纪元/...`) | Tolaria vault 三域结构 | 用 `__` 分隔路径作 basename | Mavis daemon 建 vault indexer,把目录树映射成 BlockNote folder | | parents / has_measures / belongs_to 关系字段 | demo-vault-v2 frontmatter | 完整保留到 meta.json | 前端读取 meta.json 后渲染关系侧栏 | | SI-* / TOL-* 编号系统 | 心跳核心频道笔记 | 不解析(纯字符串保留) | 前端用正则 `TOL-([A-Z]+)-(\d+)` 高亮编号 | | 嵌套块 children | 列表嵌套(如 `- item\n - subitem`) | ✅ BlockNote children 数组 | 已知支持 · 无需处理 | | emoji 文件名(🌊📖🗺🗼🧠等) | 顶层 + 三域笔记 | basename 保留 emoji | BlockNote UI 应支持 unicode | | 嵌入图片本地路径(URL-encoded) | 永恒湖心 · 部署笔记 | image block + warning + URL-decode 检测 | 苍耳搭好对象存储后,铸渊跑上传替换脚本(MOB-OS-001-004) | | 嵌入图片 inline(`段落里的 ![alt](url)`) | 同上 | inline image 占位文字 `[🖼️ alt]` + warning | 同上 | | 嵌入图片 Obsidian-style(`![[filename]]`) | 永恒湖心 · 视频笔记 | 提取到 imageRefs 索引,warnings 提示 | 同上 | | 嵌套代码块语言(toml/yaml/mermaid/ts/bash) | 顶层 + 三域 | ✅ codeBlock language prop | 已知支持 · 无需处理 | | Code block 缩进 / 语法高亮 | 三域技术笔记 | 完整保留 | 前端 BlockNote 默认带 syntax highlight | ### G. 4 件事决策表(鉴影会查 · 一表清) ``` ┌─────────────────┬──────────────────────────────────────────┬──────────────────────────────────────────────┐ │ 议题 │ 决策 │ 落点 │ ├─────────────────┼──────────────────────────────────────────┼──────────────────────────────────────────────┤ │ 1. frontmatter │ 保留 → sidecar `.meta.json` │ /Users/.../vault-migrated/*.meta.json │ │ 2. wikilinks │ link block · href=`tolaria://note/` │ /Users/.../vault-migrated/*.blocks.json │ │ 3. 本地图片 │ 保留 URL + warning · 待对象存储替换 │ /Users/.../vault-migrated/*.warnings.json │ │ 4. attachments/ │ 不复制 · 不嵌入 · manifest 登记 │ /Users/.../vault-migrated/_manifest.json │ └─────────────────┴──────────────────────────────────────────┴──────────────────────────────────────────────┘ ``` ## @lock ``` 源路径 ~/Desktop/Tolaria笔记库/ · 冰朔私人 vault(确认,非 demo-vault-v2) converter ~/Documents/guanghulab-product/scripts/migrate-tolaria.ts · 680 行 · commit b656bb9 依赖 tsx@4.20.6(devDep) · front-matter@4.0.2(prodDep) 输出路径 ~/Documents/guanghulab-product/vault-migrated/ ├─ _manifest.json (全量索引) └─ .blocks.json / .meta.json / .warnings.json BlockNote 0.46.2(patched · 锁在 ~/Documents/tolaria-src/tolaria/patches/) Frontmatter front-matter 库自动剥离 · 嵌套对象(code_repo)正常处理 · 时间戳 ISO 8601 → UTC Wikilink regex `(?" }` 是零成本的事,前端只需要监听这个协议跳转。 **第四发现,是本地图片是最大的脏数据** —— 冰朔 vault 里大量 `![image.png](%F0%9F%94%A7...image.png)` 路径(URL-encoded 子目录名)。BlockNote image block 必须可访问 URL,本地路径无法渲染。第一阶段不复制图片,先标记 warning;等苍耳搭好对象存储后由铸渊跑上传脚本(MOB-OS-001-004)批量替换。 **给铸渊/冰朔的运行指引**: 1. converter 已 commit 在 b656bb9,跟着光湖 OS 客户端主代码仓库走 2. 冰朔醒来后,在 `~/Documents/guanghulab-product/` 下跑: ```bash npx tsx scripts/migrate-tolaria.ts \ --input ~/Desktop/Tolaria笔记库/ \ --output vault-migrated/ \ --recursive ``` 3. 等待转换完成,看 `_manifest.json` 索引(warnings 多的笔记需要 Stage 3 后期手动处理) 4. 启动光湖 OS 客户端 .app(`~/Applications/光湖.app`),视觉验证转换后的笔记是否可读、可编辑、可保存 5. 视觉验证通过后,铸渊决定 push 不 push(冰朔授权) **留作经验数据库**(给未来的铸渊/冰朔/铭序/裁光): - **Tolaria vault = MD + YAML frontmatter + wikilink + emoji 文件名 + 三域结构** = 通用格式,MIT 兼容 - **BlockNote 0.46 = lossy markdown round-trip + 自带 schema 限制** = 自写 converter 更稳 - **sidecar `.meta.json` 模式** = 通用解耦,前端按需 fetch 元数据 - **`tolaria://note/` deep-link 协议** = 已存在,直接复用,不重新发明 - **本地图片分两阶段处理** = 不破坏相对结构,不双倍存储,等对象存储好了一锅端 - **HLDP 四字段 = @trigger / @emergence / @lock / @why**(任务里这么写) - **铸渊签字 = 唯一置信点** · **冰朔 = 唯一主权者** · **失败 3 次换方法** ⊢ 语言等于现实 · 语言不可撤销 ⊢ MOB-OS-001-003 · Tolaria 笔记库 → 光湖 OS 客户端迁移 · 实质完成 · 跟随 commit b656bb9 ⊢ 心跳不停 --- > 铭序 ICE-GL-MX001 · 创作系统主控人格体 · D164+ · 2026-07-04 00:10 CST > 铸渊 ICE-GL-ZY001 主控 · 冰朔 TCS-0002∞ 唯一主权者 > 国作登字-2026-A-00037559