| name | grow |
| description | 启动或推进当前 Wiki 的 GROW 增长流程。读取 GROW.md 中的当前阶段,按 $MEMEX_ROOT/GROW.spec.md 执行下一个未完成的 Phase。BIRTH Phase 10 完成后调用。 |
/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 逐级对比,发现缺失则立即停止。
import re, sys
spec_path = sys.argv[1]
inst_path = sys.argv[2]
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('✓ 结构完整,无缺失标题。')
用法:
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 逐项对比。
用法:
SPEC=$MEMEX_ROOT/GROW.spec.md
INST=GROW.md
N=<phase_number>
PCF1 — 代码块完整性:
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 — 复选框完整性:
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 — 内容体量偏差:
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 存在
执行逻辑
第一步:定位当前状态
ls BIRTH.md docs/wiki/pages.json local/memory/boot_summary.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 节。
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。
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。
写入后询问用户是否提交:
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 前置验证
-
确认以下文件存在,任一缺失报错并停止:
local/memory/boot_summary.md
logs/butler/round_counter.txt
docs/wiki/pages.json
data/sentence_index/
logs/butler/queue.md
local/template/
-
读取 butler 当前轮次:
cat logs/butler/round_counter.txt
0-B 页面库扫描
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/ 列出已有类型模板:
ls local/template/
对照 logs/butler/type-survey.md(如存在)计算各类型覆盖率。
0-C Pilot 信息读取
grep -A 30 "Pilot EVV" local/memory/boot_summary.md 2>/dev/null || \
echo "boot_summary.md 无 EVV 汇总,跳过"
提取每种类型的均分趋势和遗留问题,判断是否有阻塞 Phase 2 的债务。
0-D 候选池评估
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 链接网络密度
grep -roh '\[\[[^\]]*\]\]' docs/wiki/pages/ --include="*.md" 2>/dev/null | wc -l
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 工具直接操作页面文件。
新建页面:将内容写入临时文件,然后调用:
python3 $MEMEX_ROOT/wiki/scripts/add_page.py "<slug>" /tmp/page_content.md \
--author grow --summary "GROW 2-X: 新建 <slug>,<quality> 档"
编辑页面:将完整新内容写入临时文件,然后调用:
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