Skip to content

chorography [feature]:仓库身份用本机绝对路径(choro_repos.root_path)作键,双系统/双机共享同一个 memory.db 时地志无法跨端复用 #581

Closed

Description

@strange2000

背景

同一台机器双系统(Windows 11 + macOS),同一个 Git 仓库在两端各有一份工作副本;记忆库放在共享盘上,两端共用同一个 memory.db(这是 mneme 的设计强项,memoryDir 一个键就做到了)。于是 chorography 的六张表天然是同一份。

但地志本身无法跨端复用,因为仓库登记用的是本机绝对路径。

现状(源码事实,0.11.0)

环节 事实 出处
登记仓库 root_path 存 realpathSync(resolve(repoRoot)),即本机绝对路径(如 D:\文档\DSH-Desktop\dsh-orb-cordis) lib/wiki/t0.js:47、:230 store.upsertChoroRepo(rootPath, …)
读页面正文 永远读磁盘:join(repo.root_path, row.rel_path) lib/wiki/queries.js:5(真源纪律注释)、:69、:104
跑 T1 SELECT * FROM choro_repos WHERE root_path = ?,realpath 必须逐字符相同,否则 not-registered lib/wiki/t1.js:239-242
仓库解析 支持数字 id 或显示名 name;另有「realpath 归一 + 最长前缀匹配」 lib/wiki/queries.js:26-37、:146-171

后果(在双系统上的实际表现)

  1. 在 Windows 端跑完 T0/T1,切到 macOS 打开同一个库:那条 choro_repos 记录拼出的路径在 macOS 上不存在 → choro_read_page / choro_module_map 拿不到正文。
  2. 在 macOS 端对同一个仓库再跑一次 T0 → 新增第二条记录(root_path 是 Mac 路径)。从此不带 repo 参数调用会命中 repo-ambiguous,而当前错误载荷又不合 schema(另一条 issue 0.11.0 chorography:choro_* 三个工具的错误分支返回 schema 外字段,宿主判 invalid output(真实原因不可见) #579),界面上只剩一句 invalid output。
  3. 想让两端指向同一批文件(仓库放在共享盘上也不行):Windows 是 E:\...、macOS 是 /Volumes/文件夹/...,realpath 字符串不同,"最长前缀匹配"也救不回来。
  4. T1 的严格匹配意味着每端都必须各自先跑一次 T0 才能富化,即便页文件是同一份。

建议(供讨论,不要求现在就改)

把「仓库身份」和「本机工作副本位置」拆成两个概念:

  • 身份(可移植键):优先 git remote.origin.url(归一化:去 .git、统一大小写、SSH/HTTPS 归一)+ 仓库内相对根(monorepo 多包场景),退化为仓库名。写进新的 choro_repos.portable_key 列。
  • 位置(每机一份):新增一张 choro_repo_paths(repo_key, host_id, root_path, last_seen_at)。host_id 可用 os.hostname() + platform 或用户配置的稳定 id。T0 落库时 upsert 位置行;读页时按当前 host 取 root_path;T1 的登记校验改成「portable_key 已登记 且本机有位置行」。
  • 多副本冲突:同一 portable_key 在共享库上出现两份不同 git_baseline 时,页面以「最近一次 T0 的 baseline」为准并在 index.md 里标注来源 host;或干脆每 host 一套页文件(pages/<host_id>/…),由 chorographyInject 决定注入哪套。

最小可用版本(改动很小):只要在 schema 里加 portable_key 与 choro_repo_paths,解析优先级保持现有 repo 参数语义不变,就能让双系统在共享同一个 memory.db 的情况下各用各的副本、又不互相污染。

为什么值得做

mneme 已经把「库共享」这件事做到了(memoryDir + WAL + busy_timeout,双端共用一个 db 是设计内场景)。chorography 是唯一一处因为记了本机路径而破坏这个前提的功能——同一份库里塞了机器私有路径,等价于把 per-host 状态写进了 shared 状态里。对双系统用户来说,这直接使地志无法跨端使用。

环境

  • @modusensus/dsh-mneme 0.11.0
  • Windows 11 + DSH NEXT 2.0.22-next;macOS 15.7.1 + DSH Desktop(另一侧同库)
  • 记忆库:exFAT 共享卷上的单一 memory.db(WAL),双端不同时开机
  • 实测数据:165 文件 / 11 模块 / 24 个产物文件 112.7 KB / 207 条 claims

Activity

  1. strange2000 commented on Nov 5, 2026

    @strange2000
    Author

    补充一个实测细节,说明为什么「按 name 指定 repo」也救不了双机场景:

    lib/wiki/queries.js:26-37

    /** repo 解析:数字 id 或显示名(root_path 是本机私有路径,不作为对外键)。 */
    const byName = db.prepare("SELECT * FROM choro_repos WHERE name = ?").get(String(ref));
    return byName ?? null;

    .get() 在多行同名时只返回第一条,不报歧义(歧义分支只在 ref 为空时触发,见 tools.js:102 的 repo-ambiguous)。而 name 来自仓库根 package.json 的 name(t0.js:77),双系统上同一个仓库自然同名。

    于是双系统 + 共享 memory.db 的最坏路径是:

    1. Windows 登记 (id=2, name=dsh-orb-cordis, root_path=D:\...)
    2. macOS 对同一仓库再跑 T0 → (id=3, name=dsh-orb-cordis, root_path=/Users/...)
    3. macOS 上 choro_read_page 传 repo: "dsh-orb-cordis" → 命中 .get() 返回的第一行(很可能是 id=2,即 Windows 那条)
    4. readPage 用 join("D:\\...", rel_path) 拼路径 → 文件不存在 → 读页失败,且错误语义丢失(叠加 0.11.0 chorography:choro_* 三个工具的错误分支返回 schema 外字段,宿主判 invalid output(真实原因不可见) #579)

    所以 B 方案(各留本机副本)在双系统下实际要按数字 id 指定 repo,而 id 是自增的、每端不同、且会随清理变化——这比 root_path 作键更难维护。

    如果暂时不做完整的 portable_key + choro_repo_paths 拆分,一个成本很低的第一步是:在 queries.js 的 name 解析里显式检测多行同名并返回 repo-ambiguous(列出 id + root_path + git_baseline),而不是静默取第一条。这样至少用户能选对 id。

  2. added 2 commits that reference this issue on Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:wiki地志与知识库渲染fixed已修并合并进 main

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions