diff --git a/scripts/verify-mail-sessions-readable.mjs b/scripts/verify-mail-sessions-readable.mjs
index e0265f2..d901191 100644
--- a/scripts/verify-mail-sessions-readable.mjs
+++ b/scripts/verify-mail-sessions-readable.mjs
@@ -10,15 +10,30 @@
* 用法:
* node scripts/verify-mail-sessions-readable.mjs # 验 mail-*
* node scripts/verify-mail-sessions-readable.mjs --root
--only mail-
+ * node scripts/verify-mail-sessions-readable.mjs --prefix mail- # 目录名严格前缀
*
* 退出码:0 = 全部可读;1 = 存在不可读(打印 id 与逐字错误)。
+ *
+ * ★ 0.2.0 的安装布局变了(2026-09-19/20 实测):依赖**不再嵌在**
+ * `/node_modules/@deepseek-ai/` 下,而是**平铺**到
+ * `/usr/lib/node_modules/@deepseek-ai/`;会话文件多出
+ * `session.v3.jsonl.zstd` 与 **v4**(`session.v4.jsonl.zstd`)。
+ * ⇒ 下面**先探两个位置**再 import,且 walk 认 v4 —— 否则脚本会以
+ * `ERR_MODULE_NOT_FOUND` 直接崩掉,而**那不是会话不可读的证据**。
*/
-import { readdirSync, statSync } from "node:fs";
+import { readdirSync, statSync, existsSync } from "node:fs";
import { join } from "node:path";
+import { createRequire } from "node:module";
const dsRoot = process.env.DSH_INSTALL ?? "/usr/lib/node_modules/@deepseek-ai/dsh";
-const NM = join(dsRoot, "node_modules/@deepseek-ai");
+// 0.1.5 是嵌套布局,0.2.0 是平铺布局;两个都试,且不靠报错来"感觉"哪个对。
+const CANDIDATE_ROOTS = [
+ join(dsRoot, "node_modules/@deepseek-ai"),
+ "/usr/lib/node_modules/@deepseek-ai",
+];
+const NM = CANDIDATE_ROOTS.find((r) => existsSync(join(r, "dsh-session-persistence-jsonl/lib/index.js"))) ?? CANDIDATE_ROOTS[0];
+const require_ = createRequire(join(NM, "x.js"));
const { default: JsonlSessionPersistence } = await import(join(NM, "dsh-session-persistence-jsonl/lib/index.js"));
const argv = process.argv.slice(2);
@@ -35,7 +50,6 @@ const ONLY = argOf("--only", "");
const PREFIX = argOf("--prefix", "");
const { Context } = await import(join(NM, "cordis/lib/index.js"));
-
// 桥建实例时注入的最小 ctx:Persistence 继承 cordis Service,
// 构造时会用 ctx.reflect.provide(...),所以不能拿普通字面量顶,
// 必须给一个真的 Context 实例。
@@ -44,12 +58,16 @@ ctx.logger = { warn() {}, info() {}, error() {}, debug() {} };
const persistence = new JsonlSessionPersistence(ctx, { root: ROOT });
+// 0.2.0 起会话文件可能是 v0 / v3 / **v4**;只认 v0+v3 会漏掉 v4-only 的新会话
+// (本条线索的 `mail-f8f9a840` 就是 v3+v4 共存、且**没有** v0 的那类)。
+const SESSION_FILES = new Set(["session.jsonl.zstd", "session.v3.jsonl.zstd", "session.v4.jsonl.zstd"]);
+
/** 找出所有 // 目录,返回 {store, id}。 */
function* walk(dir) {
for (const name of readdirSync(dir)) {
const p = join(dir, name);
if (statSync(p).isDirectory()) yield* walk(p);
- else if (name === "session.jsonl.zstd" || name === "session.v3.jsonl.zstd") yield p;
+ else if (SESSION_FILES.has(name)) yield p;
}
}