dsh-ledger-memory 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +61 -5
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3073,9 +3073,61 @@ function renderAfterCompaction(info, capsule, meta) {
|
|
|
3073
3073
|
* @returns {string|undefined} 绝对路径;拿不到 cwd 且没锁 ⇒ undefined
|
|
3074
3074
|
*/
|
|
3075
3075
|
function projectRootOf(agent) {
|
|
3076
|
-
const
|
|
3076
|
+
const h = agent?.session?.header;
|
|
3077
|
+
return resolveProjectRoot(h?.id, h?.cwd);
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
/**
|
|
3081
|
+
* ★★★ 2026-10-10(用户报的真缺口):**采集器那条路的同一个判定**。
|
|
3082
|
+
*
|
|
3083
|
+
* **为什么需要它**:`ctx.on("session/event", (session, event) => …)` 拿到的是
|
|
3084
|
+
* **`session`**,不是 `agent` —— 所以它压根够不到 `projectRootOf(agent)`,
|
|
3085
|
+
* 旧代码就自己写了 `const cwd = session?.header?.cwd` **直接取原始 cwd**。
|
|
3086
|
+
* ⇒ 后果:**项目锁对活动日志(含 L4 用户消息存档)完全无效**。
|
|
3087
|
+
* 实测(本机,2026-10-10 用户让我把会话锁到插件目录之后):
|
|
3088
|
+
* · `ledger_status` 报的是**锁定目录**(工具那条路走了锁);
|
|
3089
|
+
* · 但 `ledger_log({view:"users"})` **一条 L4 都没有** ——
|
|
3090
|
+
* 因为采集器拿的是容器根,那里没启用日志 ⇒ `logDirOf` undefined ⇒ 直接 return。
|
|
3091
|
+
* ⇒ 锁着子项目,**用户在总工作区说的话一句都不进 L4**(而那正是 L4 最该记的东西)。
|
|
3092
|
+
*
|
|
3093
|
+
* ★ 修法不是"在采集器里再抄一遍判定",而是**抽成 `resolveProjectRoot` 一个出口**:
|
|
3094
|
+
* 两处各写一套判据 = 迟早分叉(本文件反复强调这条)。
|
|
3095
|
+
* ★ 这就是本项目「一个事实只能有一个判定出口」(D25)的又一次应用 ——
|
|
3096
|
+
* 而且这次是**我自己先违反了它**才出的缺口:`projectRootOf` 被当成唯一出口写在注释里,
|
|
3097
|
+
* 却漏了这条不经过 `agent` 的路。
|
|
3098
|
+
*
|
|
3099
|
+
* @param {object} session 官方 `session/event` 的第一个入参
|
|
3100
|
+
* @returns {string|undefined}
|
|
3101
|
+
*/
|
|
3102
|
+
function projectRootOfSession(session) {
|
|
3103
|
+
const h = session?.header ?? session;
|
|
3104
|
+
return resolveProjectRoot(h?.id ?? session?.id, h?.cwd);
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
/**
|
|
3108
|
+
* 判定项目根 —— **唯一的出口**(`projectRootOf` 与 `projectRootOfSession` 都走这里)。
|
|
3109
|
+
*
|
|
3110
|
+
* ★★★ 2026-10-10(用户拍板)加了「项目锁」:用户说的
|
|
3111
|
+
* *"把对话建在总的工作区下面…或者说把项目注册到对应的文件夹上,
|
|
3112
|
+
* 以后各种工具的使用都在那个文件夹上"*。
|
|
3113
|
+
*
|
|
3114
|
+
* ★★ 优先级:**cwd 自己有台账 > 锁 > cwd**(用户选的"只在这场对话内接管")。
|
|
3115
|
+
* 为什么不无条件以锁为准:用户说得很明确 ——
|
|
3116
|
+
* 锁是给"cwd 没有台账(典型:建在总工作区)"这种情况用的**接管**手段;
|
|
3117
|
+
* 若当前目录本来就是一个有台账的项目,那它自己就是答案,锁不该压过它。
|
|
3118
|
+
* ⇒ 这条判据让"锁"**只会扩大能用的情况,不会改变已有情况**(与 D49 默认 steady
|
|
3119
|
+
* 同一条思路:新能力不许悄悄改掉旧行为)。
|
|
3120
|
+
*
|
|
3121
|
+
* ★ 代价(如实记下):这里多了一次 `readManifest`(只读一个小 JSON)。
|
|
3122
|
+
* 它只在**真的锁了**的时候才走,没锁的会话行为与以前**逐字节相同**。
|
|
3123
|
+
*
|
|
3124
|
+
* @param {string|undefined} sid 会话 id(锁是按会话记的)
|
|
3125
|
+
* @param {string|undefined} cwd 会话工作目录
|
|
3126
|
+
* @returns {string|undefined} 绝对路径;拿不到 cwd 且没锁 ⇒ undefined
|
|
3127
|
+
*/
|
|
3128
|
+
function resolveProjectRoot(sid, cwd) {
|
|
3077
3129
|
const here = typeof cwd === "string" && cwd !== "" ? path.resolve(cwd) : undefined;
|
|
3078
|
-
const locked =
|
|
3130
|
+
const locked = typeof sid === "string" && sid !== "" ? sessionProjectLock.get(sid) : undefined;
|
|
3079
3131
|
if (locked === undefined) return here; // 没锁 ⇒ 与以前完全一致
|
|
3080
3132
|
// 锁了:当前目录**自己有台账**就以它为准(锁只接管"没有台账"的情况)。
|
|
3081
3133
|
if (here !== undefined && readManifest(here) !== undefined) return here;
|
|
@@ -9476,13 +9528,17 @@ export function apply(ctx, config) {
|
|
|
9476
9528
|
// ── ② 活动日志采集 ───────────────────────────────────────────────────
|
|
9477
9529
|
try {
|
|
9478
9530
|
if (collector !== undefined) {
|
|
9479
|
-
const cwd = session?.header?.cwd;
|
|
9480
9531
|
const sid = session?.header?.id ?? session?.id;
|
|
9481
|
-
|
|
9532
|
+
// ★★★ 必须走 `projectRootOfSession`(**不是**直接取 `session.header.cwd`):
|
|
9533
|
+
// 项目锁是按会话记的,而这条链手里只有 `session`。
|
|
9534
|
+
// 旧代码直取 cwd ⇒ 锁对 L0–L4 **全部无效** ⇒ 实测
|
|
9535
|
+
// "锁着子项目、用户的话一句都不进 L4"(2026-10-10 用户让我锁之后暴露的)。
|
|
9536
|
+
const root = projectRootOfSession(session);
|
|
9537
|
+
if (typeof root === "string" && root !== "" && typeof sid === "string" && sid !== "") {
|
|
9482
9538
|
// ★ 压缩来源由插件自己记的(内核那条事件里没有)—— 见 `state.hfSource`。
|
|
9483
9539
|
// 取出来立刻删:它只描述"紧接着这一次压缩"。
|
|
9484
9540
|
const hfSource = state.hfSource?.get?.(String(sid));
|
|
9485
|
-
collector.consume(
|
|
9541
|
+
collector.consume(root, sid, event, { hfSource });
|
|
9486
9542
|
if (event?.type === "compaction/end") state.hfSource?.delete?.(String(sid));
|
|
9487
9543
|
}
|
|
9488
9544
|
}
|
package/package.json
CHANGED