# Evolve

> 读取 memex 发来的变更通知（GitHub issue 或本地文档），自动分析本 wiki 中需要更新的内容并应用变更。最常见场景：memex 完成架构调整后向各子 wiki 推送同步通知，/evolve 在子 wiki 中执行变更并提交。

- Skill: `orangeviolin/evolve` (Agent Skill)
- Install (CLI): `npx skillmds@latest add orangeviolin/evolve`
- Raw SKILL.md: https://api.skillmd.com/api/skills/orangeviolin/evolve/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: OrangeViolin (https://skillmd.com/u/orangeviolin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/orangeviolin/evolve

---


# /evolve — 自动应用 memex 变更通知

## 用途

memex 主库完成某项架构变更后，会向各子 wiki 创建通知 issue（如路径重命名、术语更新、规范调整）。在子 wiki 中运行 `/evolve` 即可自动读取通知、扫描受影响内容、应用变更并提交。

也可用于读取任意本地文档中的变更指令并执行。

---

## 参数形式

| 参数 | 含义 |
|------|------|
| `/evolve` | 无参数：自动查找本 repo GitHub issues 中最新的未关闭 memex 通知（标题含 `[通知]` 或 `[memex]`）|
| `/evolve <N>` | 本 repo 的 issue #N |
| `/evolve <URL>` | 任意 GitHub issue URL（跨 repo 也支持） |
| `/evolve <文件路径>` | 读取本地 `.md` 文件中的变更指令 |

---

## 执行流程

### Step 0 — 识别当前 wiki 环境

```bash
# 获取当前 wiki 名（用于过滤和日志）
WIKI_NAME=$(basename $(git rev-parse --show-toplevel))
WIKI_ROOT=$(git rev-parse --show-toplevel)
WIKI_REMOTE=$(git remote get-url origin 2>/dev/null)
```

记录：`wiki=$WIKI_NAME`，后续所有操作均在此目录下执行。

---

### Step 1 — 读取变更通知

#### 无参数时：自动发现

```bash
gh issue list --repo "$CURRENT_REPO" --state open \
  --json number,title,createdAt \
  | python3 -c "
import json, sys
issues = json.load(sys.stdin)
notify = [i for i in issues if '[通知]' in i['title'] or '[memex]' in i['title']]
if not notify:
    print('NO_NOTIFY')
else:
    notify.sort(key=lambda x: x['number'])
    print(notify[0]['number'])
"
```

若无待处理通知，输出"当前无待处理 memex 通知 issue"，结束。

#### 参数为 issue 编号或 URL：

```bash
# 编号：gh issue view <N> --repo <当前 repo>
# URL：gh issue view <URL>
```

提取 issue 正文全文。

#### 参数为本地文件：

直接 Read 文件内容。

---

### Step 2 — 解析变更指令

从通知正文中提取结构化变更：

#### 2-A 路径重命名

识别形如：
```
`旧路径/` → `新路径/`
旧路径/ → 新路径/
old/path/ → new/path/
```

构建重命名映射表：`[(旧路径, 新路径), ...]`

#### 2-B 文本替换

识别形如：
```
旧术语 → 新术语
`旧字符串` → `新字符串`
s/旧/新/g
```

构建替换规则列表：`[(旧, 新), ...]`

#### 2-C 文件操作

识别需要新增/删除/移动的文件（如 `git mv`、创建新文件、追加内容等）。

#### 2-D 排除范围

识别通知中声明的"保留原文"文件（如历史 RFC 文件），加入排除列表。

**若无法从通知提取任何结构化变更**，在屏幕说明"无法解析明确的变更指令"，展示通知原文摘要，询问用户手动确认变更内容后继续。

---

### Step 3 — 扫描影响范围

对当前 wiki 执行 dry-run 扫描，找出所有受影响文件：

```bash
# 扫描文本替换影响范围
for (旧, 新) in 替换规则:
    grep -rn "旧" . --include="*.md" --include="*.py" --include="*.sh" \
      --include="*.json" --include="*.yaml" | grep -v ".git"
```

**输出预览**（必须在应用前展示）：

```
=== /evolve 变更预览 ===
Wiki: <wiki_name>
来源: issue #N / <文件路径>

【路径重命名】
  skills/atomic/ → skills/gene/（影响 N 个文件）

【文本替换】
  "原子动作" → "基因"（N 处，X 个文件）
  "skills/atomic/" → "skills/gene/"（N 处，X 个文件）

【排除文件】
  ref/rfc/rfc-<wiki>-000X-*.md（历史文件，保留原文）

【受影响文件列表（前 10）】
  - BIRTH.md（3 处）
  - wiki/scripts/assign_pn.py（1 处）
  ...

确认应用以上变更？(y/n)
```

等待用户确认后继续。若影响范围为 0，告知"本 wiki 无需更新"，结束。

---

### Step 4 — 应用变更

按以下顺序执行：

#### 4-A git mv（路径重命名）

```bash
# 仅当本 wiki 存在旧路径时执行
for (旧路径, 新路径) in 重命名映射:
    if [ -e "旧路径" ]; then
        git mv "旧路径" "新路径"
    fi
```

#### 4-B 全局文本替换

```bash
# 排除 .git/ 和声明保留的文件
受影响文件列表 | xargs sed -i 替换规则...
```

**替换顺序**：先长串、再短串（避免前缀冲突）。

#### 4-C 特殊操作

按通知中的额外指令执行（如向某节追加内容、更新字段值等）。

每步完成后输出进度：`✅ 完成：<操作描述>`

---

### Step 5 — 验证

```bash
# 验证旧术语/路径已清零（排除历史文件）
for (旧, 新) in 替换规则:
    count=$(grep -rn "旧" . --include="*.md" --include="*.py" \
      | grep -v ".git" | grep -v 排除文件 | wc -l)
    if [ $count -gt 0 ]; then
        echo "⚠️ 仍有 $count 处未替换，列出位置"
    fi
```

若有残留，列出文件和行号，询问用户是否手动处理后继续。

---

### Step 6 — 写执行报告

在 `logs/evolve/` 下写入本次执行的报告文件。

**文件路径**：`logs/evolve/YYYY-MM-DD-<来源slug>.md`

- 日期取执行当日
- `<来源slug>`：issue 编号（如 `issue-1`）或文件名去扩展名（如 `migration-notes`）

**报告格式**：

```markdown
# evolve 执行报告：<通知标题>

- **日期**: YYYY-MM-DD
- **Wiki**: <wiki_name>
- **来源**: <issue URL 或文件路径>
- **执行结果**: success | partial | skipped

---

## 变更摘要

| 类型 | 内容 | 处数 | 文件数 |
|------|------|------|--------|
| 路径重命名 | `旧路径/` → `新路径/` | — | N |
| 文本替换 | "旧术语" → "新术语" | N | N |
| ... | | | |

## 受影响文件

- `BIRTH.md`（3 处）
- `wiki/scripts/assign_pn.py`（1 处）

## 验证结果

- [x] "旧术语" 残留：0 处
- [x] `旧路径/` 残留：0 处

## 残留问题（若有）

> 若验证步骤发现有残留，在此列出文件和行号。若无，此节删除。

## Commit

`<commit SHA>`

## 备注

> 可选：记录执行中遇到的特殊情况、人工干预、跳过原因等。
```

**结果码说明**：
- `success`：所有变更完整应用，验证清零
- `partial`：有残留或跳过部分变更（须填写"残留问题"节）
- `skipped`：本 wiki 无需更新（影响范围为 0）

---

### Step 7 — 提交

```bash
git add <所有变更文件> logs/evolve/YYYY-MM-DD-<来源slug>.md
bash wiki/scripts/skill_commit.sh -m "evolve: 同步 memex 变更——<通知标题简述>

来源: <issue URL 或文件路径>
变更: <1-2 句话描述>
日志: logs/evolve/YYYY-MM-DD-<来源slug>.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"
```

---

### Step 8 — 回应通知（可选）

若变更来源为 GitHub issue，在 issue 留回复：

```
✅ <wiki_name> 已同步（commit: <SHA>）

变更摘要：
- BIRTH.md：3 处路径引用更新
- wiki/scripts/assign_pn.py：注释更新

执行报告：logs/evolve/YYYY-MM-DD-<来源slug>.md
```

若通知 issue 来自本 wiki repo，询问用户是否关闭该 issue。

---

## 铁律

- **Step 3 的预览是强制的**：在用户确认前绝不写入任何文件
- **不写入 memex**：当前 wiki 非 memex 时，绝不修改 `$MEMEX_ROOT` 下任何文件
- **历史文件保留**：RFC 历史文件（`ref/rfc/rfc-*-000*.md`）默认加入排除列表，除非通知明确说明要更改
- **范围最小化**：只替换通知明确指定的内容，不做超出范围的"顺手"修改
- **无结构化指令时停止**：无法从通知中解析出明确的变更规则时，展示原文并等待用户指示，不猜测

---

## 典型场景示例

### 场景 A：memex 路径重命名通知

memex 在 aima repo 创建 issue："skills/atomic/ → skills/gene/ 路径变更"

在 aima 中运行：
```
/evolve 1
```

执行流程：
1. 读取 issue #1
2. 解析：路径重命名 `skills/atomic/` → `skills/gene/`，文本替换"原子动作"→"基因"
3. 扫描：BIRTH.md（3处），assign_pn.py（1处）
4. 展示预览，确认
5. 应用替换，验证，提交
6. 在 issue #1 留回复

### 场景 B：本地变更文档

```
/evolve ref/spec/migration-notes.md
```

读取本地迁移文档，按其中的变更指令在当前 wiki 执行。

### 场景 C：跨 repo issue

```
/evolve https://github.com/baojie/memex/issues/58
```

直接读取 memex repo 的 issue，解析并在当前 wiki 应用相关变更。

