diff --git a/plugins/memcore/skills/memory-lint/SKILL.md b/plugins/memcore/skills/memory-lint/SKILL.md index 8ec2e34..5ce0a64 100644 --- a/plugins/memcore/skills/memory-lint/SKILL.md +++ b/plugins/memcore/skills/memory-lint/SKILL.md @@ -49,7 +49,7 @@ ls "$PROJECT_DIR/.claude/memory/"*.md | Phase | 定义 | 级别 | AUTO-FIX | |-------|------|------|---------| | 1 孤儿 | 索引有 → 磁盘无 | ERROR | 从 MEMORY.md 删该条目 | -| 2 幽灵 | 磁盘有 → 索引无(排除 MEMORY.md / lint_report.md) | WARN | 补入索引(类型推断见下) | +| 2 幽灵 | 磁盘有 → 索引无(排除 MEMORY.md / lint_report.md / synonyms.md) | WARN | 补入索引(类型推断见下) | 幽灵类型推断:`user_*` → user / `project_*` 或 `decisions.md` → project / `feedback*` → feedback / `reference*` → reference / `synthesis_*` → synthesis / 其他默认 project。 @@ -84,6 +84,40 @@ ls "$PROJECT_DIR/.claude/memory/"*.md 三类全部为 NEED-HUMAN,写入 lint_report.md 时**必须附带 3 问 yes/no checklist + 决策矩阵**(Phase 8 模板)。 +### Phase 4-pre — 等价表述加载 + +矛盾检测前先加载 `$PROJECT_DIR/.claude/memory/synonyms.md`(可选文件)。 + +**加载方式**: +```bash +[ -f "$PROJECT_DIR/.claude/memory/synonyms.md" ] && \ + grep -v "^#\|^---\|^$\|^name:\|^description:\|^type:" \ + "$PROJECT_DIR/.claude/memory/synonyms.md" +# 输出每行一个等价组(逗号分隔),大小写不敏感,存入 $SYNONYMS_GROUPS +``` + +**synonyms.md 格式**(用户自行在项目内创建和维护): +```markdown +--- +name: 等价表述清单 +description: 矛盾检测等价词表,同组词视为相同概念 +type: reference +--- + +# 等价表述清单 +> 每行一组,逗号分隔,大小写不敏感 + +PostgreSQL, PG, Postgres, postgresql +JWT, JSON Web Token +Vue3, Vue 3, Vue 3.x +``` + +**判定规则**:检查两处描述中出现的技术术语是否属于同一等价组。若属同组 → 跳过,不纳入矛盾候选。 + +**无 synonyms.md 时**:仅检测直接数值/版本冲突(如 PostgreSQL 14 vs PostgreSQL 16),对措辞差异不报告。 + +--- + ### Phase 4 内容矛盾 | 维度 | 检查 | @@ -92,6 +126,25 @@ ls "$PROJECT_DIR/.claude/memory/"*.md | decisions vs 架构文件 | 与 pom.xml / package.json / requirements.txt 实际依赖不一致 | | 多 feedback 文件 | feedback.md 与 feedback_{topic}.md 重复或矛盾 | | synthesis vs decisions | synthesis 结论与决策抵触 | +| 合并残留标记 | 文件含 `` 或 `` → WARN,NEED-HUMAN | + +```bash +grep -rn "`) +- **Checklist**:Q1 本地版本是否正确?Q2 远端版本是否有本地没有的有效信息?Q3 是否可合并为单一表述? +- **矩阵**:Q2 否 → 删除 `## [合并待审]` 段落和标记;Q2 是 + Q3 是 → 合并后删标记;Q3 否 → 保留两段但清除 HTML 注释 + +矛盾判定门槛(过 synonyms.md 等价检查后): + +| 情况 | 处理 | +|------|------| +| 同主题,等价组内术语不同 | 跳过,不报告 | +| 同主题,结论相反(推荐 A vs 推荐 B) | WARN → NEED-HUMAN | +| 同主题,数值/版本直接冲突 | ERROR → NEED-HUMAN | +| 措辞不同,无直接逻辑冲突 | 跳过(宁漏报不误报) | ```bash cat "$PROJECT_DIR/pom.xml" || cat "$PROJECT_DIR/package.json" || cat "$PROJECT_DIR/requirements.txt" @@ -226,6 +279,11 @@ last_updated: YYYY-MM-DD 独立调用:扩展输出已修复 / 待处理清单 + 报告路径;全通过则 `✅ 记忆体系健康,已更新执行时间`。 +发现矛盾候选且 `synonyms.md` 不存在时,额外输出: +``` +💡 创建 .claude/memory/synonyms.md 可将等价术语(如 "PostgreSQL, PG")预先排除出矛盾检测,降低误报率。 +``` + 每次执行必须更新 lint_report.md(即使全通过也刷新执行时间)。 --- @@ -234,6 +292,6 @@ last_updated: YYYY-MM-DD 1. **AUTO-FIX 边界严格** — 只修结构性错误(孤儿、幽灵、断链、双链),不改业务内容 2. **NEED-HUMAN 完整记录** — 每项含 checklist + 决策矩阵 -3. **矛盾检测宁缺勿滥** — 措辞不一致 ≠ 矛盾,宁漏报不误报 +3. **矛盾检测先过等价表** — 先加载 `synonyms.md` 再判矛盾;措辞不一致 ≠ 矛盾,宁漏报不误报;项目可在 `.claude/memory/synonyms.md` 维护等价组降低误报率 4. **污染检测边界**(重申)— 架构层级保留 / 具体类名路径删除 5. **被调用静默返回** — `/memory-sync` 内 Phase 9 不输出收尾 diff --git a/plugins/memcore/skills/memory-sync/SKILL.md b/plugins/memcore/skills/memory-sync/SKILL.md index 6fcd189..24c2709 100644 --- a/plugins/memcore/skills/memory-sync/SKILL.md +++ b/plugins/memcore/skills/memory-sync/SKILL.md @@ -8,7 +8,8 @@ description: 项目记忆体系完整同步。Git检查→远程补充本地→ 记忆体系完整同步周期。**本地 `.claude/memory/` 是唯一权威**,远程为镜像。会话目录 = `$PROJECT_DIR`。 ``` -Phase 0-4 前置(git + 锚点 + 远程→本地补充 + 多机检测 + diff) +Phase 0 Git 准备(冲突解决优先 → 普通变更提交) +Phase 1-4 前置(锚点 + 远程→本地补充 + 多机/并发检测 + diff) Phase 5 /memory-update(本地写入) Phase 6 /memory-lint(收敛) Phase 7-9 CLAUDE.md 维护与记忆引导区块注入 @@ -18,15 +19,48 @@ Phase 11 完成报告 --- -## Phase 0 — Git 检查 +## Phase 0 — Git 准备(冲突解决 → 变更提交) ```bash git -C "$PROJECT_DIR" status --short ``` -- 有未提交变更 → 展示文件、询问 commit message(默认 `chore: sync before memory update`)→ `git add .claude/memory/ && git commit -m ""` → 记新 hash -- 干净 → `git rev-parse --short HEAD` → `$HEAD_HASH` -- 非 git 仓库 → 跳过 Phase 0,commit 字段填 `N/A` +非 git 仓库 → 跳过 Phase 0,commit 字段填 `N/A`。 + +### Step 1 — 冲突优先检测(必须先于 commit) + +```bash +git -C "$PROJECT_DIR" diff --name-only --diff-filter=U -- .claude/memory/ +``` + +有冲突文件(输出非空)→ 执行**语义合并**(见规则表)→ `git add .claude/memory/ && git commit -m "chore: resolve memory merge conflicts"` → 更新 `$HEAD_HASH` → 跳至 Phase 1。 + +无冲突 → 继续 Step 2。 + +**语义合并规则**(冲突文件逐个处理): + +| 冲突类型 | 处理方式 | +|---------|---------| +| frontmatter `last_updated` | 取两者较新日期 | +| frontmatter `commit` | 取 HEAD 侧(本地权威) | +| `## Section` 块 — 两边内容相同 | 保留一份 | +| `## Section` 块 — 仅本地有 | 保留 | +| `## Section` 块 — 仅远端有 | 追加到文件末尾 | +| `## Section` 块 — 两边均有且不同 | 本地原位保留,远端追加为 `## [合并待审] Section`,标注 `` | +| `MEMORY.md` 索引 | 取本地版本,不尝试合并;Phase 6 lint 重建 | +| `user_profile.md` / `synthesis_*.md` | 整文件不自动合并,在文件头追加 `` | + +合并前备份: +```bash +cp "$conflicted_file" "${conflicted_file%.md}.conflict_backup_$(git rev-parse --short HEAD).md" +``` +备份文件加入 `.gitignore`(`*.conflict_backup_*.md`),不提交。 + +### Step 2 — 普通变更提交 + +有未提交变更(非冲突)→ 展示文件、询问 commit message(默认 `chore: sync before memory update`)→ `git add .claude/memory/ && git commit -m ""` → 记新 hash。 + +干净工作区 → `git rev-parse --short HEAD` → `$HEAD_HASH`。 --- @@ -81,6 +115,34 @@ done - `n` → 终止整个 sync 流程 - `y` → 继续(Phase 10 仍按本地权威覆盖远程) +### 并发分歧检测(mtime 差 < 7 天的冲突预警) + +对「两边都存在且 mtime 差 < 7 天」的文件,进一步做内容比对: + +```bash +for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do + local="$PROJECT_DIR/.claude/memory/$(basename "$f")" + [ ! -f "$local" ] && continue + diff_days_abs=$(...) # 绝对值 < 7 + if [ "$diff_days_abs" -lt 7 ] && ! diff -q "$f" "$local" > /dev/null 2>&1; then + echo "⚡ $(basename "$f") 双边近期均有改动,内容不同" + fi +done +``` + +发现 ≥1 个双边分歧文件 → 执行**轻量节段合并**(不等 git 冲突): + +1. 提取远端文件中所有 `## Section` 块 +2. 检查本地文件是否含同名 `## Section`: + - **不含** → 将整个远端 Section 追加到本地文件末尾(自动合并) + - **含且内容相同** → 跳过 + - **含且内容不同** → 在本地文件该 Section 末尾追加注释: + ``,并将远端版本追加为 `## [远端版本] Section` +3. 不修改 `MEMORY.md`(由 Phase 6 lint 重建) +4. 完成后输出合并摘要,提示用户审查 `` 标记 + +**此步骤的保护边界**:仅处理 decisions.md / feedback*.md / project*.md;`user_profile.md` 和 `synthesis_*.md` 不自动合并(内容主观性强,直接标 NEED-HUMAN)。 + --- ## Phase 4 — diff 范围 @@ -164,6 +226,9 @@ cp -pf "$PROJECT_DIR/.claude/memory/"*.md ~/.claude/projects/{PROJECT_KEY}/memor ``` ✓ memory-sync 完成 +⚡ 并发冲突处理:git冲突 N 个文件 / 双边分歧 M 个文件(均为 0 则省略本行) + 含 / 标记的条目请通过 /memory-lint 审查 + 📋 CLAUDE.md [已更新 / 已新建 / 无变更] 📖 记忆引导区块 [已注入 / 已刷新 / 无变更] @@ -185,8 +250,9 @@ cp -pf "$PROJECT_DIR/.claude/memory/"*.md ~/.claude/projects/{PROJECT_KEY}/memor ## 执行约束 -1. **Phase 0 最先** — 有未提交代码不允许跳过 +1. **Phase 0 最先** — 冲突检测(Step 1)必须先于普通变更提交(Step 2);有未解决冲突不允许跳过语义合并直接进入 Phase 1 2. **方向严格区分** — Phase 3 只补充 / Phase 10 才覆盖 3. **顺序固定** — Phase 5(update)→ Phase 6(lint);lint 在 update 写入完毕后检查 4. **统一推送** — update + lint 修改全部本地完成后由 Phase 10 一次推 5. **记忆引导区块强制存在** — 每次 sync 后 CLAUDE.md 必须含最新区块,文件清单与 MEMORY.md 严格一致 +6. **并发冲突处理顺序** — git 冲突(Phase 0 Step 1)→ mtime 分歧合并(Phase 3)→ 两者均完成后才进 Phase 5;`` / `` 标记由 lint 扫描、用户事后审查 diff --git a/plugins/memcore/skills/memory-update/SKILL.md b/plugins/memcore/skills/memory-update/SKILL.md index 07b8fc6..46a9c3b 100644 --- a/plugins/memcore/skills/memory-update/SKILL.md +++ b/plugins/memcore/skills/memory-update/SKILL.md @@ -109,7 +109,7 @@ commit: HASH 2. 主题相关 → 新条目末尾追加 `[[file.md#标题]]` 3. **反向也补**:被引用的旧条目末尾补充对新条目的引用 -### synthesis 双触发模式 +### synthesis 触发模式(三路) **A. 会话内主动**:会话出现技术选型对比 / Bug 根因 / 架构演进 / 性能安全分析时,主动提议归档为 `synthesis_{type}_{topic}.md`。 @@ -126,6 +126,37 @@ commit: HASH 5. `n` → 原条目末尾加 ``,30 天免打扰 6. `skip-all` → 本次不再提议 +### 3C — 即时引用计数快扫(不依赖 lint) + +每次执行 Phase 3 末尾**强制运行**。目的:在短会话或任务型对话中,不依赖 lint 的延迟触发,直接检测 synthesis 升级候选。 + +```bash +# 对 decisions.md / feedback*.md 的每个 ## 条目,统计被多少不同源文件引用 +for entry_file in "$PROJECT_DIR/.claude/memory/decisions.md" \ + "$PROJECT_DIR/.claude/memory/feedback"*.md; do + [ -f "$entry_file" ] || continue + fn=$(basename "$entry_file") + while IFS= read -r title; do + count=$(grep -rl "\[\[${fn}#${title}\]\]" \ + "$PROJECT_DIR/.claude/memory/" --include="*.md" \ + | grep -v "^${entry_file}$" | wc -l) + [ "$count" -ge 3 ] && echo "$count|$fn#$title" + done < <(grep "^## " "$entry_file" | sed 's/^## //') +done | sort -t'|' -k1 -rn +``` + +对每条输出候选(`count|file#title`): +1. 读原条目内是否含 `**Synthesized:**` → 已升级,跳过 +2. 读原条目内是否含 `` → 30 天内,跳过 +3. 以上均无 → 触发提议(同 B 模式 step 3-6) + +**与 lint 的分工**: +- Phase 3C(快扫):每次 memory-update 必跑,判据为「存在引用行数」,适合即时触发 +- lint Phase 3A(精扫):按源文件去重的精确计数,月度健康检查时运行 +- 两者以 `**Synthesized:**` 标记为唯一判重依据,不重复创建文件 + +--- + ### 写入要点 - 仅更新有变化维度,不重写无关文件 @@ -161,5 +192,5 @@ commit: HASH 2. **不记录可推断内容** — 实现细节、文件路径、git 历史不入库 3. **feedback 拆分** — 同主题 >5 条规则 → 拆出 `feedback_{topic}.md` 4. **See Also 双向同步** — 新增时扫关联并双向补 -5. **synthesis 双触发** — 会话主动 + lint Top 反向;`**Synthesized:**` 标记不可覆盖;`` 标记 30 天免打扰 +5. **synthesis 三触发** — 会话主动 + Phase 3C 即时快扫 + lint Top 反向;`**Synthesized:**` 标记不可覆盖;`` 标记 30 天免打扰 6. **被调用静默返回** — `/memory-sync` 内执行不输出收尾