sage-mem 0.9.0 → 0.9.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/autodream-audit.js +34 -9
- package/package.json +1 -1
package/lib/autodream-audit.js
CHANGED
|
@@ -28,14 +28,17 @@ import { join } from 'node:path'
|
|
|
28
28
|
const INDEX_FILE = 'MEMORY.md'
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* 审计**整个跳过**的文件(不读、不当被审对象)。
|
|
32
32
|
*
|
|
33
|
-
* session-log.md
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* session-log.md 是追加型流水,逐会话的账本而不是一条记忆;它没有
|
|
34
|
+
* `user_/feedback_/project_/reference_` 前缀,扫进来只会白白读一大坨再报假问题。
|
|
35
|
+
*
|
|
36
|
+
* ⚠️ 别和 `lib/memory/config.js` 的 `NON_ENTRY_FILES` 混为一谈 —— **同名不同义**:
|
|
37
|
+
* 那个管「列不列进设置页 / 星图 / 检索」,这个管「审计读不读」。它们的差集就是
|
|
38
|
+
* **索引 `MEMORY.md`**:它**要**被读(要当链接来源、要查行尾与链接),只是
|
|
39
|
+
* **不是一条记忆** —— 见下面 `f !== INDEX_FILE` 那两处。
|
|
37
40
|
*/
|
|
38
|
-
const
|
|
41
|
+
const AUDIT_SKIP_FILES = new Set(['session-log.md'])
|
|
39
42
|
|
|
40
43
|
/** 归档区目录名(与 autodream-tools.js 的 ARCHIVE_DIR、宿主侧 memory/scan.js 同名)。 */
|
|
41
44
|
const ARCHIVE_DIR = 'archive'
|
|
@@ -95,7 +98,7 @@ async function readDirSnapshot(dir) {
|
|
|
95
98
|
const all = entries
|
|
96
99
|
.filter((e) => e.isFile() && e.name.toLowerCase().endsWith('.md'))
|
|
97
100
|
.map((e) => e.name)
|
|
98
|
-
const files = all.filter((f) => !
|
|
101
|
+
const files = all.filter((f) => !AUDIT_SKIP_FILES.has(f.toLowerCase()))
|
|
99
102
|
let indexText = ''
|
|
100
103
|
try {
|
|
101
104
|
indexText = await readFile(join(dir, INDEX_FILE), 'utf8')
|
|
@@ -175,13 +178,28 @@ export async function auditMemoryDir(dir) {
|
|
|
175
178
|
}
|
|
176
179
|
for (const f of readable) linkKeys.add(f)
|
|
177
180
|
for (const f of readable) linkKeys.add(f.replace(/\.md$/, ''))
|
|
181
|
+
/**
|
|
182
|
+
* ⚠️ 链接目标池还必须含**非条目文件**(`session-log.md` / `MEMORY.md`)。
|
|
183
|
+
*
|
|
184
|
+
* 它们不在 `readable` 里(不参与检索),但 `[[session-log]]` 指向的是**真实存在的文件** ——
|
|
185
|
+
* 只因它不参与检索就报成断链,是假阳性。这与上面 `dangling` 用 `allSet` 而非 `files`
|
|
186
|
+
* 判定悬空是同一个理由,别只在一处想到。(2026-10-09 实测:健康记忆库被报 1 条假断链)
|
|
187
|
+
*/
|
|
188
|
+
for (const f of all) {
|
|
189
|
+
linkKeys.add(f)
|
|
190
|
+
linkKeys.add(f.replace(/\.md$/i, ''))
|
|
191
|
+
}
|
|
178
192
|
|
|
179
193
|
for (const f of readable) {
|
|
180
194
|
const raw = contents.get(f)
|
|
181
195
|
if (raw.includes('\r')) crlf.push(f)
|
|
182
196
|
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/)
|
|
183
197
|
if (!fmMatch) {
|
|
184
|
-
|
|
198
|
+
/**
|
|
199
|
+
* 索引 `MEMORY.md` 是**纯清单、不是一条记忆**(见 `lib/memory/config.js` 的
|
|
200
|
+
* `NON_ENTRY_FILES` 说明),不要求 frontmatter。报它等于给每一个健康的记忆库挂一盏常驻红灯。
|
|
201
|
+
*/
|
|
202
|
+
if (f !== INDEX_FILE) noFrontmatter.push(f)
|
|
185
203
|
} else {
|
|
186
204
|
const meta = parseFrontmatterLite(raw)
|
|
187
205
|
const prefix = f.split('_')[0]
|
|
@@ -196,7 +214,14 @@ export async function auditMemoryDir(dir) {
|
|
|
196
214
|
}
|
|
197
215
|
}
|
|
198
216
|
}
|
|
199
|
-
|
|
217
|
+
/**
|
|
218
|
+
* ⚠️ 只在**非代码**文本里找双链。
|
|
219
|
+
*
|
|
220
|
+
* `` `[[双链]]` `` 写在行内代码或围栏代码块里,是在**讲链接语法本身**,不是一条链接。
|
|
221
|
+
* 直接在原文上 `matchAll` 会把它报成断链(2026-10-09 实测的假阳性)。
|
|
222
|
+
*/
|
|
223
|
+
const prose = raw.replace(/```[\s\S]*?```/g, '').replace(/`+[^`]*`+/g, '')
|
|
224
|
+
for (const m of prose.matchAll(/\[\[([^\]]+)\]\]/g)) {
|
|
200
225
|
const target = m[1].trim()
|
|
201
226
|
if (linkKeys.has(target)) continue
|
|
202
227
|
// 指向归档区的链接:单列提示、不计问题 —— 归档不是删除,目标还在库里躺着。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sage-mem",
|
|
3
3
|
"description": "File-based memory plugin for DeepSeek Harness (DSH) — cross-session memory in plain markdown files, with a memory star-map view, type/tag filtering, retrieval aliases, and an optional autodream pass that consolidates memories on demand or on a schedule — with per-run rollback points, a per-file change declaration (what changed and why), and a separately selectable model for the consolidation pass",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|