Projects with multiple milestones may have colliding prefixes (e.g., 01-foundation from v0.1.0 and 01-setup from v0.2.0 both in completed/). This causes find ... -name "01-*" | head -1 to return the wrong directory.
Scan all phase directories for duplicate numeric prefixes:
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)
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.
Read ROADMAP.md and STATE.md. Confirm project is active:
[ -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 <details> block contains phase lists. Parse phases in document order.
Current milestone: Parse #### Phase N: headings from the active section.
Build a chronology array. Each entry: {global_seq} {phase_name} where phase_name is the slug from the phase heading (e.g., "foundation", "api-endpoints").
GLOBAL_SEQ=0
CHRONOLOGY=""
# Parse all "Phase N: name" lines from ROADMAP.md in document order.
# Completed milestones appear in <details> blocks; current milestone uses #### headings.
# 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, ...
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}:
- Find directories whose slug matches
{name}across all states - If multiple matches, use the one whose numeric prefix matches the original milestone-local number
- 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.
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."
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]
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
Re-run collision detection:
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 updated
If duplicates remain: report as error with details.
Check planning config:
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
If COMMIT_PLANNING_DOCS=false: Skip git operations.
If COMMIT_PLANNING_DOCS=true (default):
git add .planning/phases/ .planning/ROADMAP.md .planning/STATE.md
git commit -m "$(cat <<'EOF'
chore: migrate phase directories to globally sequential numbering
EOF
)"