问题描述:
LocalFilesystem.glob() 在 walkFileTree 的 visitFile 回调中,将 pattern(如 *.md)转换为 **/*.md 后,用 PathMatcher 匹配 searchPath.relativize(file) 的结果。
当被搜索目录(如 memory/)下直接存放文件(如 2026-05-20.md)时,relativize 结果只有文件名,没有任何目录前缀,**/*.md 要求至少有一层 /,导致匹配失败,返回空列表。
复现路径:
MemoryMaintenanceHook.onEvent(PostCallEvent) 触发
- 调用
MemoryConsolidator.consolidate()
- 调用
readDailyEntries(watermark)
- 调用
fs.glob(DEFAULT_FS_RUNTIME, "*.md", "memory")
glob 内部 walkFileTree 遍历 memory/ 目录,找到 2026-05-20.md
rel = "2026-05-20.md",用 **/*.md 匹配 → 失败
- 返回空列表 →
dailyEntries 为空 → 跳过 consolidation → MEMORY.md 永远不更新
根本原因:
// LocalFilesystem.java
String globExpr = effectivePattern.startsWith("**") ? effectivePattern : "**/" + effectivePattern;
PathMatcher matcher = fs.getPathMatcher("glob:" + globExpr);
// ↑ "*.md" 被转成 "**/*.md",但直接子文件的相对路径只有文件名,匹配失败
// visitFile 里只有:
if (matcher.matches(rel)) { ... }
// ↑ 缺少对 directMatcher("*.md") 的检查
修复方案:
在 visitFile 里同时检查 directMatcher:
PathMatcher directMatcher = fs.getPathMatcher("glob:" + effectivePattern);
// visitFile 里改为:
if (matcher.matches(rel) || directMatcher.matches(rel)) {
// ...
}
影响范围:
所有调用 fs.glob(pattern, path) 且目标文件直接位于 path 根目录下的场景,包括但不限于:
MemoryConsolidator.readDailyEntries() — memory/*.md
MemoryMaintenanceHook.expireDailyFiles() — memory/*.md
MemoryMaintenanceHook.pruneOldSessions() — agents/*.log.jsonl
问题描述:
LocalFilesystem.glob()在walkFileTree的visitFile回调中,将pattern(如*.md)转换为**/*.md后,用PathMatcher匹配searchPath.relativize(file)的结果。当被搜索目录(如
memory/)下直接存放文件(如2026-05-20.md)时,relativize结果只有文件名,没有任何目录前缀,**/*.md要求至少有一层/,导致匹配失败,返回空列表。复现路径:
MemoryMaintenanceHook.onEvent(PostCallEvent)触发MemoryConsolidator.consolidate()readDailyEntries(watermark)fs.glob(DEFAULT_FS_RUNTIME, "*.md", "memory")glob内部walkFileTree遍历memory/目录,找到2026-05-20.mdrel = "2026-05-20.md",用**/*.md匹配 → 失败dailyEntries为空 → 跳过 consolidation →MEMORY.md永远不更新根本原因:
修复方案:
在
visitFile里同时检查directMatcher:影响范围:
所有调用
fs.glob(pattern, path)且目标文件直接位于path根目录下的场景,包括但不限于:MemoryConsolidator.readDailyEntries()—memory/*.mdMemoryMaintenanceHook.expireDailyFiles()—memory/*.mdMemoryMaintenanceHook.pruneOldSessions()—agents/*.log.jsonl