Compare commits
2
Commits
4bf58796cf
...
a9a89e57c3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9a89e57c3 | ||
|
|
38beecb2d0 |
@@ -1,9 +1,9 @@
|
||||
# Memory Index
|
||||
> _Last synced: 2026-05-10 | Base commit: `f26e741`_
|
||||
> _Last synced: 2026-06-12 | Base commit: `38beecb`_
|
||||
|
||||
| 文件 | 描述 | 类型 | 引用 | Commit |
|
||||
|------|------|------|------|--------|
|
||||
| decisions.md | 关键架构决策:无版本号/userConfig/Bearer Token/SKILL.md规范/路径锁定/memcore三项优化决策 | project | 1 | f26e741 |
|
||||
| project_overview.md | 项目定位、目录结构、插件规范、发布流程(huanxi/memcore/obsidian) | project | 1 | f26e741 |
|
||||
| feedback_plugin_dev.md | 插件开发协作规范:同步四处/路径解析/工具签名对照 | feedback | 0 | 0c46ed0 |
|
||||
| lint_report.md | memory-lint 最新执行结果 | lint | 0 | 0c46ed0 |
|
||||
| decisions.md | 关键架构决策:无版本号/userConfig/Bearer Token/SKILL.md规范/路径锁定/memcore三项优化/memcore-shared共享层/lint_report保活/Base commit兜底 | project | 1 | 38beecb |
|
||||
| project_overview.md | 项目定位、目录结构、插件规范、发布流程(huanxi/memcore/obsidian) | project | 1 | 38beecb |
|
||||
| feedback_plugin_dev.md | 插件开发协作规范:同步四处/路径解析/工具签名对照/MCP docstring单一真相/签名变更全量扫描 | feedback | 1 | 38beecb |
|
||||
| lint_report.md | memory-lint 最新执行结果 | lint | 0 | 38beecb |
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: 架构决策
|
||||
description: Marketplace 设计中的关键技术决策及其原因
|
||||
type: project
|
||||
last_updated: 2026-05-10
|
||||
commit: f26e741
|
||||
last_updated: 2026-06-12
|
||||
commit: 38beecb
|
||||
---
|
||||
|
||||
# 关键架构决策
|
||||
@@ -95,6 +95,40 @@ commit: f26e741
|
||||
|
||||
---
|
||||
|
||||
## memcore-shared:路径锁定 + 全局常量的单一来源
|
||||
|
||||
**结论**:把路径锁定、全局常量(SYNTHESIS_THRESHOLD / LINT_STALE_*_DAYS / MULTI_HOST_WARN_DAYS)、PROJECT_DIR 跨平台解析提取到独立 skill `memcore-shared`,三个主技能(memory-sync / memory-update / memory-lint)开头 `Read ../memcore-shared/SKILL.md` 引用其约束。description 中显式说明"内部 include,不由用户直接调用"。
|
||||
|
||||
**Why**:原设计中 memory-update 和 memory-lint 各自维护一份 20 行的"路径锁定"块,完全重复;阈值常量 `≥3`、`≥30/90 天`、`≥7 天` 分散硬编码在多个文件多个位置,调整需多处改动。共享层独立成 skill 后:① 单点维护、② 阈值修改只动一处、③ 与 huanxi-shared 同模式,可演进性强。
|
||||
|
||||
**How to apply**:未来 memcore 类多 skill 插件如出现「共享约束 + 多处硬编码常量」时,提取为独立 `<plugin>-shared` skill;常量声明在共享 skill 顶部表格,子技能引用常量名而非裸数字。
|
||||
|
||||
**See Also**:[[decisions.md#memcore memory-update/lint 路径锁定:禁止写入系统自动记忆路径]] [[feedback_plugin_dev.md#skill 不要重写 MCP 参数表,引用 docstring]]
|
||||
|
||||
---
|
||||
|
||||
## memcore lint_report 增量保活:稳定 ID + resolved 跳过
|
||||
|
||||
**结论**:lint Phase 8 生成 NEED-HUMAN 条目时,末尾附 `<!-- id: 8位sha1 -->`(基于 phase + 文件 + 章节 + 关键事实计算)。Phase 8-pre 提取旧 `lint_report.md` 中带 `<!-- resolved -->` 标记的 ID 集合,新报告中同 ID 条目跳过。
|
||||
|
||||
**Why**:原 lint_report.md 每次覆盖写入,用户即使在 NEED-HUMAN 条目处理完或决定"不处理"后,下次 lint 仍会重新列出。导致信号疲劳,长期看反而忽视所有 lint 提示。引入稳定 ID + resolved 标记后,用户对每个条目的判断(处理/接受现状)能跨多次 lint 持续生效,lint_report 变成只列"真正待处理"的事项。
|
||||
|
||||
**How to apply**:任何"周期性扫描 + 报告生成"的 lint/check 系统,凡有用户主观判断维度(不只是机器判定)时,输出条目都应有稳定 ID + 用户标记跳过机制。ID 计算用「问题本体」字段(位置+事实),不要包含执行时间/扫描序号。
|
||||
|
||||
---
|
||||
|
||||
## memory-update Phase 1 锚点丢失兜底
|
||||
|
||||
**结论**:memory-update Phase 1 读 `Base commit` 锚点时,若 MEMORY.md 头部该行缺失或为 N/A,从各 memory 文件 frontmatter 的 `commit:` 字段取最旧值兜底,避免退化为全量。
|
||||
|
||||
**Why**:MEMORY.md 头部 `Base commit: HASH` 是单一锚点来源,一旦用户手动编辑误删此行,整个 git diff 范围退化为全量审查,触发 memory-update 对所有文件做"按变更维度重写"。即使大部分文件没真实变化,也会被刷一次 last_updated 和 commit 字段,造成虚假改动。兜底机制从各文件 frontmatter 取最旧 commit,确保覆盖所有真实差量而非无差别全量。
|
||||
|
||||
**How to apply**:任何"单点配置 → 关键路径"的设计,必须考虑配置丢失时的退路。优先级:单点 → 多点冗余 → 兜底推导。memcore 当前是「单点 + 兜底推导」,无需冗余存储。
|
||||
|
||||
**See Also**:[[decisions.md#memcore memory-sync:冲突检测必须先于 git commit]]
|
||||
|
||||
---
|
||||
|
||||
## SKILL.md frontmatter 只保留 name 和 description
|
||||
|
||||
**结论**:SKILL.md frontmatter 只写 `name` 和 `description` 两个字段,去掉 `version`。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: 插件开发协作反馈
|
||||
description: 在此 marketplace 项目中开发插件时需遵守的协作规范和经验教训
|
||||
type: feedback
|
||||
last_updated: 2026-05-01
|
||||
commit: 0c46ed0
|
||||
last_updated: 2026-06-12
|
||||
commit: 38beecb
|
||||
---
|
||||
|
||||
# 插件开发协作规范
|
||||
@@ -55,3 +55,33 @@ commit: 0c46ed0
|
||||
**Why**:本次发现 huanxi-shared 工具索引中 report_submit/withdraw 用了旧名,leader_report_submit/withdraw 缺必填参数,weekly_report_save 参数名用 week 而非 week_number,这些都是 MCP 升级后 skill 未同步导致的。
|
||||
|
||||
**How to apply**:每次 MCP server 工具链升级后,运行 plugin-validator 对照检查 skill 中的工具调用。
|
||||
|
||||
---
|
||||
|
||||
## skill 不要重写 MCP 参数表,引用 docstring 为单一真相
|
||||
|
||||
**规范**:MCP 工具的参数细节(字段名、必填、枚举值、类型)以后端 Python 函数 docstring 为**单一真相来源**。skill 文档不要重画完整字段表,最多给一个 happy path 的调用示例 + 历史踩坑说明,在 reference 文档顶部统一声明"参数细节以 MCP `<tool_name>` 的 docstring 为准"。
|
||||
|
||||
**Why**:本次发现 `huanxi-report/references/report-draft.md` 的字段表与后端 `report_save_draft` docstring 大幅漂移(缺 module_id 必填、progress 字段名错为 progress 应为 progress_update、虚构 status 字段),直接导致用户日报频繁报"参数缺失"。skill 一旦重画参数表,就和 MCP docstring 形成两套真相 —— 任一处改动另一处就漂移。同类漂移在 weekly(week→week_number)、task(due_date→end_date / urgent→critical / todo→not_started)、org(user_id→id)系列均出现,呈系统性问题。
|
||||
|
||||
**How to apply**:
|
||||
1. 写 skill 时不画字段表;如非要列字段,必须在文末加"以 MCP docstring 为准"声明
|
||||
2. 给 LLM 的提示是"调 MCP 时直接信任 docstring"而非"按本文档调用"
|
||||
3. MCP 工具签名变更时**不需要**改 skill(只要 skill 没硬编码参数表)
|
||||
|
||||
**See Also**:[[feedback_plugin_dev.md#plugin-validator 和 skill-reviewer 审查之后要对照实际代码修正工具签名]] [[feedback_plugin_dev.md#MCP 后端工具签名变更后必须全量扫描所有 skill]] [[decisions.md#memcore-shared:路径锁定 + 全局常量的单一来源]]
|
||||
|
||||
---
|
||||
|
||||
## MCP 后端工具签名变更后必须全量扫描所有 skill
|
||||
|
||||
**规范**:MCP server 的工具签名(参数名、必填项、枚举值、返回字段)变更后,必须对引用该 MCP 的所有 skill 做全量 grep 扫描,找到漂移点逐一对齐。不要依赖单元测试或调用时报错来"被动发现"。
|
||||
|
||||
**Why**:本次扫描发现 huanxi 的 6 个 skill + 7 个 reference 中漂移密度极高:4 类典型模式(字段名错 / 枚举值错 / 缺必填 / 缓存示例与后端返回结构不一致)覆盖所有 huanxi-* 系列。漂移源于后端 docstring 在多次迭代中演进,但 skill 未同步审查。这种漂移在调用时才会被发现("参数缺失"、"字段不存在"),对用户体验是慢性损耗。
|
||||
|
||||
**How to apply**:
|
||||
1. 后端 PR 中涉及 MCP 工具的,PR 描述必须列出签名变更点
|
||||
2. 合并后立即在 marketplace 仓库做对照扫描(grep 漂移关键词,如旧字段名)
|
||||
3. 漂移修正与签名变更在同一 sprint 完成,不留尾巴
|
||||
|
||||
**典型扫描点**(针对 huanxi):参数名 `progress` vs `progress_update`、`due_date` vs `end_date`、`week` vs `week_number`;枚举值 `todo` vs `not_started`、`urgent` vs `critical`;返回字段 `user_id` vs `id`。
|
||||
|
||||
@@ -2,38 +2,59 @@
|
||||
name: 记忆健康检查报告
|
||||
description: memory-lint 最新一次执行的检查结果与待处理项
|
||||
type: lint
|
||||
last_updated: 2026-05-10
|
||||
last_updated: 2026-06-12
|
||||
commit: 38beecb
|
||||
---
|
||||
|
||||
# 记忆健康检查报告
|
||||
|
||||
> _执行时间: 2026-05-10 | Base commit: `f26e741` | Last synced: 2026-05-10_
|
||||
> _执行时间: 2026-06-12 | Base commit: `38beecb` | Last synced: 2026-06-12_
|
||||
>
|
||||
> **如何使用**:NEED-HUMAN 条目末尾有 `<!-- id: xxxxxxxx -->` 标记。处理完或决定不处理时,在同段追加 `<!-- resolved: DATE, 简要原因 -->`,下次 lint 该条目自动跳过。
|
||||
|
||||
## 健康概览
|
||||
|
||||
| 检查项 | AUTO-FIX | NEED-HUMAN |
|
||||
|--------|---------|-----------|
|
||||
| 1 孤儿 / 2 幽灵 / 3A 引用 / 3B 双链 | 0 / 0 / 0 / 0 | — / — / 0 / 0 |
|
||||
| 1 孤儿 / 2 幽灵 / 3A 引用 / 3B 双链 | 0 / 0 / 0 / 1 | — / — / 0 / 0 |
|
||||
| 4 矛盾 / 5 过期 / 6 污染 | — | 0 / 0 / 0 |
|
||||
|
||||
**AUTO-FIX 已执行 0 项 | NEED-HUMAN 待处理 0 项**
|
||||
**AUTO-FIX 已执行 1 项 | NEED-HUMAN 新列出 0 项 | 历史已 resolved 跳过 0 项**
|
||||
|
||||
---
|
||||
|
||||
## AUTO-FIX 已执行清单
|
||||
|
||||
无
|
||||
- [x] 双链补全(Phase 3B):`feedback_plugin_dev.md#skill 不要重写 MCP 参数表,引用 docstring` 末尾追加对 `[[decisions.md#memcore-shared:路径锁定 + 全局常量的单一来源]]` 的反向引用
|
||||
- [x] MEMORY.md「引用」列已刷新(4 文件)
|
||||
|
||||
---
|
||||
|
||||
## 条目级高频引用 Top(供 /memory-update 消费)
|
||||
|
||||
无候选(所有条目跨文件引用次数 < 3)
|
||||
跨 ≥`SYNTHESIS_THRESHOLD`(默认 3)个不同源文件被引用的 decisions/feedback 条目。
|
||||
|
||||
| 条目 | 跨文件次数 | 建议 |
|
||||
|------|----------|------|
|
||||
| — | — | 无候选 |
|
||||
|
||||
当前所有 decisions/feedback 条目的跨文件引用数均 < 3,无 synthesis 升级候选。
|
||||
|
||||
---
|
||||
|
||||
## NEED-HUMAN 待处理清单
|
||||
|
||||
✅ 全部通过,无待处理项。
|
||||
✅ 本次扫描无 NEED-HUMAN 待处理项,记忆体系健康。
|
||||
|
||||
**备注**:`synonyms.md` 不存在,矛盾检测使用保守模式(仅检测直接数值/版本冲突)。如项目有领域术语缩写,建议创建 `.claude/memory/synonyms.md`。
|
||||
**备注**:`synonyms.md` 不存在,矛盾检测使用保守模式(仅检测直接数值/版本冲突)。如项目有领域术语缩写,建议创建 `.claude/memory/synonyms.md`(首次创建后会被 Phase 2 自动登记为 reference 类型入索引)。
|
||||
|
||||
---
|
||||
|
||||
## 文件级引用计数(来自 Phase 3A,按源文件去重)
|
||||
|
||||
| 文件 | 被引用次数(去重源) | 引用来源 |
|
||||
|------|-------|---------|
|
||||
| project_overview.md | 1 | decisions.md(2 个章节,同一源文件去重为 1) |
|
||||
| decisions.md | 1 | project_overview.md |
|
||||
| feedback_plugin_dev.md | 1 | decisions.md |
|
||||
| lint_report.md | 0 | — |
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name: 项目概述
|
||||
description: yixiong-claude-marketplace 的定位、目录结构、插件规范和发布流程
|
||||
type: project
|
||||
last_updated: 2026-05-10
|
||||
commit: f26e741
|
||||
last_updated: 2026-06-12
|
||||
commit: 38beecb
|
||||
---
|
||||
|
||||
# 蚁熊内部 Claude Code Marketplace
|
||||
@@ -60,8 +60,8 @@ description: "触发描述(用户实际口语,不用内部视角)"
|
||||
|
||||
| 插件 | 技能 | 特性 |
|
||||
|------|------|------|
|
||||
| `huanxi` | 6 个(report/leader/task/weekly/org/shared) | userConfig Bearer Token + MCP Server |
|
||||
| `memcore` | 3 个(memory-sync/lint/update) | 纯技能,无 MCP;支持 synonyms.md 等价词表、Phase 3C 即时引用快扫、Phase 0 并发冲突保护 |
|
||||
| `huanxi` | 6 个(report/leader/task/weekly/org/shared) | userConfig Bearer Token + MCP Server(URL 走 office 子域,无端口) |
|
||||
| `memcore` | 4 个(memory-sync/lint/update/shared) | 纯技能,无 MCP;memcore-shared 作内部 include(路径锁定 + 阈值常量 + PROJECT_DIR 解析),支持 synonyms.md 等价词表、Phase 3C 即时引用快扫、Phase 0 并发冲突保护、lint_report 稳定 ID + resolved 跳过、Base commit 兜底 |
|
||||
| `obsidian` | 9 个(obsidian/bases/daily/history/meta/plugins/search/tasks/workflow-pkm) | 纯技能,无 MCP |
|
||||
|
||||
**See Also**:[[decisions.md#huanxi plugin 使用 userConfig 而非环境变量传 Token]]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- Last updated: 2026-05-08 | Commit: 9c91382 -->
|
||||
<!-- Last updated: 2026-06-12 | Commit: 38beecb -->
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
@@ -77,17 +77,25 @@ description: 一句话说明该技能的用途(Claude 用此判断何时触发
|
||||
| 插件 | 技能 | 说明 |
|
||||
|------|------|------|
|
||||
| `huanxi` | `/huanxi-shared` `/huanxi-report` `/huanxi-leader` `/huanxi-task` `/huanxi-weekly` `/huanxi-org` | 寰汐企业管理系统完整工作流,含 MCP Server 自动配置 |
|
||||
| `memcore` | `/memory-sync` `/memory-update` `/memory-lint` | 项目记忆体系核心引擎 |
|
||||
| `memcore` | `/memory-sync` `/memory-update` `/memory-lint` `/memcore-shared`(内部 include) | 项目记忆体系核心引擎 |
|
||||
| `obsidian` | `/obsidian` `/obsidian-bases` `/obsidian-daily` `/obsidian-history` `/obsidian-meta` `/obsidian-plugins` `/obsidian-search` `/obsidian-tasks` `/obsidian-workflow-pkm` | Obsidian 知识库完整工作流(9 个技能) |
|
||||
|
||||
### memcore 技能调用关系
|
||||
|
||||
```
|
||||
/memcore-shared ← 内部 include(路径锁定 + 全局常量 + PROJECT_DIR 解析),不由用户直接调用
|
||||
↑ Read 引用
|
||||
│
|
||||
/memory-sync ← 总编排(11 phases),调用下面两个技能
|
||||
├── /memory-update ← 增量写入,可独立执行
|
||||
└── /memory-lint ← 健康校验,可独立执行
|
||||
```
|
||||
|
||||
**关键常量统一来源**(修改 memcore-shared 一处即可全局生效):
|
||||
- `SYNTHESIS_THRESHOLD` = 3(synthesis 升级跨文件引用阈值)
|
||||
- `LINT_STALE_WARN_DAYS` = 30 / `LINT_STALE_ERROR_DAYS` = 90(过期阈值)
|
||||
- `MULTI_HOST_WARN_DAYS` = 7(多机不同步预警阈值)
|
||||
|
||||
## 记忆体系(会话启动必读)
|
||||
|
||||
> 每次新会话或长会话压缩后,必须先读 `MEMORY.md` 索引再按需加载文件。代码与记忆冲突 → 以代码为准并更新记忆。
|
||||
@@ -95,17 +103,17 @@ description: 一句话说明该技能的用途(Claude 用此判断何时触发
|
||||
### 读取流程
|
||||
|
||||
1. `cat .claude/memory/MEMORY.md` 获取清单
|
||||
2. **必读**(type=`project`/`feedback`):decisions.md / feedback_plugin_dev.md / project_overview.md
|
||||
3. **按需**(type=`lint`):lint_report.md
|
||||
2. **必读**(type=`project`/`feedback`):decisions.md / project_overview.md / feedback_plugin_dev.md
|
||||
3. **按需**(type=`lint`):lint_report.md(仅查看 NEED-HUMAN 待处理项时读)
|
||||
|
||||
### 记忆目录骨架
|
||||
|
||||
```
|
||||
.claude/memory/
|
||||
├── MEMORY.md # 索引(入口)
|
||||
├── decisions.md # 关键架构决策
|
||||
├── project_overview.md # 项目定位与结构
|
||||
├── feedback_plugin_dev.md # 插件开发协作规范
|
||||
├── decisions.md # 关键架构决策(含 memcore-shared/lint_report 保活/Base commit 兜底等 11 项)
|
||||
├── project_overview.md # 项目定位与结构(huanxi/memcore/obsidian 已发布插件)
|
||||
├── feedback_plugin_dev.md # 插件开发协作规范(含 MCP docstring 单一真相、签名变更全量扫描)
|
||||
└── lint_report.md # 记忆健康检查报告(按需)
|
||||
```
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"mcpServers": {
|
||||
"huanxi": {
|
||||
"type": "http",
|
||||
"url": "https://huanxi.yixiong-tech.com:18085/mcp/",
|
||||
"url": "https://huanxi.office.yixiong-tech.com/mcp/",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${user_config.token}"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 负责人日报草稿(+draft)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `leader_report_save` / `llm_generate_leader_summary` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 两种草稿模式
|
||||
|
||||
### 模式 A:AI 自动生成
|
||||
@@ -29,13 +31,22 @@
|
||||
```
|
||||
mcp__huanxi__leader_report_save(
|
||||
report_date = "YYYY-MM-DD", ← 日期格式
|
||||
module_id = "<模块ID>", ← 从 modules.json 缓存取
|
||||
content = "<正文内容>" ← 支持 Markdown
|
||||
scope_type = "module", ← 默认 "module";组织维度填 "org"
|
||||
module_id = "<模块ID>", ← scope_type="module" 时必填,从 modules.json 缓存取
|
||||
# org_id = "<组织ID>", ← scope_type="org" 时必填,与 module_id 互斥
|
||||
content = "<正文内容>", ← 支持 Markdown,三段式(今日进展/问题与风险/明日重点)
|
||||
# progress_corrections = [ ← 可选:手动修正模块进度
|
||||
# { "module_id": "<id>", "new_progress": 75 }
|
||||
# ]
|
||||
)
|
||||
```
|
||||
|
||||
**返回值**:保存成功后返回草稿 ID,告知用户已保存,询问是否立即提交。
|
||||
|
||||
**注意**:
|
||||
- 同一用户同一日期同一 scope 只有一条记录(重复调用是更新)
|
||||
- 默认走 module 维度;只有组织负责人需要 org 维度时才传 `scope_type="org"` + `org_id`
|
||||
|
||||
---
|
||||
|
||||
## 多模块批量操作
|
||||
|
||||
@@ -104,13 +104,15 @@ Step 3: 告知用户:缓存已刷新(模块 N 个,用户 M 人)
|
||||
{
|
||||
"cached_at": "2026-04-13T09:00:00+08:00",
|
||||
"data": {
|
||||
"user_id": "123",
|
||||
"id": "123",
|
||||
"name": "张三",
|
||||
"feishu_user_id": "ou_xxx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 用户身份的系统内部 ID 字段名是 `id`(与后端 `user_get_me` / `user_list` 返回结构一致),不是 `user_id`。
|
||||
|
||||
**modules.json:**
|
||||
```json
|
||||
{
|
||||
@@ -127,7 +129,7 @@ Step 3: 告知用户:缓存已刷新(模块 N 个,用户 M 人)
|
||||
{
|
||||
"cached_at": "2026-04-13T09:00:00+08:00",
|
||||
"data": [
|
||||
{ "user_id": "456", "name": "李四", "feishu_user_id": "ou_yyy" }
|
||||
{ "id": "456", "name": "李四", "feishu_user_id": "ou_yyy" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# 名字 → ID 解析
|
||||
|
||||
> ⚠️ 参数细节以 MCP `module_list` / `user_list` / `user_get_me` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
本文件详细说明如何将模块名、人员名解析为系统 ID,所有步骤均**缓存优先**。
|
||||
|
||||
**字段名约定**:用户/模块的系统内部 ID 字段名统一为 `id`(与后端返回结构一致),不要写成 `user_id`/`module_id` 作为 JSON 字段名。`module_id`/`user_id` 仅在传入 MCP 工具参数时使用。
|
||||
|
||||
---
|
||||
|
||||
## 模块名 → 模块 ID {#modules}
|
||||
@@ -33,7 +37,7 @@
|
||||
→ 检查 cached_at,若 age < 24h → 在 data 数组中查找
|
||||
|
||||
2. 查找逻辑:
|
||||
a. name 精确匹配 → 返回 user_id
|
||||
a. name 精确匹配 → 返回 user.id
|
||||
b. name 包含输入 → 列出候选
|
||||
c. 未找到 → 执行 Step 3
|
||||
|
||||
@@ -46,8 +50,8 @@
|
||||
```
|
||||
|
||||
**特别注意:**
|
||||
- `user_id`(系统内部 ID)≠ `feishu_user_id`(飞书 open_id)
|
||||
- 设置任务执行人用 `user_id`
|
||||
- 用户的系统内部 ID 字段名是 `id`(后端 `user_list` 返回结构),`≠ feishu_user_id`(飞书 open_id)
|
||||
- 设置任务执行人时,MCP 工具的参数名叫 `assignee_ids`,传入的值就是 user.id 列表
|
||||
- 飞书消息通知用 `feishu_user_id`(MCP 内部会自动处理,无需手动区分)
|
||||
|
||||
---
|
||||
@@ -58,7 +62,7 @@
|
||||
|
||||
```
|
||||
1. 解析模块 → read modules.json → 匹配"前端开发" → mod_001
|
||||
2. 解析人员 → read users.json → 匹配"李四" → user_id: 456
|
||||
2. 解析人员 → read users.json → 匹配"李四" → id: 456
|
||||
3. 若任一缓存未命中:先拉 MCP,写缓存,再继续
|
||||
4. 两个 ID 都拿到后 → 调用 task_create(module_id="mod_001", ...)
|
||||
5. 创建完成后 → task_set_assignees(task_id, ["456"])
|
||||
|
||||
@@ -28,12 +28,14 @@ Step 2: 查看今日日报状态
|
||||
|
||||
Step 3: 获取待汇报任务并收集内容
|
||||
→ mcp__huanxi__report_get_tasks_to_report()
|
||||
→ 展示待汇报任务列表(task_id, name, 模块, 当前进度)
|
||||
→ 返回的每个任务条目含:id(task_id)、title、module_id、module_name、progress 等
|
||||
→ 展示待汇报任务列表(任务名、模块、当前进度)
|
||||
→ 引导用户逐一填写今日进展和完成百分比
|
||||
→ 详见 references/report-draft.md
|
||||
|
||||
Step 4: 保存草稿并展示初稿
|
||||
→ mcp__huanxi__report_save_draft(items=[...])
|
||||
→ ⚠️ items 字段以 MCP docstring 为准;每条必须带 module_id(取自 Step 3 任务条目)
|
||||
→ 展示完整初稿内容供用户预览
|
||||
|
||||
Step 5: 询问是否 AI 润色
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
# 保存日报草稿(+draft)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `report_save_draft` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 前置
|
||||
|
||||
已通过 `report_get_tasks_to_report()` 获取待汇报任务列表。
|
||||
已通过 `report_get_tasks_to_report()` 获取待汇报任务列表。返回的每个任务条目至少含 `id`(task_id)、`title`、`module_name`,**以及 module_id 字段**(保存草稿必需)。
|
||||
|
||||
---
|
||||
|
||||
## 草稿数据结构
|
||||
## items 字段(与后端签名一致)
|
||||
|
||||
每个 `item` 包含:
|
||||
| 字段 | 必填 | 类型 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `module_id` | ✅ **必填** | string (UUID) | 任务所属模块 ID,从 `report_get_tasks_to_report()` 返回的任务条目里取(不要从任务名推断) |
|
||||
| `task_id` | 可选 | string (UUID) | 任务 ID;不传则为模块级汇报 |
|
||||
| `content` | ✅ **必填** | string | 汇报内容(今日进展),支持 Markdown,可为空字符串 |
|
||||
| `progress_update` | 可选 | int (0-100) | 任务进度百分比(字段名是 `progress_update`,不是 `progress`) |
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `task_id` | string | 任务 ID(从待报任务中取) |
|
||||
| `content` | string | 汇报内容(今日进展) |
|
||||
| `progress` | int | 任务进度(0-100,整数) |
|
||||
| `status` | string | 可选,不改变则不传 |
|
||||
⚠️ **历史踩坑**:曾用错的字段名 `progress`、`status`,以及遗漏 `module_id`,会触发"参数缺失"错误。
|
||||
|
||||
---
|
||||
|
||||
@@ -33,12 +35,18 @@ Step 1: 展示待汇报任务列表,引导用户逐一填写内容
|
||||
└─────────────────────────────────────────
|
||||
|
||||
Step 2: 收集所有填写内容,构建 items 数组
|
||||
⚠️ 每个 item 必须含 module_id(来自 Step 0 的任务条目)
|
||||
|
||||
Step 3: [可选] 若用户请求 AI 辅助 → mcp__huanxi__llm_polish_report(content)
|
||||
将润色建议展示给用户,由用户确认采用哪个版本
|
||||
|
||||
Step 4: mcp__huanxi__report_save_draft(items=[
|
||||
{ task_id: "xxx", content: "...", progress: 80 },
|
||||
{
|
||||
module_id: "<从任务条目取>",
|
||||
task_id: "<从任务条目取>",
|
||||
content: "今日完成 ...",
|
||||
progress_update: 80
|
||||
},
|
||||
...
|
||||
])
|
||||
|
||||
@@ -50,7 +58,7 @@ Step 5: 告知保存结果:
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `progress` 是 **整数百分比**(0-100),不是小数
|
||||
- `progress_update` 是 **整数百分比**(0-100),不是小数;字段名末尾必须是 `_update`
|
||||
- 用户未填写 `content` 的任务:询问是否 dismiss(今天不汇报)还是暂时跳过
|
||||
- `report_save_draft` 是 upsert 操作,多次调用不会重复创建
|
||||
- 草稿保存成功后,下次调用 `report_get_today()` 可看到 draft 状态
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 提交日报(+submit)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `report_submit_item` / `report_get_today` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 草稿已通过 `report_save_draft()` 保存
|
||||
|
||||
@@ -23,7 +23,7 @@ description: "寰汐 MCP 共享基础:本地缓存策略(me/modules/users/wo
|
||||
|
||||
| 文件 | 内容 | TTL | 刷新方式 |
|
||||
|------|------|-----|---------|
|
||||
| `me.json` | 当前用户身份(user_id, name, feishu_user_id) | 永久 | 手动删除文件 |
|
||||
| `me.json` | 当前用户身份(id, name, feishu_user_id;注意字段名是 `id` 而不是 `user_id`) | 永久 | 手动删除文件 |
|
||||
| `modules.json` | 我参与的模块列表(id, name, my_role) | 24h | 过期自动重拉 或 `/huanxi-org +sync` |
|
||||
| `users.json` | 组织用户搜索结果(name/feishu_user_id 索引) | 24h | 过期自动重拉 或 `/huanxi-org +sync` |
|
||||
| `workdays.json` | 工作日查询结果(date → bool 的 KV 字典) | 永久(按日期 key) | 已有日期不重新查 |
|
||||
|
||||
@@ -37,6 +37,8 @@ description: "寰汐任务管理:创建任务(+create)、更新任务状
|
||||
|
||||
## +update:更新任务
|
||||
|
||||
> ⚠️ 参数细节以 MCP `task_update` 的 docstring 为准,本节仅做工作流引导。
|
||||
|
||||
```
|
||||
Step 1: 确认任务 ID
|
||||
→ 若用户已提供 task_id:直接使用
|
||||
@@ -48,17 +50,24 @@ Step 1: 确认任务 ID
|
||||
Step 2: 展示当前任务状态,引导用户填写要修改的字段
|
||||
|
||||
Step 3: mcp__huanxi__task_update(task_id, {
|
||||
title? : "新标题",
|
||||
description? : "新描述",
|
||||
progress? : 80, ← 0-100 整数
|
||||
status? : "in_progress" | "done" | "todo",
|
||||
due_date? : "YYYY-MM-DD",
|
||||
priority? : "low" | "medium" | "high"
|
||||
title? : "新标题",
|
||||
description? : "新描述",
|
||||
progress? : 80, ← 0-100 整数
|
||||
progress_before? : 60, ← 修改 progress 时必传当前值(乐观锁,防并发覆盖)
|
||||
status? : "not_started" | "in_progress" | "done" | "cancelled" | "on_hold",
|
||||
end_date? : "YYYY-MM-DD", ← 字段名是 end_date,不是 due_date
|
||||
priority? : "low" | "medium" | "high" | "critical"
|
||||
})
|
||||
|
||||
Step 4: 告知更新结果
|
||||
```
|
||||
|
||||
⚠️ **历史踩坑**:
|
||||
- 字段名 `due_date` 错误,后端为 `end_date`
|
||||
- 状态值 `todo` 错误,后端为 `not_started`
|
||||
- priority 缺 `critical`,没有 `urgent`
|
||||
- 改 progress 不传 `progress_before` 会 409 冲突
|
||||
|
||||
---
|
||||
|
||||
## +assign:设置执行人
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
# 创建任务(+create)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `task_create` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 必填信息收集
|
||||
|
||||
在调用 `task_create` 前,引导用户提供:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `module_id` | ✅ | 所属模块(从缓存解析名字 → ID) |
|
||||
| `module_id` | ✅ | 所属模块 UUID(从缓存解析名字 → ID) |
|
||||
| `title` | ✅ | 任务标题(简洁明了)|
|
||||
| `description` | 可选 | 任务详情、背景、验收标准 |
|
||||
| `due_date` | 可选 | 截止日期(YYYY-MM-DD 格式)|
|
||||
| `priority` | 可选 | `low` / `medium` / `high` / `urgent`,默认 medium |
|
||||
| `assignee_ids` | 可选 | 执行人(从缓存解析人名 → user_id)|
|
||||
| `description` | 可选 | 任务详情、背景、验收标准(Markdown) |
|
||||
| `end_date` | 可选 | 截止日期(YYYY-MM-DD 格式,**字段名是 end_date,不是 due_date**) |
|
||||
| `priority` | 可选 | `low` / `medium` / `high` / `critical`,默认 `medium`(**没有 urgent**) |
|
||||
| `status` | 可选 | `not_started`(默认)/ `in_progress` |
|
||||
| `parent_task_id` | 可选 | 父任务 UUID,传此字段即为子任务 |
|
||||
| `assignee_ids` | 可选 | 执行人 user_id 列表,**可在创建时一并传入**(无需再单独调 `task_set_assignees`) |
|
||||
|
||||
---
|
||||
|
||||
@@ -22,21 +26,23 @@ Step 1: 解析模块名 → module_id
|
||||
→ Read ~/.claude/huanxi-cache/modules.json
|
||||
→ 模糊匹配模块名(详见 huanxi-org resolve-ids.md)
|
||||
|
||||
Step 2: [若用户提到执行人] 解析人名 → user_id
|
||||
Step 2: [若用户提到执行人] 解析人名 → user_id(user 对象的 id 字段)
|
||||
→ Read ~/.claude/huanxi-cache/users.json
|
||||
→ 未命中 → mcp__huanxi__user_list(name=<人名>) → 追加写缓存
|
||||
|
||||
Step 3: 创建任务
|
||||
Step 3: 创建任务(推荐一次性把执行人也带上)
|
||||
→ mcp__huanxi__task_create(
|
||||
module_id = "<模块ID>",
|
||||
title = "任务标题",
|
||||
description = "...", ← 可选
|
||||
due_date = "YYYY-MM-DD", ← 可选
|
||||
priority = "medium" ← 可选
|
||||
module_id = "<模块ID>",
|
||||
title = "任务标题",
|
||||
description = "...", ← 可选
|
||||
end_date = "YYYY-MM-DD", ← 可选;字段名 end_date
|
||||
priority = "medium", ← 可选;low/medium/high/critical
|
||||
status = "not_started", ← 可选;默认 not_started
|
||||
assignee_ids = ["<user_id>"] ← 可选;若 Step 2 有解析到,建议一并传入
|
||||
)
|
||||
→ 返回:task_id
|
||||
|
||||
Step 4: 设置执行人(若 Step 2 有解析到)
|
||||
Step 4: [仅当 Step 3 未传 assignee_ids 时] 单独设置执行人
|
||||
→ mcp__huanxi__task_set_assignees(
|
||||
task_id = "<刚创建的 task_id>",
|
||||
assignee_ids = ["<user_id>"]
|
||||
@@ -67,3 +73,14 @@ mcp__huanxi__task_create(
|
||||
parent_task_id = "<父任务ID>" ← 传此字段即为子任务
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 字段名速查(避免漂移)
|
||||
|
||||
| 概念 | 正确字段名 | 错误写法 |
|
||||
|------|----------|---------|
|
||||
| 截止日期 | `end_date` | ~~due_date~~ |
|
||||
| 紧急优先级 | `critical` | ~~urgent~~ |
|
||||
| 未开始状态 | `not_started` | ~~todo~~ |
|
||||
| 父任务 ID | `parent_task_id` | ~~parent_id~~(后端 body 内是 parent_id,但 MCP 参数是 parent_task_id) |
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
# 任务看板(+board)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `task_list_mine` / `task_list_by_module` / `people_get_board` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 查看我的任务
|
||||
|
||||
```
|
||||
Step 1: mcp__huanxi__task_list_mine()
|
||||
→ 返回我认领的所有任务(跨模块)
|
||||
→ 每条含:id / title / status / priority / progress / module_name / end_date / assignees
|
||||
|
||||
Step 2: 按状态分组展示:
|
||||
Step 2: 按状态分组展示(状态值与后端枚举一致):
|
||||
────────────────────────────────────
|
||||
📋 待处理(todo)
|
||||
· [前端开发] 完成登录页面 UI 优化 ← 截止: 04-15
|
||||
📋 未开始(not_started)
|
||||
· [前端开发] 完成登录页面 UI 优化 ← end_date: 04-15
|
||||
· [后端API] 接口文档更新 ← 无截止日
|
||||
|
||||
🔄 进行中(in_progress)
|
||||
· [前端开发] 接口联调 60% ← 截止: 04-20
|
||||
· [前端开发] 接口联调 60% ← end_date: 04-20
|
||||
|
||||
✅ 已完成(done)
|
||||
· [前端开发] 初始化项目结构 100%
|
||||
|
||||
⏸️ 已挂起(on_hold) / ❌ 已取消(cancelled)— 默认折叠
|
||||
────────────────────────────────────
|
||||
```
|
||||
|
||||
@@ -47,5 +52,5 @@ Step 2: 展示每人的任务负载情况(适合分配任务前参考)
|
||||
|------|------|
|
||||
| "我今天要做什么" | task_list_mine() → 过滤 status=in_progress + 截止日临近 |
|
||||
| "某个模块的任务" | task_list_by_module(module_id) |
|
||||
| "即将到期的任务" | task_list_mine() → 筛选 due_date ≤ 今日+3天 |
|
||||
| "即将到期的任务" | task_list_mine() → 筛选 end_date ≤ 今日+3天 |
|
||||
| "团队任务分布" | people_get_board() |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 周报草稿(+draft,仅限模块负责人)
|
||||
|
||||
> ⚠️ 参数细节以 MCP `weekly_report_save` 的 docstring 为准,本文档仅做工作流引导。
|
||||
|
||||
## 数据来源
|
||||
|
||||
周报草稿基于**本周负责人日报汇总**(`leader_report_get_batch` 返回值),而非员工个人日报。
|
||||
@@ -34,8 +36,8 @@ Step 4: 展示草稿给用户审阅修改
|
||||
Step 5: 用户确认后逐模块保存:
|
||||
mcp__huanxi__weekly_report_save(
|
||||
module_id = "<模块ID>",
|
||||
year = <ISO year>, ← 注意:ISO year,不是日历年
|
||||
week = <ISO week>,
|
||||
year = <ISO year>, ← 注意:ISO year,不是日历年
|
||||
week_number = <ISO week>, ← 后端字段名是 week_number,不是 week
|
||||
content = "<本周总结>",
|
||||
next_week_plan = "<下周计划>"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: memcore-shared
|
||||
description: "memcore 内部共享约定:路径锁定、PROJECT_DIR 解析、synthesis 阈值常量。本技能仅供 /memory-sync、/memory-update、/memory-lint 内部 Read 引用,**不要由用户直接调用**。"
|
||||
---
|
||||
|
||||
# memcore 共享约定
|
||||
|
||||
本文件是 `/memory-sync`、`/memory-update`、`/memory-lint` 三个技能的内部共享 include,**用户不会直接调用本技能**。三个主技能在 Phase 0 必须 Read 本文件载入约束。
|
||||
|
||||
---
|
||||
|
||||
## ⚠ 路径锁定(强制约束)
|
||||
|
||||
### 唯一允许写入的路径
|
||||
|
||||
```
|
||||
$PROJECT_DIR/.claude/memory/
|
||||
```
|
||||
|
||||
即「会话当前工作目录下的 `.claude/memory/`」。
|
||||
|
||||
### 严禁写入的路径
|
||||
|
||||
| 路径 | 原因 |
|
||||
|------|------|
|
||||
| `~/.claude/projects/*/memory/` | 系统 auto memory 路径,仅 `/memory-sync` 的 Phase 10 统一同步 |
|
||||
| `~/.claude/` 下任何其他目录 | 全局配置目录,禁止 memcore 触碰 |
|
||||
| `$PROJECT_DIR` 之外任何路径 | 跨项目污染 |
|
||||
|
||||
### 不触发 auto memory 系统
|
||||
|
||||
memcore 子技能产生的所有写入**严禁**进入 auto memory 系统(`~/.claude/projects/{PROJECT_KEY}/memory/`)。该路径仅由 `/memory-sync` 的 Phase 10 一次性推送。
|
||||
|
||||
### 执行前断言(每个子技能必须执行)
|
||||
|
||||
```bash
|
||||
TARGET="$PROJECT_DIR/.claude/memory"
|
||||
echo "目标路径:$TARGET"
|
||||
case "$TARGET" in *"/.claude/projects/"*)
|
||||
echo "ERROR: 路径含系统自动记忆目录,中止" && exit 1 ;;
|
||||
esac
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PROJECT_DIR 解析(跨平台统一)
|
||||
|
||||
`$PROJECT_DIR` 必须等于「shell 当前工作目录的 native 形式」:
|
||||
|
||||
```bash
|
||||
# Windows Git Bash / MSYS 优先取 -W(输出 C:/... 形式,便于 git -C 跨工具使用)
|
||||
PROJECT_DIR="$(pwd -W 2>/dev/null || pwd)"
|
||||
echo "PROJECT_DIR=$PROJECT_DIR"
|
||||
```
|
||||
|
||||
理由:
|
||||
- macOS / Linux:`pwd -W` 不存在,会 fallback 到 `pwd`,输出 `/Users/x/proj`
|
||||
- Windows Git Bash:`pwd` 输出 `/c/Projects/x`,但 `git -C`、`cp` 跨 native 工具时更稳定的形式是 `C:/Projects/x`,正是 `pwd -W` 的输出
|
||||
|
||||
子技能内所有 `git -C "$PROJECT_DIR"`、`cp -p`、`stat` 等命令统一使用此 `$PROJECT_DIR`。
|
||||
|
||||
---
|
||||
|
||||
## 全局常量
|
||||
|
||||
| 常量 | 值 | 含义 | 使用位置 |
|
||||
|------|----|------|---------|
|
||||
| `SYNTHESIS_THRESHOLD` | `3` | 跨文件引用数 ≥ 此值即为 synthesis 升级候选 | `/memory-update` Phase 3C、`/memory-lint` Phase 3A & Phase 8 |
|
||||
| `LINT_STALE_WARN_DAYS` | `30` | last_updated 超过此天数 → WARN | `/memory-lint` Phase 5 |
|
||||
| `LINT_STALE_ERROR_DAYS` | `90` | last_updated 超过此天数 → ERROR | `/memory-lint` Phase 5 |
|
||||
| `MULTI_HOST_WARN_DAYS` | `7` | 远程 vs 本地 mtime 差 ≥ 此天数 → 多机不同步警告 | `/memory-sync` Phase 3 |
|
||||
|
||||
子技能引用常量时使用上述名称,调整阈值只需修改本文件单一来源。
|
||||
|
||||
---
|
||||
|
||||
## REMOTE_MEMORY 路径推导
|
||||
|
||||
```bash
|
||||
PROJECT_KEY="$(echo "$PROJECT_DIR" | sed 's#[:\\/]#-#g')"
|
||||
REMOTE_MEMORY="$HOME/.claude/projects/$PROJECT_KEY/memory"
|
||||
```
|
||||
|
||||
例:`C:\Projects\yixiong-claude-marketplace` → `C--Projects-yixiong-claude-marketplace`。
|
||||
|
||||
**该路径只允许 `/memory-sync` 的 Phase 3(读)和 Phase 10(写)触碰**,其他子技能不允许直接读写。
|
||||
|
||||
---
|
||||
|
||||
## 引用约定
|
||||
|
||||
子技能开头标准引用句:
|
||||
|
||||
```markdown
|
||||
**前置约束:先 Read `../memcore-shared/SKILL.md`(路径锁定 + 常量 + PROJECT_DIR 解析)**
|
||||
```
|
||||
|
||||
读取后,子技能内所有出现的:
|
||||
- `$PROJECT_DIR` → 按本文件「PROJECT_DIR 解析」一节获取
|
||||
- `SYNTHESIS_THRESHOLD` 等常量 → 按本文件「全局常量」表
|
||||
- 路径断言 → 按本文件「执行前断言」执行
|
||||
@@ -5,29 +5,14 @@ description: 检查本地记忆文件的健康状况。AUTO-FIX类问题直接
|
||||
|
||||
# memory-lint
|
||||
|
||||
健康检查 `.claude/memory/`:AUTO-FIX 直修,NEED-HUMAN 写入 `lint_report.md`。会话目录 = `$PROJECT_DIR`。
|
||||
健康检查 `.claude/memory/`:AUTO-FIX 直修,NEED-HUMAN 写入 `lint_report.md`。
|
||||
|
||||
---
|
||||
**前置约束:先 Read `../memcore-shared/SKILL.md`**(路径锁定 + 常量 + PROJECT_DIR 解析),其约束在本技能全程生效。
|
||||
|
||||
## ⚠ 路径锁定(执行前必读)
|
||||
|
||||
**唯一操作路径**:`$PROJECT_DIR/.claude/memory/`(项目根目录内的 `.claude/memory/`)
|
||||
|
||||
**严禁读写的路径**:
|
||||
- `~/.claude/projects/*/memory/`(系统自动记忆路径,由 auto memory 系统单独管理)
|
||||
- `~/.claude/` 下任何其他目录
|
||||
- 项目目录(`$PROJECT_DIR`)以外的任何路径
|
||||
|
||||
**不触发 auto memory**:本技能执行期间产生的所有 lint 修正和报告,均**不写入** auto memory 系统(`~/.claude/projects/{PROJECT_KEY}/memory/`),该路径仅由 `/memory-sync` 的 Phase 10 统一管理。
|
||||
|
||||
**执行前断言**:
|
||||
```bash
|
||||
TARGET="$PROJECT_DIR/.claude/memory"
|
||||
echo "memory-lint 目标路径:$TARGET"
|
||||
case "$TARGET" in *"/.claude/projects/"*)
|
||||
echo "ERROR: 路径含系统自动记忆目录,中止" && exit 1 ;;
|
||||
esac
|
||||
```
|
||||
红线速记(详细见 memcore-shared):
|
||||
- **唯一读写路径**:`$PROJECT_DIR/.claude/memory/`
|
||||
- **严禁读写**:`~/.claude/projects/*/memory/`、`~/.claude/` 其他目录、项目外路径
|
||||
- **执行前断言**:必须运行 memcore-shared 中的路径断言脚本
|
||||
|
||||
目录不存在 → 输出 `⚠ 未找到 .claude/memory/,建议先执行 /memory-sync` 并终止。
|
||||
|
||||
@@ -49,9 +34,18 @@ ls "$PROJECT_DIR/.claude/memory/"*.md
|
||||
| Phase | 定义 | 级别 | AUTO-FIX |
|
||||
|-------|------|------|---------|
|
||||
| 1 孤儿 | 索引有 → 磁盘无 | ERROR | 从 MEMORY.md 删该条目 |
|
||||
| 2 幽灵 | 磁盘有 → 索引无(排除 MEMORY.md / lint_report.md / synonyms.md) | WARN | 补入索引(类型推断见下) |
|
||||
| 2 幽灵 | 磁盘有 → 索引无(仅排除 MEMORY.md / lint_report.md) | WARN | 补入索引(类型推断见下) |
|
||||
|
||||
幽灵类型推断:`user_*` → user / `project_*` 或 `decisions.md` → project / `feedback*` → feedback / `reference*` → reference / `synthesis_*` → synthesis / 其他默认 project。
|
||||
幽灵类型推断(按优先级匹配):
|
||||
- `synonyms.md`(精确匹配) → reference ← 新增:用户首次创建 synonyms.md 后会被自动登记,不再"隐形"
|
||||
- `user_*` → user
|
||||
- `project_*` 或 `decisions.md` → project
|
||||
- `feedback*` → feedback
|
||||
- `reference*` → reference
|
||||
- `synthesis_*` → synthesis
|
||||
- 其他默认 project
|
||||
|
||||
> **synonyms.md 自动登记说明**:用户在 `.claude/memory/` 中创建 `synonyms.md` 后,Phase 2 会自动将其登记入 MEMORY.md 索引(type=reference)。该文件由 Phase 4-pre 加载用于矛盾检测等价表。不要再把它从幽灵检测中排除。
|
||||
|
||||
---
|
||||
|
||||
@@ -152,7 +146,11 @@ cat "$PROJECT_DIR/pom.xml" || cat "$PROJECT_DIR/package.json" || cat "$PROJECT_D
|
||||
|
||||
### Phase 5 过期检测
|
||||
|
||||
阈值:WARN ≥30 天 / ERROR ≥90 天(可由 MEMORY.md 头部 `<!-- lint-stale-warn: N -->` 覆盖)。
|
||||
阈值由 memcore-shared 定义:
|
||||
- WARN ≥ `LINT_STALE_WARN_DAYS`(默认 30 天)
|
||||
- ERROR ≥ `LINT_STALE_ERROR_DAYS`(默认 90 天)
|
||||
|
||||
可由 MEMORY.md 头部 `<!-- lint-stale-warn: N -->` 局部覆盖。
|
||||
|
||||
```bash
|
||||
git -C "$PROJECT_DIR" log --oneline --since="$last_updated" -- .
|
||||
@@ -183,6 +181,58 @@ git -C "$PROJECT_DIR" log --oneline --since="$last_updated" -- .
|
||||
|
||||
## Phase 8 — 生成 lint_report.md
|
||||
|
||||
### Phase 8-pre — NEED-HUMAN 稳定 ID 与已 resolved 保活
|
||||
|
||||
**目的**:用户在 lint_report.md 中给某个 NEED-HUMAN 条目添加 `<!-- resolved -->` 标记后,下次 lint 不再重复列出该条目(即使问题尚未真正修复,用户已表达"不处理"意图)。
|
||||
|
||||
**ID 生成规则**:
|
||||
|
||||
```bash
|
||||
# 每个 NEED-HUMAN 条目计算稳定 ID(与执行时间无关,仅与"问题本体"有关)
|
||||
# 输入:phase 编号 + 目标文件 + 目标章节 + 问题关键事实
|
||||
# 输出:sha1 前 8 位
|
||||
gen_id() {
|
||||
printf '%s|%s|%s|%s' "$1" "$2" "$3" "$4" | sha1sum | cut -c1-8
|
||||
}
|
||||
|
||||
# 示例:
|
||||
# Phase 3A 断链:gen_id "3A" "decisions.md" "## 数据库选型" "[[synthesis_arch_xxx.md]]"
|
||||
# Phase 4 矛盾:gen_id "4" "decisions.md+project_overview.md" "数据库选型" "PostgreSQL vs MySQL"
|
||||
# Phase 5 过期:gen_id "5" "project_progress.md" "" "stale-86d"
|
||||
# Phase 6 污染:gen_id "6" "project_overview.md" "" "line-N"
|
||||
```
|
||||
|
||||
**已 resolved ID 提取**:
|
||||
|
||||
```bash
|
||||
RESOLVED_IDS=$(grep -B1 "<!-- resolved" "$PROJECT_DIR/.claude/memory/lint_report.md" 2>/dev/null \
|
||||
| grep -oE '<!-- id: [a-f0-9]{8}' | awk '{print $3}')
|
||||
```
|
||||
|
||||
**生成新 NEED-HUMAN 时的过滤**:
|
||||
|
||||
```
|
||||
对每个新检测出的 NEED-HUMAN 条目:
|
||||
id = gen_id(phase, file, section, fact)
|
||||
if id ∈ RESOLVED_IDS:
|
||||
skip(用户已标记 resolved,本次不再列出)
|
||||
else:
|
||||
写入 lint_report.md,并在条目末尾附 `<!-- id: {id} -->`
|
||||
```
|
||||
|
||||
**用户如何使用**:在 lint_report.md 中某个 NEED-HUMAN 条目末尾、`<!-- id: ... -->` 同段内,追加 `<!-- resolved -->`:
|
||||
|
||||
```markdown
|
||||
### [WARN] 内容矛盾 — PostgreSQL vs MySQL
|
||||
...
|
||||
<!-- id: a1b2c3d4 -->
|
||||
<!-- resolved: 2026-06-12, 决定保留两者作为历史对比 -->
|
||||
```
|
||||
|
||||
下次 lint 跑到时,发现 id=a1b2c3d4 在 RESOLVED_IDS 中 → 整条跳过,不再骚扰。
|
||||
|
||||
### 报告模板
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: 记忆健康检查报告
|
||||
@@ -194,15 +244,17 @@ last_updated: YYYY-MM-DD
|
||||
# 记忆健康检查报告
|
||||
|
||||
> _执行时间: YYYY-MM-DD | Base commit: `HASH` | Last synced: DATE_
|
||||
>
|
||||
> **如何使用**:NEED-HUMAN 条目末尾有 `<!-- id: xxxxxxxx -->` 标记。处理完或决定不处理时,在同段追加 `<!-- resolved: DATE, 简要原因 -->`,下次 lint 该条目自动跳过。
|
||||
|
||||
## 健康概览
|
||||
|
||||
| 检查项 | AUTO-FIX | NEED-HUMAN |
|
||||
| 检查项 | AUTO-FIX | NEED-HUMAN(含已 resolved 跳过 N 项) |
|
||||
|--------|---------|-----------|
|
||||
| 1 孤儿 / 2 幽灵 / 3A 引用 / 3B 双链 | N / N / N / N | — / — / N / N |
|
||||
| 4 矛盾 / 5 过期 / 6 污染 | — | N / N / N |
|
||||
|
||||
**AUTO-FIX 已执行 N 项 | NEED-HUMAN 待处理 N 项**
|
||||
**AUTO-FIX 已执行 N 项 | NEED-HUMAN 新列出 N 项 | 历史已 resolved 跳过 M 项**
|
||||
|
||||
---
|
||||
|
||||
@@ -210,6 +262,7 @@ last_updated: YYYY-MM-DD
|
||||
|
||||
- [x] 移除孤儿:`synthesis_xxx.md`
|
||||
- [x] 补入幽灵:`feedback_api.md`(feedback)
|
||||
- [x] 自动登记 synonyms:`synonyms.md`(reference)
|
||||
- [x] 更新断链:`[[feedback.md#API 认证规范]]` → `[[feedback.md#API 鉴权约束]]`
|
||||
- [x] MEMORY.md「引用」列已刷新(22 文件,倒序)
|
||||
|
||||
@@ -217,7 +270,7 @@ last_updated: YYYY-MM-DD
|
||||
|
||||
## 条目级高频引用 Top(供 /memory-update 消费)
|
||||
|
||||
跨 ≥3 个不同源文件被引用的 decisions/feedback 条目。无候选时保留标题 + "无候选"。
|
||||
跨 ≥`SYNTHESIS_THRESHOLD` 个不同源文件被引用的 decisions/feedback 条目(阈值见 memcore-shared,默认 3)。无候选时保留标题 + "无候选"。
|
||||
|
||||
| 条目 | 跨文件次数 | 建议 |
|
||||
|------|----------|------|
|
||||
@@ -238,6 +291,7 @@ last_updated: YYYY-MM-DD
|
||||
- Q2:git history 能否找到删除/重命名证据?
|
||||
- Q3:该引用是「锦上添花」还是「核心支撑」?
|
||||
- **矩阵**:Q1+Q2 = 是 → 恢复文件;Q1 是 + Q2 否 → 重新归档;Q1 否 → 删引用;Q3 核心 → 必须二选一不允许保留断链
|
||||
<!-- id: a1b2c3d4 -->
|
||||
|
||||
### [WARN] 内容矛盾 — 跨文件表述冲突
|
||||
|
||||
@@ -248,6 +302,7 @@ last_updated: YYYY-MM-DD
|
||||
- Q2:另一方是「计划未实施」还是「过时记录」?
|
||||
- Q3:近 30 天 git log 有迁移提交?
|
||||
- **矩阵**:Q1 答案 = 当前权威;Q2 过时 → 直接更新另一方;Q2 计划 → 末尾标 `**Status:** planned, target HASH`;Q3 有迁移 → 用迁移时间反推
|
||||
<!-- id: e5f6a7b8 -->
|
||||
|
||||
### [WARN] 过期记忆 — last_updated 超阈值
|
||||
|
||||
@@ -257,6 +312,7 @@ last_updated: YYYY-MM-DD
|
||||
- Q2:现有内容是否仍可指导决策?
|
||||
- Q3:是否有继任 synthesis_* 已分担其职责?
|
||||
- **矩阵**:Q1 是 + Q2 否 → 触发 `/memory-update`;Q2 是(仅日期老)→ 仅刷新 `last_updated`;Q3 是 → 归档/删除,索引指向继任者
|
||||
<!-- id: c9d0e1f2 -->
|
||||
|
||||
### [WARN] 可推断内容污染 — 疑似从代码可 grep 的明细
|
||||
|
||||
@@ -266,6 +322,7 @@ last_updated: YYYY-MM-DD
|
||||
- Q2:删除后剩余内容是否仍清晰描述「为什么/约束/边界」?
|
||||
- Q3:是否承载 git history 抓不到的语义?(如「曾选 A 后改 B 因 X」)
|
||||
- **矩阵**:Q1+Q2 = 是 + Q3 否 → 安全删除;Q3 是 → 改写为决策格式迁到 decisions.md(保留 Why);Q2 否 → 保留架构层级描述但删具体路径
|
||||
<!-- id: 3a4b5c6d -->
|
||||
```
|
||||
|
||||
---
|
||||
@@ -291,7 +348,8 @@ last_updated: YYYY-MM-DD
|
||||
## 执行约束
|
||||
|
||||
1. **AUTO-FIX 边界严格** — 只修结构性错误(孤儿、幽灵、断链、双链),不改业务内容
|
||||
2. **NEED-HUMAN 完整记录** — 每项含 checklist + 决策矩阵
|
||||
3. **矛盾检测先过等价表** — 先加载 `synonyms.md` 再判矛盾;措辞不一致 ≠ 矛盾,宁漏报不误报;项目可在 `.claude/memory/synonyms.md` 维护等价组降低误报率
|
||||
4. **污染检测边界**(重申)— 架构层级保留 / 具体类名路径删除
|
||||
5. **被调用静默返回** — `/memory-sync` 内 Phase 9 不输出收尾
|
||||
2. **NEED-HUMAN 完整记录** — 每项含 checklist + 决策矩阵 + 末尾 `<!-- id: xxxxxxxx -->` 稳定 ID
|
||||
3. **resolved 保活** — Phase 8-pre 提取旧 lint_report.md 中带 `<!-- resolved -->` 的 ID 集合,新报告中同 ID 条目跳过;用户标记 resolved 即长效免打扰
|
||||
4. **矛盾检测先过等价表** — 先加载 `synonyms.md` 再判矛盾;措辞不一致 ≠ 矛盾,宁漏报不误报;项目可在 `.claude/memory/synonyms.md` 维护等价组降低误报率(synonyms.md 由 Phase 2 自动登记入 MEMORY.md)
|
||||
5. **污染检测边界**(重申)— 架构层级保留 / 具体类名路径删除
|
||||
6. **被调用静默返回** — `/memory-sync` 内 Phase 9 不输出收尾
|
||||
|
||||
@@ -5,7 +5,9 @@ description: 项目记忆体系完整同步。Git检查→远程补充本地→
|
||||
|
||||
# memory-sync
|
||||
|
||||
记忆体系完整同步周期。**本地 `.claude/memory/` 是唯一权威**,远程为镜像。会话目录 = `$PROJECT_DIR`。
|
||||
记忆体系完整同步周期。**本地 `.claude/memory/` 是唯一权威**,远程为镜像。
|
||||
|
||||
**前置约束:先 Read `../memcore-shared/SKILL.md`**(路径锁定 + 常量定义 + PROJECT_DIR 解析 + REMOTE_MEMORY 推导),其约束在本技能全程生效。本技能的 Phase 3(读远程)与 Phase 10(写远程)是**全 memcore 中唯二**允许触碰 `$REMOTE_MEMORY` 的环节。
|
||||
|
||||
```
|
||||
Phase 0 Git 准备(冲突解决优先 → 普通变更提交)
|
||||
@@ -98,26 +100,28 @@ done
|
||||
|
||||
### 多机不同步检测
|
||||
|
||||
两边都存在的文件,对比 mtime:
|
||||
两边都存在的文件,对比 mtime。阈值:`MULTI_HOST_WARN_DAYS`(见 memcore-shared,默认 7)。
|
||||
|
||||
```bash
|
||||
MULTI_HOST_WARN_DAYS=7 # 与 memcore-shared 全局常量保持一致
|
||||
|
||||
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
||||
local="$PROJECT_DIR/.claude/memory/$(basename "$f")"
|
||||
[ ! -f "$local" ] && continue
|
||||
rm=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f")
|
||||
lm=$(stat -c %Y "$local" 2>/dev/null || stat -f %m "$local")
|
||||
diff_days=$(( (rm - lm) / 86400 ))
|
||||
[ $diff_days -ge 7 ] && echo "⚠ $(basename "$f") 远程比本地新 $diff_days 天"
|
||||
[ $diff_days -ge "$MULTI_HOST_WARN_DAYS" ] && echo "⚠ $(basename "$f") 远程比本地新 $diff_days 天"
|
||||
done
|
||||
```
|
||||
|
||||
≥1 个警告 → 提示 `检测到 N 个文件远程比本地新 ≥7 天,可能多机不同步。继续?(y/n)`。
|
||||
≥1 个警告 → 提示 `检测到 N 个文件远程比本地新 ≥MULTI_HOST_WARN_DAYS 天,可能多机不同步。继续?(y/n)`。
|
||||
- `n` → 终止整个 sync 流程
|
||||
- `y` → 继续(Phase 10 仍按本地权威覆盖远程)
|
||||
|
||||
### 并发分歧检测(mtime 差 < 7 天的冲突预警)
|
||||
### 并发分歧检测(mtime 差 < `MULTI_HOST_WARN_DAYS` 天的冲突预警)
|
||||
|
||||
对「两边都存在且 mtime 差 < 7 天」的文件,进一步做内容比对:
|
||||
对「两边都存在且 mtime 差 < `MULTI_HOST_WARN_DAYS`(默认 7)天」的文件,进一步做内容比对:
|
||||
|
||||
```bash
|
||||
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
||||
|
||||
@@ -5,41 +5,43 @@ description: 根据git diff增量范围,更新本地记忆文件和MEMORY.md
|
||||
|
||||
# memory-update
|
||||
|
||||
按 git diff 增量更新本地 `.claude/memory/`。会话目录 = `$PROJECT_DIR`;目录不存在则 `mkdir -p`。
|
||||
按 git diff 增量更新本地 `.claude/memory/`。
|
||||
|
||||
---
|
||||
**前置约束:先 Read `../memcore-shared/SKILL.md`**(路径锁定 + 常量 + PROJECT_DIR 解析),其约束在本技能全程生效。
|
||||
|
||||
## ⚠ 路径锁定(执行前必读)
|
||||
红线速记(详细见 memcore-shared):
|
||||
- **唯一写入路径**:`$PROJECT_DIR/.claude/memory/`
|
||||
- **严禁写入**:`~/.claude/projects/*/memory/`、`~/.claude/` 其他目录、项目外路径
|
||||
- **执行前断言**:必须运行 memcore-shared 中的路径断言脚本,确认目标路径不含 `/.claude/projects/`
|
||||
|
||||
**唯一操作路径**:`$PROJECT_DIR/.claude/memory/`(项目根目录内的 `.claude/memory/`)
|
||||
|
||||
**严禁写入的路径**:
|
||||
- `~/.claude/projects/*/memory/`(系统自动记忆路径,由 auto memory 系统单独管理)
|
||||
- `~/.claude/` 下任何其他目录
|
||||
- 项目目录(`$PROJECT_DIR`)以外的任何路径
|
||||
|
||||
**不触发 auto memory**:本技能执行期间产生的所有记忆内容,均**不写入** auto memory 系统(`~/.claude/projects/{PROJECT_KEY}/memory/`),该路径仅由 `/memory-sync` 的 Phase 10 统一管理。
|
||||
|
||||
**执行前断言**:
|
||||
```bash
|
||||
# 确认目标路径在项目目录内
|
||||
TARGET="$PROJECT_DIR/.claude/memory"
|
||||
echo "memory-update 目标路径:$TARGET"
|
||||
# 路径含 .claude/projects 则中止
|
||||
case "$TARGET" in *"/.claude/projects/"*)
|
||||
echo "ERROR: 路径含系统自动记忆目录,中止" && exit 1 ;;
|
||||
esac
|
||||
```
|
||||
目录不存在则 `mkdir -p`。
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — 读取增量锚点
|
||||
|
||||
```bash
|
||||
# MEMORY.md 头部 _Last synced: DATE | Base commit: `HASH`_ → $ANCHOR_COMMIT(无则空=全量)
|
||||
# 主锚点:MEMORY.md 头部 _Last synced: DATE | Base commit: `HASH`_ → $ANCHOR_COMMIT
|
||||
ANCHOR_COMMIT=$(grep -oE 'Base commit: `[^`]+`' "$PROJECT_DIR/.claude/memory/MEMORY.md" 2>/dev/null \
|
||||
| head -1 | sed 's/Base commit: `//; s/`$//')
|
||||
|
||||
# 兜底锚点:若 MEMORY.md 头部锚点丢失,取各文件 frontmatter commit 字段的最旧值
|
||||
# 防止"误删 MEMORY.md 头部 → 雪崩全量重写"
|
||||
if [ -z "$ANCHOR_COMMIT" ] || [ "$ANCHOR_COMMIT" = "N/A" ]; then
|
||||
FALLBACK=$(grep -h "^commit:" "$PROJECT_DIR/.claude/memory/"*.md 2>/dev/null \
|
||||
| awk '{print $2}' | sort -u)
|
||||
if [ -n "$FALLBACK" ]; then
|
||||
# 取所有 commit 中按 git 拓扑序最旧的(保守锚点,确保覆盖所有改动)
|
||||
ANCHOR_COMMIT=$(git -C "$PROJECT_DIR" rev-list --topo-order $FALLBACK 2>/dev/null | tail -1)
|
||||
echo "⚠ MEMORY.md 头部锚点丢失,使用兜底锚点:$ANCHOR_COMMIT(来自各文件 frontmatter 最旧 commit)"
|
||||
fi
|
||||
fi
|
||||
|
||||
git -C "$PROJECT_DIR" rev-parse --short HEAD # → $HEAD_HASH(非 git 仓库填 N/A)
|
||||
```
|
||||
|
||||
**为什么需要兜底**:MEMORY.md 头部的 `Base commit: HASH` 是单一来源,一旦用户手动编辑误删此行,整个 diff 范围退化为全量 → 触发 update 重写所有文件。兜底机制从各文件 frontmatter 的 `commit:` 字段取**最旧值**,确保覆盖所有真实改动而不退化为无差别全量。
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — 计算变更范围
|
||||
@@ -130,21 +132,35 @@ commit: HASH
|
||||
|
||||
每次执行 Phase 3 末尾**强制运行**。目的:在短会话或任务型对话中,不依赖 lint 的延迟触发,直接检测 synthesis 升级候选。
|
||||
|
||||
阈值:`SYNTHESIS_THRESHOLD`(见 memcore-shared,当前 = 3)。
|
||||
|
||||
```bash
|
||||
# 阈值从 memcore-shared 读取
|
||||
SYNTHESIS_THRESHOLD=3 # 与 memcore-shared 全局常量保持一致
|
||||
|
||||
# 对 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" \
|
||||
# 使用 printf %q 转义 title 中的特殊字符(空格 / 中文标点 / 引号等)
|
||||
# 同时去除 grep 模式中的方括号歧义([[..]] 是字面量)
|
||||
pat=$(printf '%s' "[[${fn}#${title}]]" | sed 's/[][\\.*^$/]/\\&/g')
|
||||
count=$(grep -rlF -- "[[${fn}#${title}]]" \
|
||||
"$PROJECT_DIR/.claude/memory/" --include="*.md" 2>/dev/null \
|
||||
| grep -v "^${entry_file}$" | wc -l)
|
||||
[ "$count" -ge 3 ] && echo "$count|$fn#$title"
|
||||
[ "$count" -ge "$SYNTHESIS_THRESHOLD" ] && echo "$count|$fn#$title"
|
||||
done < <(grep "^## " "$entry_file" | sed 's/^## //')
|
||||
done | sort -t'|' -k1 -rn
|
||||
```
|
||||
|
||||
**脚本健壮性说明**:
|
||||
- 使用 `grep -F`(fixed string)避免 `[[` `]]` 在正则中的歧义
|
||||
- title 含中文 / 空格 / 标点时不会破坏匹配
|
||||
- `--` 防止 title 以 `-` 开头被误解为 grep 选项
|
||||
- 单文件中同标题多次引用按 `-l` 仅记一次(按文件去重)
|
||||
|
||||
对每条输出候选(`count|file#title`):
|
||||
1. 读原条目内是否含 `**Synthesized:**` → 已升级,跳过
|
||||
2. 读原条目内是否含 `<!-- synthesis-decline: YYYY-MM-DD -->` → 30 天内,跳过
|
||||
@@ -154,6 +170,7 @@ done | sort -t'|' -k1 -rn
|
||||
- Phase 3C(快扫):每次 memory-update 必跑,判据为「存在引用行数」,适合即时触发
|
||||
- lint Phase 3A(精扫):按源文件去重的精确计数,月度健康检查时运行
|
||||
- 两者以 `**Synthesized:**` 标记为唯一判重依据,不重复创建文件
|
||||
- 阈值唯一来源为 memcore-shared 的 `SYNTHESIS_THRESHOLD`,调整请改 memcore-shared
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user