# Grow

> 启动或推进当前 Wiki 的 GROW 增长流程。读取 GROW.md 中的当前阶段，按 $MEMEX_ROOT/GROW.spec.md 执行下一个未完成的 Phase。BIRTH Phase 10 完成后调用。

- Skill: `orangeviolin/grow` (Agent Skill)
- Install (CLI): `npx skillmds@latest add orangeviolin/grow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/orangeviolin/grow/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/grow

---


# /grow — Wiki 增长流程推进器

## 用法

```
/grow                   # 读取当前阶段，执行下一步
/grow phase0            # 强制执行 Phase 0（基线摸底）
/grow status            # 只展示当前状态，不执行任何操作
/grow init phaseN       # 初始化模式：N 为数字（如 /grow init phase2）
```

**门控 — pypinyin 检查**：CJK wiki 必须先确认已安装 pypinyin（`python3 -c "import pypinyin"`），否则后续创建中文页面时 `page_bucket.py` 会抛出 ImportError。缺失则提示用户安装并中止。

## `init phaseN` 模式

**触发条件**：参数为 `init phaseN`，N 为整数（如 `phase0`、`phase2`）。

执行以下三步，顺序不可调换：

### Step 1 — 补全 Phase 0 至 Phase N-1

读取本地 `GROW.md`，对每个 Phase（0 到 N-1）：
- 若该 Phase 已有完整实例化内容（非 `> 状态：未开始`），跳过
- 若该 Phase 仅有占位行，从 `$MEMEX_ROOT/GROW.spec.md` 复制对应 Phase 的规范内容，用本项目已知参数填写具体值，所有 `[ ]` 改为 `[x]`（视为已完成），写入 `GROW.md`
- 补全时保留本地已有的 `grow_baseline.md` 数据、commit hash、日期等具体记录，不用模板占位符覆盖
- **Phase 1 特例**：Phase 1 对应 BIRTH Phase 9（种子层），补全时从 `local/memory/boot_summary.md` 提取 Pilot EVV 数据填入，而非生成虚构数据

### Step 2 — 实例化 Phase N

从 `$MEMEX_ROOT/GROW.spec.md` 复制 Phase N 的完整规范内容，写入本地 `GROW.md` 的对应节（替换原有的 `> 状态：未开始`），执行以下替换：
- 所有 `{{...}}` 占位符用本项目实际参数填写
- 所有 `[ ]` 保持 `[ ]`（待执行）
- `WIKI_NAME`、`PORT` 等从 `local/config.md` 读取
- 章节结构、类型体系从 `LAW.md` 读取
- 基线指标（页数、质量分布）从 `grow_baseline.md` 读取（若存在）

**Phase 特定初始化**：

| Phase N | 额外初始化动作 |
|---------|--------------|
| `phase0` | 无（Phase 0 本身产出 `grow_baseline.md`，执行时生成）|
| `phase2` | 若 `grow_state.json` 不存在，按 `GROW.spec.md §grow_state.json` 的 schema 初始化骨架文件（`status: pending`，`closed_types: []`，从 `pages.json` 重建当前状态）|
| `phase3`、`phase4` | 确认 `grow_baseline.md` 存在，否则提示先执行 Phase 0 |

### Step 3 — 合规检查

#### Step 3a — 标题树结构完整性校验

从 `GROW.spec.md` 提取 Phase N 的标题树，与实例化后的 `GROW.md` 逐级对比，发现缺失则立即停止。

```python
import re, sys
spec_path = sys.argv[1]  # GROW.spec.md
inst_path = sys.argv[2]  # GROW.md
phase_n   = int(sys.argv[3])

def extract_headings(text, phase_n):
    pat = re.compile(rf'^##\s+Phase\s+{phase_n}[\s：]', re.M)
    nxt = re.compile(rf'^##\s+Phase\s+{phase_n + 1}[\s：]', re.M)
    m = pat.search(text)
    if not m: return [], 0
    start, headings = m.start(), []
    m2 = nxt.search(text, start + 1)
    end = m2.start() if m2 else len(text)
    for h in re.findall(r'^(#{2,4}\s+.+)$', text[start:end], re.M):
        headings.append(h.strip())
    return headings, len(re.findall(r'^##\s+Phase\s+\d+', text[start:end], re.M))

spec_heads, spec_sub = extract_headings(open(spec_path).read(), phase_n)
inst_heads, inst_sub = extract_headings(open(inst_path).read(), phase_n)
missing = set(spec_heads) - set(inst_heads)
extra   = set(inst_heads) - set(spec_heads)

print(f'Spec Phase {phase_n} 标题数: {len(spec_heads)}')
print(f'实例 Phase {phase_n} 标题数: {len(inst_heads)}')
if missing:
    print(f'✗ 缺失 {len(missing)} 项：')
    for h in sorted(missing):
        print(f'  {h}')
    print('→ 补全缺失节后重新检查。')
    sys.exit(1)
if extra:
    print(f'（额外 {len(extra)} 项——疑为专有扩展，不报错）')
    for h in sorted(extra):
        print(f'  {h}')
print('✓ 结构完整，无缺失标题。')
```

用法：
```bash
python3 -c "$(上述代码)" $MEMEX_ROOT/GROW.spec.md GROW.md <N>
```

校验不通过时中止，补全缺失节后重新执行 Step 3a。通过后进入 Step 3c。

#### Step 3c — Content Fidelity 检查（PCF1–PCF3）

标题树通过后，进一步验证内容实例化 fidelity。从 `GROW.spec.md` 对应 Phase 提取数据，与 `GROW.md` 逐项对比。

用法：
```bash
# 以下各脚本以 GROW.spec.md 为 spec 参数、GROW.md 为实例参数
SPEC=$MEMEX_ROOT/GROW.spec.md
INST=GROW.md
N=<phase_number>
```

**PCF1 — 代码块完整性**：

```python
import re, sys
spec_path = sys.argv[1]; inst_path = sys.argv[2]; phase_n = int(sys.argv[3])
def cnt(text, pn):
    pat = re.compile(rf'^##\s+Phase\s+{pn}[\s：]', re.M)
    nxt = re.compile(rf'^##\s+Phase\s+{pn+1}[\s：]', re.M)
    m = pat.search(text)
    if not m: return 0
    s=m.start(); m2=nxt.search(text,s+1); e=m2.start() if m2 else len(text)
    return len(re.findall(r'^```', text[s:e], re.M))
sc=cnt(open(spec_path).read(),phase_n); ic=cnt(open(inst_path).read(),phase_n)
r=ic/sc*100 if sc else 100
print(f'{"✓" if ic>=sc else "✗"} PCF1: spec {sc} 代码块, 实例 {ic} ({r:.0f}%)')
if ic<sc: print(f'  → 缺失 {sc-ic} 个，补全后重新执行 Step 3c'); exit(1)
```

**PCF2 — 复选框完整性**：

```python
import re, sys
spec_path=sys.argv[1]; inst_path=sys.argv[2]; phase_n=int(sys.argv[3])
def cnt(text,pn):
    pat=re.compile(rf'^##\s+Phase\s+{pn}[\s：]',re.M)
    nxt=re.compile(rf'^##\s+Phase\s+{pn+1}[\s：]',re.M)
    m=pat.search(text)
    if not m: return 0
    s=m.start(); m2=nxt.search(text,s+1); e=m2.start() if m2 else len(text)
    return len(re.findall(r'\[[\sx]\]',text[s:e]))
sc=cnt(open(spec_path).read(),phase_n); ic=cnt(open(inst_path).read(),phase_n)
r=ic/sc*100 if sc else 100
print(f'{"✓" if ic>=sc else "✗"} PCF2: spec {sc} 复选框, 实例 {ic} ({r:.0f}%)')
if ic<sc: print(f'  → 缺失 {sc-ic} 个，补全后重新执行 Step 3c'); exit(1)
```

**PCF3 — 内容体量偏差**：

```python
import re, sys
spec_path=sys.argv[1]; inst_path=sys.argv[2]; phase_n=int(sys.argv[3])
def lines(text,pn):
    pat=re.compile(rf'^##\s+Phase\s+{pn}[\s：]',re.M)
    nxt=re.compile(rf'^##\s+Phase\s+{pn+1}[\s：]',re.M)
    m=pat.search(text)
    if not m: return 0
    s=m.start(); m2=nxt.search(text,s+1); e=m2.start() if m2 else len(text)
    return len(text[s:e].splitlines())
sl=lines(open(spec_path).read(),phase_n); il=lines(open(inst_path).read(),phase_n)
r=il/sl*100 if sl else 100
print(f'{"✓" if r>=50 else "✗"} PCF3: spec {sl} 行 → 实例 {il} 行 ({r:.0f}%)')
if r<50: print(f'  → 疑似摘要而非实例化（<50%），补全后重新执行 Step 3c'); exit(1)
```

全部通过后进入 Step 3b。

#### Step 3b — 语义合规检查

对刚写入的 Phase N 内容执行 `/comply GROW.md phase N` 检查（含 PCF4 占位符残留 + PCF5 结构性节缺失）：
- 检查内容是否忠实于 `GROW.spec.md`（无遗漏步骤、无错误参数）
- PCF4 — 检查占位符是否全部替换（不得有 `{{...}}` 残留）
- PCF5 — 检查结构性节是否完整（标题下的代码块/表格/列表等结构元素无缺失）
- 检查与本项目 `LAW.md`、`CONSTITUTION.md` 是否一致
- **Phase 2 专项**：检查 `grow_state.json` schema 是否符合 `GROW.spec.md §grow_state.json`（字段名、类型、必填项）
- 发现偏差直接在当前对话中修正，不另起 RFC

完成后输出摘要：已补全哪些 Phase、Phase N 实例化了哪些内容、comply 发现了什么（若无问题则写"无发现"）。

---

## 前置条件

- 当前目录为 wiki 根目录（含 `BIRTH.md`、`docs/wiki/pages.json`）
- BIRTH Phase 10 已完成（`local/memory/boot_summary.md` 存在）
- `$MEMEX_ROOT` 指向 `~/memex`，`GROW.spec.md` 存在

## 执行逻辑

### 第一步：定位当前状态

```bash
# 1. 确认处于 wiki 根目录
ls BIRTH.md docs/wiki/pages.json local/memory/boot_summary.md

# 2. 读取 GROW.md（如存在）
# 3. 读取 local/memory/grow_baseline.md（如存在）
```

判断入口：

| 条件 | 行动 |
|------|------|
| `GROW.md` 不存在 | 从 `$MEMEX_ROOT/GROW.spec.md` 创建本 wiki 的 `GROW.md` 骨架，然后执行 Phase 0 |
| `GROW.md` 存在，Phase 0 未完成（无 `[x]` 在 0-X 验收标准）| 执行 Phase 0 |
| Phase 0 已完成，`grow_baseline.md` 中 `grow_phase: Phase 2` | 执行 Phase 2 |
| Phase 0 已完成，`grow_baseline.md` 中 `grow_phase: Phase 3` | 执行 Phase 3 |
| Phase 0 已完成，`grow_baseline.md` 中 `grow_phase: Phase 4` | 执行 Phase 4 |

### 第二步：执行对应 Phase

> 以下门控在确定 Phase N 后、执行任何步骤前逐一检查，任一不通过则中止。

**门控 1 — 实例化检查**：确认 GROW.md 中存在 `^## Phase N` 节。
```bash
grep -q "^## Phase ${PHASE}" GROW.md 2>/dev/null && echo "✓ Phase ${PHASE} 已实例化" || {
  echo "✗ Phase ${PHASE} 尚未在 GROW.md 中实例化。"
  echo "→ 请先执行 /grow init phase${PHASE} 完成实例化"
  exit 1
}
```

**门控 2 — comply 质检检查**：确认 Phase N 节中标注了 `> **comply**: pass`。
```bash
grep -A 50 "^## Phase ${PHASE}" GROW.md 2>/dev/null \
  | grep -q "> \*\*comply\*\*: pass" \
  && echo "✓ Phase ${PHASE} comply 质检已通过" || {
    echo "✗ Phase ${PHASE} 尚未通过 comply 质检。"
    echo "→ 请先执行 /comply grow ${PHASE}，质检通过后在 Phase 节标注 comply: pass 再继续"
    exit 1
  }
```

两门控通过后，读取 `$MEMEX_ROOT/GROW.spec.md` 对应 Phase 的步骤，逐步执行。
执行完每个小节（0-A / 0-B / ...）后，在 `GROW.md` 中将对应条目标记为 `[x]`。

### 第三步：写入基线快照（Phase 0 专属）

Phase 0 的最终产出是 `local/memory/grow_baseline.md`，格式见 `GROW.spec.md §0-G`。
写入后询问用户是否提交：

```bash
git add local/memory/grow_baseline.md GROW.md
bash wiki/scripts/skill_commit.sh "docs: GROW Phase 0 基线摸底完成"
```

## Phase 0 详细步骤（内联）

> Phase 2–4 规范持续完善中，执行前读 `$MEMEX_ROOT/GROW.spec.md` 对应章节。

### 0-A 前置验证

1. 确认以下文件存在，任一缺失报错并停止：
   - `local/memory/boot_summary.md`
   - `logs/butler/round_counter.txt`
   - `docs/wiki/pages.json`
   - `data/sentence_index/`
   - `logs/butler/queue.md`
   - `local/template/`

2. 读取 butler 当前轮次：
   ```bash
   cat logs/butler/round_counter.txt
   ```

### 0-B 页面库扫描

```python
python3 -c "
import json
from collections import Counter
d = json.load(open('docs/wiki/pages.json'))
pages = d['pages']
types = Counter(v.get('type','?') for v in pages.values())
quals = Counter(v.get('quality','none') for v in pages.values())
entries = {k:v for k,v in pages.items() if v.get('type') not in ('chapter','overview','list')}
e_quals = Counter(v.get('quality','none') for v in entries.values())
print(f'总页数: {len(pages)}')
print(f'章节: {types.get(\"chapter\",0)}  词条类: {len(entries)}')
print(f'类型分布: {dict(sorted(types.items()))}')
print(f'词条质量: {dict(sorted(e_quals.items()))}')
stub_pct = e_quals.get('stub',0) / max(len(entries),1) * 100
feat_pct = (e_quals.get('featured',0) + e_quals.get('premium',0)) / max(len(entries),1) * 100
print(f'stub%: {stub_pct:.1f}%  featured+%: {feat_pct:.1f}%')
"
```

读取 `local/template/` 列出已有类型模板：
```bash
ls local/template/
```

对照 `logs/butler/type-survey.md`（如存在）计算各类型覆盖率。

### 0-C Pilot 信息读取

```bash
grep -A 30 "Pilot EVV" local/memory/boot_summary.md 2>/dev/null || \
  echo "boot_summary.md 无 EVV 汇总，跳过"
```

提取每种类型的均分趋势和遗留问题，判断是否有阻塞 Phase 2 的债务。

### 0-D 候选池评估

```bash
grep -c "^\-" logs/butler/queue.md 2>/dev/null || echo "队列为空"
cat logs/butler/type-survey.md 2>/dev/null | grep -A 2 "估算数量" || true
```

### 0-E 链接网络密度

```bash
grep -roh '\[\[[^\]]*\]\]' docs/wiki/pages/ --include="*.md" 2>/dev/null | wc -l
```

```python
python3 -c "
import json
try:
    d = json.load(open('docs/wiki/backlinks.json'))
    covered = len([k for k,v in d.items() if v])
    print(f'backlinks: {covered}/{len(d)} 页被引用，{sum(len(v) for v in d.values())} 条')
except FileNotFoundError:
    print('backlinks.json 不存在，未构建')
" 2>/dev/null
```

### 0-F 阶段定位

根据以下规则确定 GROW 阶段并报告：

| 条件 | GROW 阶段 |
|------|----------|
| BIRTH Phase 9 未完成 | ⛔ 返回 BIRTH |
| 存在阻塞性遗留债务 | ⛔ 先修复 |
| stub% = 0，N_entries < 80 | Phase 2（广度扩张）|
| stub% 0–20%，featured% < 20% | Phase 2（广度扩张）|
| stub% < 5%，featured% < 50% | Phase 3（深度提升）|
| stub% < 5%，featured% > 50% | Phase 4（洞察层）|

### 0-G 写入 grow_baseline.md

按 `GROW.spec.md §0-G` 的模板写入 `local/memory/grow_baseline.md`，
填写所有扫描结果（无 `{{占位符}}`），并确定「下一步优先动作 Top 3」。

同步更新 `GROW.md` 中 Phase 0 各步骤的 `[x]` 状态。

## Phase 2 页面操作规范（不可违背）

所有 wiki 页面的新建和编辑，**必须**通过脚本完成，严禁使用 Claude 内置的 Write/Edit 工具直接操作页面文件。

**新建页面**：将内容写入临时文件，然后调用：
```bash
python3 $MEMEX_ROOT/wiki/scripts/add_page.py "<slug>" /tmp/page_content.md \
    --author grow --summary "GROW 2-X: 新建 <slug>，<quality> 档"
```

**编辑页面**：将完整新内容写入临时文件，然后调用：
```bash
python3 $MEMEX_ROOT/wiki/scripts/edit_page.py "<slug>" /tmp/page_content.md \
    --author grow --summary "GROW 2-X: 编辑 <slug>"
```

这两个脚本会自动调用 `record_revision.py`，写入修订历史，并执行所有合规检查（防内容缩减、PN 有效性等）。

## 禁止事项

- ❌ 禁止直接 `git commit`（通过 `skill_commit.sh` 提交）
- ❌ 禁止写入 `$MEMEX_ROOT`（只读引用）
- ❌ 禁止跳过 0-X 验收标准直接进入 Phase 2
- ❌ 禁止在阻塞性债务未处理时推进
- ❌ 禁止用 Write 工具直接写入 `docs/pages/**/*.md`（违反 EXIT-GATE G4，绕过安全检查）
- ❌ 禁止用 Edit 工具直接修改 `docs/pages/**/*.md`（同上）
- ❌ 任何对 wiki 页面文件的增删改，必须且只能通过 `add_page.py` / `edit_page.py`

