feat(huanxi+memcore): 全量修正 huanxi 技能描述漂移 + memcore 七项优化
- huanxi: 更新 MCP URL 至 huanxi.office.yixiong-tech.com - huanxi: 修正所有技能与后端 docstring 漂移 · report items 字段表(补 module_id 必填、progress→progress_update、去除虚构 status) · weekly_report_save week→week_number · task end_date(非 due_date)、critical(非 urgent)、not_started(非 todo) · 用户/模块 ID 字段名统一为 id(非 user_id) · 所有 references 顶部声明"参数细节以 MCP docstring 为准" - memcore: 新增 memcore-shared 共享层(路径锁定 + 全局常量 + PROJECT_DIR 跨平台解析) - memcore: lint_report 增量保活(NEED-HUMAN 稳定 ID + resolved 跳过) - memcore: synonyms.md 自动登记入索引 - memcore: SYNTHESIS_THRESHOLD / LINT_STALE_*_DAYS / MULTI_HOST_WARN_DAYS 常量化 - memcore: update Phase 1 增加 Base commit 兜底,防锚点丢失雪崩 - memcore: Phase 3C 引用快扫脚本改用 grep -F + -- 兼容中文/空格 title Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4bf58796cf
commit
38beecb2d0
@@ -77,17 +77,25 @@ description: 一句话说明该技能的用途(Claude 用此判断何时触发
|
|||||||
| 插件 | 技能 | 说明 |
|
| 插件 | 技能 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| `huanxi` | `/huanxi-shared` `/huanxi-report` `/huanxi-leader` `/huanxi-task` `/huanxi-weekly` `/huanxi-org` | 寰汐企业管理系统完整工作流,含 MCP Server 自动配置 |
|
| `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 个技能) |
|
| `obsidian` | `/obsidian` `/obsidian-bases` `/obsidian-daily` `/obsidian-history` `/obsidian-meta` `/obsidian-plugins` `/obsidian-search` `/obsidian-tasks` `/obsidian-workflow-pkm` | Obsidian 知识库完整工作流(9 个技能) |
|
||||||
|
|
||||||
### memcore 技能调用关系
|
### memcore 技能调用关系
|
||||||
|
|
||||||
```
|
```
|
||||||
|
/memcore-shared ← 内部 include(路径锁定 + 全局常量 + PROJECT_DIR 解析),不由用户直接调用
|
||||||
|
↑ Read 引用
|
||||||
|
│
|
||||||
/memory-sync ← 总编排(11 phases),调用下面两个技能
|
/memory-sync ← 总编排(11 phases),调用下面两个技能
|
||||||
├── /memory-update ← 增量写入,可独立执行
|
├── /memory-update ← 增量写入,可独立执行
|
||||||
└── /memory-lint ← 健康校验,可独立执行
|
└── /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` 索引再按需加载文件。代码与记忆冲突 → 以代码为准并更新记忆。
|
> 每次新会话或长会话压缩后,必须先读 `MEMORY.md` 索引再按需加载文件。代码与记忆冲突 → 以代码为准并更新记忆。
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"huanxi": {
|
"huanxi": {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"url": "https://huanxi.yixiong-tech.com:18085/mcp/",
|
"url": "https://huanxi.office.yixiong-tech.com/mcp/",
|
||||||
"headers": {
|
"headers": {
|
||||||
"Authorization": "Bearer ${user_config.token}"
|
"Authorization": "Bearer ${user_config.token}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# 负责人日报草稿(+draft)
|
# 负责人日报草稿(+draft)
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `leader_report_save` / `llm_generate_leader_summary` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
## 两种草稿模式
|
## 两种草稿模式
|
||||||
|
|
||||||
### 模式 A:AI 自动生成
|
### 模式 A:AI 自动生成
|
||||||
@@ -29,13 +31,22 @@
|
|||||||
```
|
```
|
||||||
mcp__huanxi__leader_report_save(
|
mcp__huanxi__leader_report_save(
|
||||||
report_date = "YYYY-MM-DD", ← 日期格式
|
report_date = "YYYY-MM-DD", ← 日期格式
|
||||||
module_id = "<模块ID>", ← 从 modules.json 缓存取
|
scope_type = "module", ← 默认 "module";组织维度填 "org"
|
||||||
content = "<正文内容>" ← 支持 Markdown
|
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,告知用户已保存,询问是否立即提交。
|
**返回值**:保存成功后返回草稿 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",
|
"cached_at": "2026-04-13T09:00:00+08:00",
|
||||||
"data": {
|
"data": {
|
||||||
"user_id": "123",
|
"id": "123",
|
||||||
"name": "张三",
|
"name": "张三",
|
||||||
"feishu_user_id": "ou_xxx"
|
"feishu_user_id": "ou_xxx"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> ⚠️ 用户身份的系统内部 ID 字段名是 `id`(与后端 `user_get_me` / `user_list` 返回结构一致),不是 `user_id`。
|
||||||
|
|
||||||
**modules.json:**
|
**modules.json:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -127,7 +129,7 @@ Step 3: 告知用户:缓存已刷新(模块 N 个,用户 M 人)
|
|||||||
{
|
{
|
||||||
"cached_at": "2026-04-13T09:00:00+08:00",
|
"cached_at": "2026-04-13T09:00:00+08:00",
|
||||||
"data": [
|
"data": [
|
||||||
{ "user_id": "456", "name": "李四", "feishu_user_id": "ou_yyy" }
|
{ "id": "456", "name": "李四", "feishu_user_id": "ou_yyy" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
# 名字 → ID 解析
|
# 名字 → ID 解析
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `module_list` / `user_list` / `user_get_me` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
本文件详细说明如何将模块名、人员名解析为系统 ID,所有步骤均**缓存优先**。
|
本文件详细说明如何将模块名、人员名解析为系统 ID,所有步骤均**缓存优先**。
|
||||||
|
|
||||||
|
**字段名约定**:用户/模块的系统内部 ID 字段名统一为 `id`(与后端返回结构一致),不要写成 `user_id`/`module_id` 作为 JSON 字段名。`module_id`/`user_id` 仅在传入 MCP 工具参数时使用。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 模块名 → 模块 ID {#modules}
|
## 模块名 → 模块 ID {#modules}
|
||||||
@@ -33,7 +37,7 @@
|
|||||||
→ 检查 cached_at,若 age < 24h → 在 data 数组中查找
|
→ 检查 cached_at,若 age < 24h → 在 data 数组中查找
|
||||||
|
|
||||||
2. 查找逻辑:
|
2. 查找逻辑:
|
||||||
a. name 精确匹配 → 返回 user_id
|
a. name 精确匹配 → 返回 user.id
|
||||||
b. name 包含输入 → 列出候选
|
b. name 包含输入 → 列出候选
|
||||||
c. 未找到 → 执行 Step 3
|
c. 未找到 → 执行 Step 3
|
||||||
|
|
||||||
@@ -46,8 +50,8 @@
|
|||||||
```
|
```
|
||||||
|
|
||||||
**特别注意:**
|
**特别注意:**
|
||||||
- `user_id`(系统内部 ID)≠ `feishu_user_id`(飞书 open_id)
|
- 用户的系统内部 ID 字段名是 `id`(后端 `user_list` 返回结构),`≠ feishu_user_id`(飞书 open_id)
|
||||||
- 设置任务执行人用 `user_id`
|
- 设置任务执行人时,MCP 工具的参数名叫 `assignee_ids`,传入的值就是 user.id 列表
|
||||||
- 飞书消息通知用 `feishu_user_id`(MCP 内部会自动处理,无需手动区分)
|
- 飞书消息通知用 `feishu_user_id`(MCP 内部会自动处理,无需手动区分)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -58,7 +62,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
1. 解析模块 → read modules.json → 匹配"前端开发" → mod_001
|
1. 解析模块 → read modules.json → 匹配"前端开发" → mod_001
|
||||||
2. 解析人员 → read users.json → 匹配"李四" → user_id: 456
|
2. 解析人员 → read users.json → 匹配"李四" → id: 456
|
||||||
3. 若任一缓存未命中:先拉 MCP,写缓存,再继续
|
3. 若任一缓存未命中:先拉 MCP,写缓存,再继续
|
||||||
4. 两个 ID 都拿到后 → 调用 task_create(module_id="mod_001", ...)
|
4. 两个 ID 都拿到后 → 调用 task_create(module_id="mod_001", ...)
|
||||||
5. 创建完成后 → task_set_assignees(task_id, ["456"])
|
5. 创建完成后 → task_set_assignees(task_id, ["456"])
|
||||||
|
|||||||
@@ -28,12 +28,14 @@ Step 2: 查看今日日报状态
|
|||||||
|
|
||||||
Step 3: 获取待汇报任务并收集内容
|
Step 3: 获取待汇报任务并收集内容
|
||||||
→ mcp__huanxi__report_get_tasks_to_report()
|
→ mcp__huanxi__report_get_tasks_to_report()
|
||||||
→ 展示待汇报任务列表(task_id, name, 模块, 当前进度)
|
→ 返回的每个任务条目含:id(task_id)、title、module_id、module_name、progress 等
|
||||||
|
→ 展示待汇报任务列表(任务名、模块、当前进度)
|
||||||
→ 引导用户逐一填写今日进展和完成百分比
|
→ 引导用户逐一填写今日进展和完成百分比
|
||||||
→ 详见 references/report-draft.md
|
→ 详见 references/report-draft.md
|
||||||
|
|
||||||
Step 4: 保存草稿并展示初稿
|
Step 4: 保存草稿并展示初稿
|
||||||
→ mcp__huanxi__report_save_draft(items=[...])
|
→ mcp__huanxi__report_save_draft(items=[...])
|
||||||
|
→ ⚠️ items 字段以 MCP docstring 为准;每条必须带 module_id(取自 Step 3 任务条目)
|
||||||
→ 展示完整初稿内容供用户预览
|
→ 展示完整初稿内容供用户预览
|
||||||
|
|
||||||
Step 5: 询问是否 AI 润色
|
Step 5: 询问是否 AI 润色
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
# 保存日报草稿(+draft)
|
# 保存日报草稿(+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`) |
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
⚠️ **历史踩坑**:曾用错的字段名 `progress`、`status`,以及遗漏 `module_id`,会触发"参数缺失"错误。
|
||||||
|------|------|------|
|
|
||||||
| `task_id` | string | 任务 ID(从待报任务中取) |
|
|
||||||
| `content` | string | 汇报内容(今日进展) |
|
|
||||||
| `progress` | int | 任务进度(0-100,整数) |
|
|
||||||
| `status` | string | 可选,不改变则不传 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -33,12 +35,18 @@ Step 1: 展示待汇报任务列表,引导用户逐一填写内容
|
|||||||
└─────────────────────────────────────────
|
└─────────────────────────────────────────
|
||||||
|
|
||||||
Step 2: 收集所有填写内容,构建 items 数组
|
Step 2: 收集所有填写内容,构建 items 数组
|
||||||
|
⚠️ 每个 item 必须含 module_id(来自 Step 0 的任务条目)
|
||||||
|
|
||||||
Step 3: [可选] 若用户请求 AI 辅助 → mcp__huanxi__llm_polish_report(content)
|
Step 3: [可选] 若用户请求 AI 辅助 → mcp__huanxi__llm_polish_report(content)
|
||||||
将润色建议展示给用户,由用户确认采用哪个版本
|
将润色建议展示给用户,由用户确认采用哪个版本
|
||||||
|
|
||||||
Step 4: mcp__huanxi__report_save_draft(items=[
|
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(今天不汇报)还是暂时跳过
|
- 用户未填写 `content` 的任务:询问是否 dismiss(今天不汇报)还是暂时跳过
|
||||||
- `report_save_draft` 是 upsert 操作,多次调用不会重复创建
|
- `report_save_draft` 是 upsert 操作,多次调用不会重复创建
|
||||||
- 草稿保存成功后,下次调用 `report_get_today()` 可看到 draft 状态
|
- 草稿保存成功后,下次调用 `report_get_today()` 可看到 draft 状态
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# 提交日报(+submit)
|
# 提交日报(+submit)
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `report_submit_item` / `report_get_today` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
## 前置条件
|
## 前置条件
|
||||||
|
|
||||||
- 草稿已通过 `report_save_draft()` 保存
|
- 草稿已通过 `report_save_draft()` 保存
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ description: "寰汐 MCP 共享基础:本地缓存策略(me/modules/users/wo
|
|||||||
|
|
||||||
| 文件 | 内容 | TTL | 刷新方式 |
|
| 文件 | 内容 | 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` |
|
| `modules.json` | 我参与的模块列表(id, name, my_role) | 24h | 过期自动重拉 或 `/huanxi-org +sync` |
|
||||||
| `users.json` | 组织用户搜索结果(name/feishu_user_id 索引) | 24h | 过期自动重拉 或 `/huanxi-org +sync` |
|
| `users.json` | 组织用户搜索结果(name/feishu_user_id 索引) | 24h | 过期自动重拉 或 `/huanxi-org +sync` |
|
||||||
| `workdays.json` | 工作日查询结果(date → bool 的 KV 字典) | 永久(按日期 key) | 已有日期不重新查 |
|
| `workdays.json` | 工作日查询结果(date → bool 的 KV 字典) | 永久(按日期 key) | 已有日期不重新查 |
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ description: "寰汐任务管理:创建任务(+create)、更新任务状
|
|||||||
|
|
||||||
## +update:更新任务
|
## +update:更新任务
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `task_update` 的 docstring 为准,本节仅做工作流引导。
|
||||||
|
|
||||||
```
|
```
|
||||||
Step 1: 确认任务 ID
|
Step 1: 确认任务 ID
|
||||||
→ 若用户已提供 task_id:直接使用
|
→ 若用户已提供 task_id:直接使用
|
||||||
@@ -48,17 +50,24 @@ Step 1: 确认任务 ID
|
|||||||
Step 2: 展示当前任务状态,引导用户填写要修改的字段
|
Step 2: 展示当前任务状态,引导用户填写要修改的字段
|
||||||
|
|
||||||
Step 3: mcp__huanxi__task_update(task_id, {
|
Step 3: mcp__huanxi__task_update(task_id, {
|
||||||
title? : "新标题",
|
title? : "新标题",
|
||||||
description? : "新描述",
|
description? : "新描述",
|
||||||
progress? : 80, ← 0-100 整数
|
progress? : 80, ← 0-100 整数
|
||||||
status? : "in_progress" | "done" | "todo",
|
progress_before? : 60, ← 修改 progress 时必传当前值(乐观锁,防并发覆盖)
|
||||||
due_date? : "YYYY-MM-DD",
|
status? : "not_started" | "in_progress" | "done" | "cancelled" | "on_hold",
|
||||||
priority? : "low" | "medium" | "high"
|
end_date? : "YYYY-MM-DD", ← 字段名是 end_date,不是 due_date
|
||||||
|
priority? : "low" | "medium" | "high" | "critical"
|
||||||
})
|
})
|
||||||
|
|
||||||
Step 4: 告知更新结果
|
Step 4: 告知更新结果
|
||||||
```
|
```
|
||||||
|
|
||||||
|
⚠️ **历史踩坑**:
|
||||||
|
- 字段名 `due_date` 错误,后端为 `end_date`
|
||||||
|
- 状态值 `todo` 错误,后端为 `not_started`
|
||||||
|
- priority 缺 `critical`,没有 `urgent`
|
||||||
|
- 改 progress 不传 `progress_before` 会 409 冲突
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## +assign:设置执行人
|
## +assign:设置执行人
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
# 创建任务(+create)
|
# 创建任务(+create)
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `task_create` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
## 必填信息收集
|
## 必填信息收集
|
||||||
|
|
||||||
在调用 `task_create` 前,引导用户提供:
|
在调用 `task_create` 前,引导用户提供:
|
||||||
|
|
||||||
| 字段 | 必填 | 说明 |
|
| 字段 | 必填 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| `module_id` | ✅ | 所属模块(从缓存解析名字 → ID) |
|
| `module_id` | ✅ | 所属模块 UUID(从缓存解析名字 → ID) |
|
||||||
| `title` | ✅ | 任务标题(简洁明了)|
|
| `title` | ✅ | 任务标题(简洁明了)|
|
||||||
| `description` | 可选 | 任务详情、背景、验收标准 |
|
| `description` | 可选 | 任务详情、背景、验收标准(Markdown) |
|
||||||
| `due_date` | 可选 | 截止日期(YYYY-MM-DD 格式)|
|
| `end_date` | 可选 | 截止日期(YYYY-MM-DD 格式,**字段名是 end_date,不是 due_date**) |
|
||||||
| `priority` | 可选 | `low` / `medium` / `high` / `urgent`,默认 medium |
|
| `priority` | 可选 | `low` / `medium` / `high` / `critical`,默认 `medium`(**没有 urgent**) |
|
||||||
| `assignee_ids` | 可选 | 执行人(从缓存解析人名 → user_id)|
|
| `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
|
→ Read ~/.claude/huanxi-cache/modules.json
|
||||||
→ 模糊匹配模块名(详见 huanxi-org resolve-ids.md)
|
→ 模糊匹配模块名(详见 huanxi-org resolve-ids.md)
|
||||||
|
|
||||||
Step 2: [若用户提到执行人] 解析人名 → user_id
|
Step 2: [若用户提到执行人] 解析人名 → user_id(user 对象的 id 字段)
|
||||||
→ Read ~/.claude/huanxi-cache/users.json
|
→ Read ~/.claude/huanxi-cache/users.json
|
||||||
→ 未命中 → mcp__huanxi__user_list(name=<人名>) → 追加写缓存
|
→ 未命中 → mcp__huanxi__user_list(name=<人名>) → 追加写缓存
|
||||||
|
|
||||||
Step 3: 创建任务
|
Step 3: 创建任务(推荐一次性把执行人也带上)
|
||||||
→ mcp__huanxi__task_create(
|
→ mcp__huanxi__task_create(
|
||||||
module_id = "<模块ID>",
|
module_id = "<模块ID>",
|
||||||
title = "任务标题",
|
title = "任务标题",
|
||||||
description = "...", ← 可选
|
description = "...", ← 可选
|
||||||
due_date = "YYYY-MM-DD", ← 可选
|
end_date = "YYYY-MM-DD", ← 可选;字段名 end_date
|
||||||
priority = "medium" ← 可选
|
priority = "medium", ← 可选;low/medium/high/critical
|
||||||
|
status = "not_started", ← 可选;默认 not_started
|
||||||
|
assignee_ids = ["<user_id>"] ← 可选;若 Step 2 有解析到,建议一并传入
|
||||||
)
|
)
|
||||||
→ 返回:task_id
|
→ 返回:task_id
|
||||||
|
|
||||||
Step 4: 设置执行人(若 Step 2 有解析到)
|
Step 4: [仅当 Step 3 未传 assignee_ids 时] 单独设置执行人
|
||||||
→ mcp__huanxi__task_set_assignees(
|
→ mcp__huanxi__task_set_assignees(
|
||||||
task_id = "<刚创建的 task_id>",
|
task_id = "<刚创建的 task_id>",
|
||||||
assignee_ids = ["<user_id>"]
|
assignee_ids = ["<user_id>"]
|
||||||
@@ -67,3 +73,14 @@ mcp__huanxi__task_create(
|
|||||||
parent_task_id = "<父任务ID>" ← 传此字段即为子任务
|
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)
|
# 任务看板(+board)
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `task_list_mine` / `task_list_by_module` / `people_get_board` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
## 查看我的任务
|
## 查看我的任务
|
||||||
|
|
||||||
```
|
```
|
||||||
Step 1: mcp__huanxi__task_list_mine()
|
Step 1: mcp__huanxi__task_list_mine()
|
||||||
→ 返回我认领的所有任务(跨模块)
|
→ 返回我认领的所有任务(跨模块)
|
||||||
|
→ 每条含:id / title / status / priority / progress / module_name / end_date / assignees
|
||||||
|
|
||||||
Step 2: 按状态分组展示:
|
Step 2: 按状态分组展示(状态值与后端枚举一致):
|
||||||
────────────────────────────────────
|
────────────────────────────────────
|
||||||
📋 待处理(todo)
|
📋 未开始(not_started)
|
||||||
· [前端开发] 完成登录页面 UI 优化 ← 截止: 04-15
|
· [前端开发] 完成登录页面 UI 优化 ← end_date: 04-15
|
||||||
· [后端API] 接口文档更新 ← 无截止日
|
· [后端API] 接口文档更新 ← 无截止日
|
||||||
|
|
||||||
🔄 进行中(in_progress)
|
🔄 进行中(in_progress)
|
||||||
· [前端开发] 接口联调 60% ← 截止: 04-20
|
· [前端开发] 接口联调 60% ← end_date: 04-20
|
||||||
|
|
||||||
✅ 已完成(done)
|
✅ 已完成(done)
|
||||||
· [前端开发] 初始化项目结构 100%
|
· [前端开发] 初始化项目结构 100%
|
||||||
|
|
||||||
|
⏸️ 已挂起(on_hold) / ❌ 已取消(cancelled)— 默认折叠
|
||||||
────────────────────────────────────
|
────────────────────────────────────
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -47,5 +52,5 @@ Step 2: 展示每人的任务负载情况(适合分配任务前参考)
|
|||||||
|------|------|
|
|------|------|
|
||||||
| "我今天要做什么" | task_list_mine() → 过滤 status=in_progress + 截止日临近 |
|
| "我今天要做什么" | task_list_mine() → 过滤 status=in_progress + 截止日临近 |
|
||||||
| "某个模块的任务" | task_list_by_module(module_id) |
|
| "某个模块的任务" | task_list_by_module(module_id) |
|
||||||
| "即将到期的任务" | task_list_mine() → 筛选 due_date ≤ 今日+3天 |
|
| "即将到期的任务" | task_list_mine() → 筛选 end_date ≤ 今日+3天 |
|
||||||
| "团队任务分布" | people_get_board() |
|
| "团队任务分布" | people_get_board() |
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# 周报草稿(+draft,仅限模块负责人)
|
# 周报草稿(+draft,仅限模块负责人)
|
||||||
|
|
||||||
|
> ⚠️ 参数细节以 MCP `weekly_report_save` 的 docstring 为准,本文档仅做工作流引导。
|
||||||
|
|
||||||
## 数据来源
|
## 数据来源
|
||||||
|
|
||||||
周报草稿基于**本周负责人日报汇总**(`leader_report_get_batch` 返回值),而非员工个人日报。
|
周报草稿基于**本周负责人日报汇总**(`leader_report_get_batch` 返回值),而非员工个人日报。
|
||||||
@@ -34,8 +36,8 @@ Step 4: 展示草稿给用户审阅修改
|
|||||||
Step 5: 用户确认后逐模块保存:
|
Step 5: 用户确认后逐模块保存:
|
||||||
mcp__huanxi__weekly_report_save(
|
mcp__huanxi__weekly_report_save(
|
||||||
module_id = "<模块ID>",
|
module_id = "<模块ID>",
|
||||||
year = <ISO year>, ← 注意:ISO year,不是日历年
|
year = <ISO year>, ← 注意:ISO year,不是日历年
|
||||||
week = <ISO week>,
|
week_number = <ISO week>, ← 后端字段名是 week_number,不是 week
|
||||||
content = "<本周总结>",
|
content = "<本周总结>",
|
||||||
next_week_plan = "<下周计划>"
|
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
|
# 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 解析),其约束在本技能全程生效。
|
||||||
|
|
||||||
## ⚠ 路径锁定(执行前必读)
|
红线速记(详细见 memcore-shared):
|
||||||
|
- **唯一读写路径**:`$PROJECT_DIR/.claude/memory/`
|
||||||
**唯一操作路径**:`$PROJECT_DIR/.claude/memory/`(项目根目录内的 `.claude/memory/`)
|
- **严禁读写**:`~/.claude/projects/*/memory/`、`~/.claude/` 其他目录、项目外路径
|
||||||
|
- **执行前断言**:必须运行 memcore-shared 中的路径断言脚本
|
||||||
**严禁读写的路径**:
|
|
||||||
- `~/.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
|
|
||||||
```
|
|
||||||
|
|
||||||
目录不存在 → 输出 `⚠ 未找到 .claude/memory/,建议先执行 /memory-sync` 并终止。
|
目录不存在 → 输出 `⚠ 未找到 .claude/memory/,建议先执行 /memory-sync` 并终止。
|
||||||
|
|
||||||
@@ -49,9 +34,18 @@ ls "$PROJECT_DIR/.claude/memory/"*.md
|
|||||||
| Phase | 定义 | 级别 | AUTO-FIX |
|
| Phase | 定义 | 级别 | AUTO-FIX |
|
||||||
|-------|------|------|---------|
|
|-------|------|------|---------|
|
||||||
| 1 孤儿 | 索引有 → 磁盘无 | ERROR | 从 MEMORY.md 删该条目 |
|
| 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 过期检测
|
### 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
|
```bash
|
||||||
git -C "$PROJECT_DIR" log --oneline --since="$last_updated" -- .
|
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 — 生成 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
|
```markdown
|
||||||
---
|
---
|
||||||
name: 记忆健康检查报告
|
name: 记忆健康检查报告
|
||||||
@@ -194,15 +244,17 @@ last_updated: YYYY-MM-DD
|
|||||||
# 记忆健康检查报告
|
# 记忆健康检查报告
|
||||||
|
|
||||||
> _执行时间: YYYY-MM-DD | Base commit: `HASH` | Last synced: DATE_
|
> _执行时间: 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 |
|
| 1 孤儿 / 2 幽灵 / 3A 引用 / 3B 双链 | N / N / N / N | — / — / N / N |
|
||||||
| 4 矛盾 / 5 过期 / 6 污染 | — | 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] 移除孤儿:`synthesis_xxx.md`
|
||||||
- [x] 补入幽灵:`feedback_api.md`(feedback)
|
- [x] 补入幽灵:`feedback_api.md`(feedback)
|
||||||
|
- [x] 自动登记 synonyms:`synonyms.md`(reference)
|
||||||
- [x] 更新断链:`[[feedback.md#API 认证规范]]` → `[[feedback.md#API 鉴权约束]]`
|
- [x] 更新断链:`[[feedback.md#API 认证规范]]` → `[[feedback.md#API 鉴权约束]]`
|
||||||
- [x] MEMORY.md「引用」列已刷新(22 文件,倒序)
|
- [x] MEMORY.md「引用」列已刷新(22 文件,倒序)
|
||||||
|
|
||||||
@@ -217,7 +270,7 @@ last_updated: YYYY-MM-DD
|
|||||||
|
|
||||||
## 条目级高频引用 Top(供 /memory-update 消费)
|
## 条目级高频引用 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 能否找到删除/重命名证据?
|
- Q2:git history 能否找到删除/重命名证据?
|
||||||
- Q3:该引用是「锦上添花」还是「核心支撑」?
|
- Q3:该引用是「锦上添花」还是「核心支撑」?
|
||||||
- **矩阵**:Q1+Q2 = 是 → 恢复文件;Q1 是 + Q2 否 → 重新归档;Q1 否 → 删引用;Q3 核心 → 必须二选一不允许保留断链
|
- **矩阵**:Q1+Q2 = 是 → 恢复文件;Q1 是 + Q2 否 → 重新归档;Q1 否 → 删引用;Q3 核心 → 必须二选一不允许保留断链
|
||||||
|
<!-- id: a1b2c3d4 -->
|
||||||
|
|
||||||
### [WARN] 内容矛盾 — 跨文件表述冲突
|
### [WARN] 内容矛盾 — 跨文件表述冲突
|
||||||
|
|
||||||
@@ -248,6 +302,7 @@ last_updated: YYYY-MM-DD
|
|||||||
- Q2:另一方是「计划未实施」还是「过时记录」?
|
- Q2:另一方是「计划未实施」还是「过时记录」?
|
||||||
- Q3:近 30 天 git log 有迁移提交?
|
- Q3:近 30 天 git log 有迁移提交?
|
||||||
- **矩阵**:Q1 答案 = 当前权威;Q2 过时 → 直接更新另一方;Q2 计划 → 末尾标 `**Status:** planned, target HASH`;Q3 有迁移 → 用迁移时间反推
|
- **矩阵**:Q1 答案 = 当前权威;Q2 过时 → 直接更新另一方;Q2 计划 → 末尾标 `**Status:** planned, target HASH`;Q3 有迁移 → 用迁移时间反推
|
||||||
|
<!-- id: e5f6a7b8 -->
|
||||||
|
|
||||||
### [WARN] 过期记忆 — last_updated 超阈值
|
### [WARN] 过期记忆 — last_updated 超阈值
|
||||||
|
|
||||||
@@ -257,6 +312,7 @@ last_updated: YYYY-MM-DD
|
|||||||
- Q2:现有内容是否仍可指导决策?
|
- Q2:现有内容是否仍可指导决策?
|
||||||
- Q3:是否有继任 synthesis_* 已分担其职责?
|
- Q3:是否有继任 synthesis_* 已分担其职责?
|
||||||
- **矩阵**:Q1 是 + Q2 否 → 触发 `/memory-update`;Q2 是(仅日期老)→ 仅刷新 `last_updated`;Q3 是 → 归档/删除,索引指向继任者
|
- **矩阵**:Q1 是 + Q2 否 → 触发 `/memory-update`;Q2 是(仅日期老)→ 仅刷新 `last_updated`;Q3 是 → 归档/删除,索引指向继任者
|
||||||
|
<!-- id: c9d0e1f2 -->
|
||||||
|
|
||||||
### [WARN] 可推断内容污染 — 疑似从代码可 grep 的明细
|
### [WARN] 可推断内容污染 — 疑似从代码可 grep 的明细
|
||||||
|
|
||||||
@@ -266,6 +322,7 @@ last_updated: YYYY-MM-DD
|
|||||||
- Q2:删除后剩余内容是否仍清晰描述「为什么/约束/边界」?
|
- Q2:删除后剩余内容是否仍清晰描述「为什么/约束/边界」?
|
||||||
- Q3:是否承载 git history 抓不到的语义?(如「曾选 A 后改 B 因 X」)
|
- Q3:是否承载 git history 抓不到的语义?(如「曾选 A 后改 B 因 X」)
|
||||||
- **矩阵**:Q1+Q2 = 是 + Q3 否 → 安全删除;Q3 是 → 改写为决策格式迁到 decisions.md(保留 Why);Q2 否 → 保留架构层级描述但删具体路径
|
- **矩阵**:Q1+Q2 = 是 + Q3 否 → 安全删除;Q3 是 → 改写为决策格式迁到 decisions.md(保留 Why);Q2 否 → 保留架构层级描述但删具体路径
|
||||||
|
<!-- id: 3a4b5c6d -->
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -291,7 +348,8 @@ last_updated: YYYY-MM-DD
|
|||||||
## 执行约束
|
## 执行约束
|
||||||
|
|
||||||
1. **AUTO-FIX 边界严格** — 只修结构性错误(孤儿、幽灵、断链、双链),不改业务内容
|
1. **AUTO-FIX 边界严格** — 只修结构性错误(孤儿、幽灵、断链、双链),不改业务内容
|
||||||
2. **NEED-HUMAN 完整记录** — 每项含 checklist + 决策矩阵
|
2. **NEED-HUMAN 完整记录** — 每项含 checklist + 决策矩阵 + 末尾 `<!-- id: xxxxxxxx -->` 稳定 ID
|
||||||
3. **矛盾检测先过等价表** — 先加载 `synonyms.md` 再判矛盾;措辞不一致 ≠ 矛盾,宁漏报不误报;项目可在 `.claude/memory/synonyms.md` 维护等价组降低误报率
|
3. **resolved 保活** — Phase 8-pre 提取旧 lint_report.md 中带 `<!-- resolved -->` 的 ID 集合,新报告中同 ID 条目跳过;用户标记 resolved 即长效免打扰
|
||||||
4. **污染检测边界**(重申)— 架构层级保留 / 具体类名路径删除
|
4. **矛盾检测先过等价表** — 先加载 `synonyms.md` 再判矛盾;措辞不一致 ≠ 矛盾,宁漏报不误报;项目可在 `.claude/memory/synonyms.md` 维护等价组降低误报率(synonyms.md 由 Phase 2 自动登记入 MEMORY.md)
|
||||||
5. **被调用静默返回** — `/memory-sync` 内 Phase 9 不输出收尾
|
5. **污染检测边界**(重申)— 架构层级保留 / 具体类名路径删除
|
||||||
|
6. **被调用静默返回** — `/memory-sync` 内 Phase 9 不输出收尾
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ description: 项目记忆体系完整同步。Git检查→远程补充本地→
|
|||||||
|
|
||||||
# memory-sync
|
# 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 准备(冲突解决优先 → 普通变更提交)
|
Phase 0 Git 准备(冲突解决优先 → 普通变更提交)
|
||||||
@@ -98,26 +100,28 @@ done
|
|||||||
|
|
||||||
### 多机不同步检测
|
### 多机不同步检测
|
||||||
|
|
||||||
两边都存在的文件,对比 mtime:
|
两边都存在的文件,对比 mtime。阈值:`MULTI_HOST_WARN_DAYS`(见 memcore-shared,默认 7)。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
MULTI_HOST_WARN_DAYS=7 # 与 memcore-shared 全局常量保持一致
|
||||||
|
|
||||||
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
||||||
local="$PROJECT_DIR/.claude/memory/$(basename "$f")"
|
local="$PROJECT_DIR/.claude/memory/$(basename "$f")"
|
||||||
[ ! -f "$local" ] && continue
|
[ ! -f "$local" ] && continue
|
||||||
rm=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f")
|
rm=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f")
|
||||||
lm=$(stat -c %Y "$local" 2>/dev/null || stat -f %m "$local")
|
lm=$(stat -c %Y "$local" 2>/dev/null || stat -f %m "$local")
|
||||||
diff_days=$(( (rm - lm) / 86400 ))
|
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
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
≥1 个警告 → 提示 `检测到 N 个文件远程比本地新 ≥7 天,可能多机不同步。继续?(y/n)`。
|
≥1 个警告 → 提示 `检测到 N 个文件远程比本地新 ≥MULTI_HOST_WARN_DAYS 天,可能多机不同步。继续?(y/n)`。
|
||||||
- `n` → 终止整个 sync 流程
|
- `n` → 终止整个 sync 流程
|
||||||
- `y` → 继续(Phase 10 仍按本地权威覆盖远程)
|
- `y` → 继续(Phase 10 仍按本地权威覆盖远程)
|
||||||
|
|
||||||
### 并发分歧检测(mtime 差 < 7 天的冲突预警)
|
### 并发分歧检测(mtime 差 < `MULTI_HOST_WARN_DAYS` 天的冲突预警)
|
||||||
|
|
||||||
对「两边都存在且 mtime 差 < 7 天」的文件,进一步做内容比对:
|
对「两边都存在且 mtime 差 < `MULTI_HOST_WARN_DAYS`(默认 7)天」的文件,进一步做内容比对:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
for f in ~/.claude/projects/{PROJECT_KEY}/memory/*.md; do
|
||||||
|
|||||||
@@ -5,41 +5,43 @@ description: 根据git diff增量范围,更新本地记忆文件和MEMORY.md
|
|||||||
|
|
||||||
# memory-update
|
# 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/`)
|
目录不存在则 `mkdir -p`。
|
||||||
|
|
||||||
**严禁写入的路径**:
|
|
||||||
- `~/.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
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 1 — 读取增量锚点
|
## Phase 1 — 读取增量锚点
|
||||||
|
|
||||||
```bash
|
```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)
|
git -C "$PROJECT_DIR" rev-parse --short HEAD # → $HEAD_HASH(非 git 仓库填 N/A)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**为什么需要兜底**:MEMORY.md 头部的 `Base commit: HASH` 是单一来源,一旦用户手动编辑误删此行,整个 diff 范围退化为全量 → 触发 update 重写所有文件。兜底机制从各文件 frontmatter 的 `commit:` 字段取**最旧值**,确保覆盖所有真实改动而不退化为无差别全量。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 2 — 计算变更范围
|
## Phase 2 — 计算变更范围
|
||||||
@@ -130,21 +132,35 @@ commit: HASH
|
|||||||
|
|
||||||
每次执行 Phase 3 末尾**强制运行**。目的:在短会话或任务型对话中,不依赖 lint 的延迟触发,直接检测 synthesis 升级候选。
|
每次执行 Phase 3 末尾**强制运行**。目的:在短会话或任务型对话中,不依赖 lint 的延迟触发,直接检测 synthesis 升级候选。
|
||||||
|
|
||||||
|
阈值:`SYNTHESIS_THRESHOLD`(见 memcore-shared,当前 = 3)。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 阈值从 memcore-shared 读取
|
||||||
|
SYNTHESIS_THRESHOLD=3 # 与 memcore-shared 全局常量保持一致
|
||||||
|
|
||||||
# 对 decisions.md / feedback*.md 的每个 ## 条目,统计被多少不同源文件引用
|
# 对 decisions.md / feedback*.md 的每个 ## 条目,统计被多少不同源文件引用
|
||||||
for entry_file in "$PROJECT_DIR/.claude/memory/decisions.md" \
|
for entry_file in "$PROJECT_DIR/.claude/memory/decisions.md" \
|
||||||
"$PROJECT_DIR/.claude/memory/feedback"*.md; do
|
"$PROJECT_DIR/.claude/memory/feedback"*.md; do
|
||||||
[ -f "$entry_file" ] || continue
|
[ -f "$entry_file" ] || continue
|
||||||
fn=$(basename "$entry_file")
|
fn=$(basename "$entry_file")
|
||||||
while IFS= read -r title; do
|
while IFS= read -r title; do
|
||||||
count=$(grep -rl "\[\[${fn}#${title}\]\]" \
|
# 使用 printf %q 转义 title 中的特殊字符(空格 / 中文标点 / 引号等)
|
||||||
"$PROJECT_DIR/.claude/memory/" --include="*.md" \
|
# 同时去除 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)
|
| 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 < <(grep "^## " "$entry_file" | sed 's/^## //')
|
||||||
done | sort -t'|' -k1 -rn
|
done | sort -t'|' -k1 -rn
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**脚本健壮性说明**:
|
||||||
|
- 使用 `grep -F`(fixed string)避免 `[[` `]]` 在正则中的歧义
|
||||||
|
- title 含中文 / 空格 / 标点时不会破坏匹配
|
||||||
|
- `--` 防止 title 以 `-` 开头被误解为 grep 选项
|
||||||
|
- 单文件中同标题多次引用按 `-l` 仅记一次(按文件去重)
|
||||||
|
|
||||||
对每条输出候选(`count|file#title`):
|
对每条输出候选(`count|file#title`):
|
||||||
1. 读原条目内是否含 `**Synthesized:**` → 已升级,跳过
|
1. 读原条目内是否含 `**Synthesized:**` → 已升级,跳过
|
||||||
2. 读原条目内是否含 `<!-- synthesis-decline: YYYY-MM-DD -->` → 30 天内,跳过
|
2. 读原条目内是否含 `<!-- synthesis-decline: YYYY-MM-DD -->` → 30 天内,跳过
|
||||||
@@ -154,6 +170,7 @@ done | sort -t'|' -k1 -rn
|
|||||||
- Phase 3C(快扫):每次 memory-update 必跑,判据为「存在引用行数」,适合即时触发
|
- Phase 3C(快扫):每次 memory-update 必跑,判据为「存在引用行数」,适合即时触发
|
||||||
- lint Phase 3A(精扫):按源文件去重的精确计数,月度健康检查时运行
|
- lint Phase 3A(精扫):按源文件去重的精确计数,月度健康检查时运行
|
||||||
- 两者以 `**Synthesized:**` 标记为唯一判重依据,不重复创建文件
|
- 两者以 `**Synthesized:**` 标记为唯一判重依据,不重复创建文件
|
||||||
|
- 阈值唯一来源为 memcore-shared 的 `SYNTHESIS_THRESHOLD`,调整请改 memcore-shared
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user