kata-migrate-phases
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<objective>
Detect and fix duplicate phase numeric prefixes caused by per-milestone numbering. Migrates all phase directories to globally sequential numbering.
Projects with multiple milestones may have colliding prefixes (e.g., from v0.1.0 and from v0.2.0 both in ). This causes to return the wrong directory.
</objective>
<context>
@.planning/STATE.md
@.planning/ROADMAP.md
</context>
<process>
<step name="detect_collisions">
01-foundation01-setupcompleted/find ... -name "01-*" | head -1Scan all phase directories for duplicate numeric prefixes:
bash
DUPES=$(for state in active pending completed; do
ls .planning/phases/${state}/ 2>/dev/null
done | grep -oE '^[0-9]+' | sort -n | uniq -d)<objective>
检测并修复因按里程碑单独编号导致的重复阶段数字前缀问题。将所有阶段目录迁移为全局连续编号。
拥有多个里程碑的项目可能会出现前缀冲突(例如,v0.1.0的和v0.2.0的都位于目录下)。这会导致返回错误的目录。
</objective>
<context>
@.planning/STATE.md
@.planning/ROADMAP.md
</context>
<process>
<step name="detect_collisions">
01-foundation01-setupcompleted/find ... -name "01-*" | head -1扫描所有阶段目录,查找重复的数字前缀:
bash
DUPES=$(for state in active pending completed; do
ls .planning/phases/${state}/ 2>/dev/null
done | grep -oE '^[0-9]+' | sort -n | uniq -d)Also check flat directories (unmigrated projects)
Also check flat directories (unmigrated projects)
FLAT_DUPES=$(ls .planning/phases/ 2>/dev/null | grep -E '^[0-9]' | grep -oE '^[0-9]+' | sort -n | uniq -d)
ALL_DUPES=$(echo -e "${DUPES}\n${FLAT_DUPES}" | sort -nu | grep -v '^$')
echo "Duplicate prefixes: ${ALL_DUPES:-none}"
If no duplicates found:
No phase prefix collisions detected. All phase directories have unique numeric prefixes.
Exit.
</step>
<step name="validate_environment">
Read ROADMAP.md and STATE.md. Confirm project is active:
```bash
[ -f .planning/ROADMAP.md ] || { echo "ERROR: No ROADMAP.md found. Not a Kata project."; exit 1; }
[ -f .planning/STATE.md ] || { echo "ERROR: No STATE.md found. Not a Kata project."; exit 1; }Display:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Kata ► PHASE MIGRATION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Duplicate prefixes detected: [list]
◆ Building chronology from ROADMAP.md...Parse ROADMAP.md to build globally sequential phase numbering. Milestones appear in chronological order.
Completed milestones: Each block contains phase lists. Parse phases in document order.
<details>Current milestone: Parse headings from the active section.
#### Phase N:Build a chronology array. Each entry: where is the slug from the phase heading (e.g., "foundation", "api-endpoints").
{global_seq} {phase_name}phase_namebash
GLOBAL_SEQ=0
CHRONOLOGY=""FLAT_DUPES=$(ls .planning/phases/ 2>/dev/null | grep -E '^[0-9]' | grep -oE '^[0-9]+' | sort -n | uniq -d)
ALL_DUPES=$(echo -e "${DUPES}\n${FLAT_DUPES}" | sort -nu | grep -v '^$')
echo "Duplicate prefixes: ${ALL_DUPES:-none}"
如果未找到重复项:
No phase prefix collisions detected. All phase directories have unique numeric prefixes.
退出。
</step>
<step name="validate_environment">
读取ROADMAP.md和STATE.md,确认项目处于活跃状态:
```bash
[ -f .planning/ROADMAP.md ] || { echo "ERROR: No ROADMAP.md found. Not a Kata project."; exit 1; }
[ -f .planning/STATE.md ] || { echo "ERROR: No STATE.md found. Not a Kata project."; exit 1; }显示:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Kata ► PHASE MIGRATION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Duplicate prefixes detected: [list]
◆ Building chronology from ROADMAP.md...解析ROADMAP.md以构建全局连续的阶段编号。里程碑按时间顺序排列。
**已完成的里程碑:**每个块包含阶段列表。按文档顺序解析阶段。
<details>**当前里程碑:**从活跃区域解析标题。
#### Phase N:构建时间线数组。每个条目格式为:,其中是阶段标题对应的短名称(例如“foundation”、“api-endpoints”)。
{global_seq} {phase_name}phase_namebash
GLOBAL_SEQ=0
CHRONOLOGY=""Parse all "Phase N: name" lines from ROADMAP.md in document order.
Parse all "Phase N: name" lines from ROADMAP.md in document order.
Completed milestones appear in <details> blocks; current milestone uses #### headings.
Completed milestones appear in <details> blocks; current milestone uses #### headings.
Both formats contain "Phase N: name" — grep catches all.
Both formats contain "Phase N: name" — grep catches all.
while IFS= read -r line; do
name=$(echo "$line" | grep -oE 'Phase [0-9.]+: .+' | sed 's/Phase [0-9.]*: //' | sed 's/**$//' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
if [ -n "$name" ]; then
CHRONOLOGY="${CHRONOLOGY}${GLOBAL_SEQ} ${name}\n"
GLOBAL_SEQ=$((GLOBAL_SEQ + 1))
fi
done < <(grep -E 'Phase [0-9.]+:' .planning/ROADMAP.md)
Decimal phases (2.1, 2.2) get sequential integer numbers after their parent. Document order determines sequence.
Display: `Chronology ([N] phases): 00 → foundation, 01 → api-endpoints, ...`
</step>
<step name="map_directories_to_phases">
Match each phase name from the chronology to its existing directory. Search across `active/`, `pending/`, `completed/`, and flat fallback.
For each chronology entry `{seq} {name}`:
1. Find directories whose slug matches `{name}` across all states
2. If multiple matches, use the one whose numeric prefix matches the original milestone-local number
3. Build mapping: `STATE/OLD_DIR → STATE/NEW_PREFIX-SLUG`
Strip numeric prefix from each directory name to get slug, compare against chronology name. Build `MAPPING` as newline-delimited entries: `STATE/OLD_DIR → PADDED-SLUG`.
Display the full mapping table.
</step>
<step name="present_migration_plan">
Display the rename table:
Migration Plan:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
completed/01-foundation → completed/00-foundation
completed/02-api-endpoints → completed/01-api-endpoints
completed/01-setup → completed/02-setup
...
active/01-current-work → active/15-current-work
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total: [N] directories to rename
Use AskUserQuestion:
- header: "Migration"
- question: "Rename [N] directories to globally sequential numbers?"
- options:
- "Proceed" — Execute all renames
- "Cancel" — Abort migration
If cancelled, exit with "Migration cancelled."
</step>
<step name="execute_renames">
Two-pass approach to avoid mid-rename collisions (established pattern from `kata-move-phase`):
**Pass 1:** Rename all directories to temporary names: `mv OLD tmp-{seq}-{slug}`
**Pass 2:** Rename from temporary to final: `mv tmp-{seq}-{slug} {padded}-{slug}`
For active/pending phases in Pass 2, also rename internal files (`*-PLAN.md`, `*-RESEARCH.md`, `*-CONTEXT.md`, `*-SUMMARY.md`) by replacing the old phase prefix with the new padded prefix: `sed "s/^[0-9.]*-/${PADDED}-/"`.
Completed phase internal files left unchanged. Wildcard lookup (`*-PLAN.md`) handles them.
Display:◆ Pass 1: Renamed [N] directories to temporary names
◆ Pass 2: Renamed [N] directories to final names
◆ Active/pending internal files updated: [count]
</step>
<step name="update_documentation">
**Update ROADMAP.md current milestone phase numbers:**
For the current (non-archived) milestone section, update `#### Phase N:` headings to use new global numbers. Match phase names to chronology to determine correct new number.
**Update STATE.md current position:**
Update the current phase reference to use the new global number. Find the line referencing the active phase and update its number.
**Leave historical `<details>` blocks unchanged.** They are archived records. Milestone archive files in `.planning/milestones/` are authoritative.
Display:
◆ Updated ROADMAP.md current milestone phase numbers
◆ Updated STATE.md current position
</step>
<step name="verify">
Re-run collision detection:
```bash
DUPES=$(for state in active pending completed; do
ls .planning/phases/${state}/ 2>/dev/null
done | grep -oE '^[0-9]+' | sort -n | uniq -d)
FLAT_DUPES=$(ls .planning/phases/ 2>/dev/null | grep -E '^[0-9]' | grep -oE '^[0-9]+' | sort -n | uniq -d)
ALL_DUPES=$(echo -e "${DUPES}\n${FLAT_DUPES}" | sort -nu | grep -v '^$')If clean:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Kata ► MIGRATION COMPLETE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ [N] directories renamed to globally sequential numbers
✓ No duplicate prefixes remain
✓ ROADMAP.md and STATE.md updatedIf duplicates remain: report as error with details.
</step>
<step name="commit">
Check planning config:
bash
COMMIT_PLANNING_DOCS=$(cat .planning/config.json 2>/dev/null | grep -o '"commit_docs"[[:space:]]*:[[:space:]]*[^,}]*' | grep -o 'true\|false' || echo "true")
git check-ignore -q .planning 2>/dev/null && COMMIT_PLANNING_DOCS=falseIf : Skip git operations.
COMMIT_PLANNING_DOCS=falseIf (default):
COMMIT_PLANNING_DOCS=truebash
git add .planning/phases/ .planning/ROADMAP.md .planning/STATE.md
git commit -m "$(cat <<'EOF'
chore: migrate phase directories to globally sequential numbering
EOF
)"<anti_patterns>
- Don't rename completed phase internal files (wildcard lookup handles them, reduces risk)
- Don't modify historical blocks in ROADMAP.md (archived records)
<details> - Don't rename one directory at a time without temp pass (causes mid-rename collisions)
- Don't ask per-directory confirmation (impractical for 30+ phases)
- Don't run migration on projects with no collisions (detect and exit early) </anti_patterns>
<success_criteria>
- Duplicate phase prefixes detected across all state directories
- Chronology built from ROADMAP.md in document order
- Migration plan displayed with full rename table
- User confirmation obtained before any renames
- Two-pass rename executed without collisions
- Active/pending internal files renamed to match new prefix
- Completed phase internal files left unchanged
- ROADMAP.md current milestone phase numbers updated
- STATE.md current position updated
- Historical blocks unchanged
<details> - Verification confirms no remaining collisions
- Changes committed (if commit_docs enabled)
- Idempotent: re-run on clean project exits with "no collisions" </success_criteria>
while IFS= read -r line; do
name=$(echo "$line" | grep -oE 'Phase [0-9.]+: .+' | sed 's/Phase [0-9.]*: //' | sed 's/**$//' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
if [ -n "$name" ]; then
CHRONOLOGY="${CHRONOLOGY}${GLOBAL_SEQ} ${name}\n"
GLOBAL_SEQ=$((GLOBAL_SEQ + 1))
fi
done < <(grep -E 'Phase [0-9.]+:' .planning/ROADMAP.md)
小数形式的阶段(2.1、2.2)在其父阶段之后获得连续的整数编号。文档顺序决定编号序列。
显示:`Chronology ([N] phases): 00 → foundation, 01 → api-endpoints, ...`
</step>
<step name="map_directories_to_phases">
将时间线中的每个阶段名称与其现有目录匹配。在`active/`、`pending/`、`completed/`目录及扁平目录(回退)中搜索。
对于每个时间线条目`{seq} {name}`:
1. 在所有状态目录中查找短名称匹配`{name}`的目录
2. 如果存在多个匹配项,使用其数字前缀与原里程碑本地编号一致的目录
3. 构建映射关系:`STATE/OLD_DIR → STATE/NEW_PREFIX-SLUG`
从每个目录名称中去除数字前缀以获取短名称,与时间线中的名称进行比较。构建`MAPPING`为换行分隔的条目:`STATE/OLD_DIR → PADDED-SLUG`。
显示完整的映射表。
</step>
<step name="present_migration_plan">
显示重命名表:
Migration Plan:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
completed/01-foundation → completed/00-foundation
completed/02-api-endpoints → completed/01-api-endpoints
completed/01-setup → completed/02-setup
...
active/01-current-work → active/15-current-work
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total: [N] directories to rename
使用AskUserQuestion:
- header: "Migration"
- question: "Rename [N] directories to globally sequential numbers?"
- options:
- "Proceed" — Execute all renames
- "Cancel" — Abort migration
如果用户选择取消,输出“Migration cancelled.”并退出。
</step>
<step name="execute_renames">
采用两步法重命名,避免重命名过程中出现冲突(此模式源自`kata-move-phase`):
**第一步:**将所有目录重命名为临时名称:`mv OLD tmp-{seq}-{slug}`
**第二步:**将临时名称重命名为最终名称:`mv tmp-{seq}-{slug} {padded}-{slug}`
在第二步中,对于活跃/待处理阶段,还需重命名内部文件(`*-PLAN.md`、`*-RESEARCH.md`、`*-CONTEXT.md`、`*-SUMMARY.md`),将旧的阶段前缀替换为新的补零前缀:`sed "s/^[0-9.]*-/${PADDED}-/"`。
已完成阶段的内部文件保持不变。通配符查找(`*-PLAN.md`)可处理这些文件。
显示:◆ Pass 1: Renamed [N] directories to temporary names
◆ Pass 2: Renamed [N] directories to final names
◆ Active/pending internal files updated: [count]
</step>
<step name="update_documentation">
**更新ROADMAP.md中当前里程碑的阶段编号:**
对于当前(未归档)的里程碑区域,将`#### Phase N:`标题更新为使用新的全局编号。将阶段名称与时间线匹配以确定正确的新编号。
**更新STATE.md中的当前位置:**
更新当前阶段引用为新的全局编号。查找引用活跃阶段的行并更新其编号。
**请勿修改ROADMAP.md中的历史`<details>`块**,它们是归档记录。`.planning/milestones/`中的里程碑归档文件为权威来源。
显示:
◆ Updated ROADMAP.md current milestone phase numbers
◆ Updated STATE.md current position
</step>
<step name="verify">
重新运行冲突检测:
```bash
DUPES=$(for state in active pending completed; do
ls .planning/phases/${state}/ 2>/dev/null
done | grep -oE '^[0-9]+' | sort -n | uniq -d)
FLAT_DUPES=$(ls .planning/phases/ 2>/dev/null | grep -E '^[0-9]' | grep -oE '^[0-9]+' | sort -n | uniq -d)
ALL_DUPES=$(echo -e "${DUPES}\n${FLAT_DUPES}" | sort -nu | grep -v '^$')如果无冲突:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Kata ► MIGRATION COMPLETE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ [N] directories renamed to globally sequential numbers
✓ No duplicate prefixes remain
✓ ROADMAP.md and STATE.md updated如果仍存在重复项:报告错误及详细信息。
</step>
<step name="commit">
检查规划配置:
bash
COMMIT_PLANNING_DOCS=$(cat .planning/config.json 2>/dev/null | grep -o '"commit_docs"[[:space:]]*:[[:space:]]*[^,}]*' | grep -o 'true\|false' || echo "true")
git check-ignore -q .planning 2>/dev/null && COMMIT_PLANNING_DOCS=false**如果:**跳过git操作。
COMMIT_PLANNING_DOCS=false如果(默认设置):
COMMIT_PLANNING_DOCS=truebash
git add .planning/phases/ .planning/ROADMAP.md .planning/STATE.md
git commit -m "$(cat <<'EOF'
chore: migrate phase directories to globally sequential numbering
EOF
)"<anti_patterns>
- 请勿重命名已完成阶段的内部文件(通配符查找可处理这些文件,降低风险)
- 请勿修改ROADMAP.md中的历史块(它们是归档记录)
<details> - 请勿不使用临时步骤就逐个重命名目录(会导致重命名过程中出现冲突)
- 请勿请求逐个目录的确认(对于30+个阶段来说不切实际)
- 请勿在无冲突的项目上运行迁移(检测到无冲突后提前退出) </anti_patterns>
<success_criteria>
- 检测到所有状态目录中的重复阶段前缀
- 按文档顺序从ROADMAP.md构建时间线
- 显示包含完整重命名表的迁移计划
- 在执行任何重命名前获得用户确认
- 执行两步法重命名,无冲突
- 活跃/待处理阶段的内部文件已重命名以匹配新前缀
- 已完成阶段的内部文件保持不变
- ROADMAP.md中当前里程碑的阶段编号已更新
- STATE.md中的当前位置已更新
- 历史块未被修改
<details> - 验证确认无剩余冲突
- 变更已提交(如果commit_docs已启用)
- 幂等性:在无冲突的项目上重新运行时,输出“no collisions”并退出 </success_criteria>