Skip to content

Commit d7e8433

Browse files
markhazletonclaude
andcommitted
fix: migrate specs/ to .documentation/specs/ and defer migration until after template install
- Migration script now moves specs/ -> .documentation/specs/ (root and .specify/specs/) - Migration step in upgrade() deferred until after init() installs templates, so migration scripts are available when needed - needs_migration() now detects root-level specs/ as requiring migration - Fix Next Steps text: ls specs/ -> ls .documentation/specs/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7717901 commit d7e8433

3 files changed

Lines changed: 62 additions & 21 deletions

File tree

.documentation/scripts/migrate-to-documentation.ps1

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,16 @@ if ((Test-Path "templates") -and -not (Test-Path ".documentation\templates")) {
191191
$oldStructuresFound = $true
192192
}
193193

194+
if ((Test-Path "specs") -and -not (Test-Path ".documentation\specs")) {
195+
Print-Status "Found specs/ directory"
196+
$structuresToMigrate += "specs"
197+
$oldStructuresFound = $true
198+
}
199+
194200
if (-not $oldStructuresFound) {
195201
Write-Host ""
196202
Print-Error "No old structure found to migrate."
197-
Write-Host "Looking for: .specify/, memory/, scripts/, or templates/"
203+
Write-Host "Looking for: .specify/, memory/, scripts/, templates/, or specs/"
198204
Write-Host ""
199205
exit 0
200206
}
@@ -219,7 +225,7 @@ foreach ($struct in $structuresToMigrate) {
219225
}
220226
Write-Host " 5. Update .gitignore if needed"
221227
Write-Host ""
222-
Write-ColorOutput "Your specs/ directory will NOT be touched - it's completely safe!" "Green"
228+
Write-ColorOutput "Your specs/ directory will be moved to .documentation/specs/" "Green"
223229
Write-Host ""
224230

225231
if (-not $DryRun) {
@@ -247,6 +253,9 @@ if ($DryRun) {
247253

248254
New-Item -ItemType Directory -Path ".documentation\templates" -Force | Out-Null
249255
Print-Status "Created .documentation\templates\"
256+
257+
New-Item -ItemType Directory -Path ".documentation\specs" -Force | Out-Null
258+
Print-Status "Created .documentation\specs\"
250259
}
251260

252261
Write-Host ""
@@ -341,6 +350,20 @@ if (Test-Path ".specify") {
341350
Print-Status "Copied .specify\templates\ to .documentation\templates\"
342351
}
343352

353+
if (Test-Path ".specify\specs") {
354+
Get-ChildItem ".specify\specs" -Recurse | ForEach-Object {
355+
$target = $_.FullName.Replace(".specify\specs", ".documentation\specs")
356+
if ($_.PSIsContainer -eq $false) {
357+
$targetDir = Split-Path $target -Parent
358+
if (-not (Test-Path $targetDir)) {
359+
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
360+
}
361+
Copy-Item $_.FullName -Destination $target -Force
362+
}
363+
}
364+
Print-Status "Copied .specify\specs\ to .documentation\specs\"
365+
}
366+
344367
# Copy any other files in .specify root
345368
Get-ChildItem ".specify" -File | ForEach-Object {
346369
Copy-Item $_.FullName -Destination ".documentation\" -Force
@@ -357,6 +380,7 @@ if (Test-Path ".specify") {
357380
Copy-Directory "memory" ".documentation\memory" "memory\"
358381
Copy-Directory "scripts" ".documentation\scripts" "scripts\"
359382
Copy-Directory "templates" ".documentation\templates" "templates\"
383+
Copy-Directory "specs" ".documentation\specs" "specs\"
360384

361385
Write-Host ""
362386
Write-ColorOutput "Step 3: Updating path references in files" "Blue"

.documentation/scripts/migrate-to-documentation.sh

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,16 @@ if [ -d "templates" ] && [ ! -d ".documentation/templates" ]; then
199199
OLD_STRUCTURES_FOUND=true
200200
fi
201201

202+
if [ -d "specs" ] && [ ! -d ".documentation/specs" ]; then
203+
print_status "Found specs/ directory"
204+
STRUCTURES_TO_MIGRATE+=("specs")
205+
OLD_STRUCTURES_FOUND=true
206+
fi
207+
202208
if [ "$OLD_STRUCTURES_FOUND" = false ]; then
203209
echo ""
204210
print_error "No old structure found to migrate."
205-
echo "Looking for: .specify/, memory/, scripts/, or templates/"
211+
echo "Looking for: .specify/, memory/, scripts/, templates/, or specs/"
206212
echo ""
207213
exit 0
208214
fi
@@ -227,7 +233,7 @@ for struct in "${STRUCTURES_TO_MIGRATE[@]}"; do
227233
done
228234
echo " 5. Update .gitignore if needed"
229235
echo ""
230-
echo -e "${GREEN}Your specs/ directory will NOT be touched - it's completely safe!${NC}"
236+
echo -e "${GREEN}Your specs/ directory will be moved to .documentation/specs/${NC}"
231237
echo ""
232238

233239
if [ "$DRY_RUN" = false ]; then
@@ -307,6 +313,11 @@ if [ -d ".specify" ]; then
307313
cp -r .specify/templates/* .documentation/templates/ 2>/dev/null || true
308314
print_status "Copied .specify/templates/ to .documentation/templates/"
309315
fi
316+
if [ -d ".specify/specs" ]; then
317+
mkdir -p .documentation/specs
318+
cp -r .specify/specs/* .documentation/specs/ 2>/dev/null || true
319+
print_status "Copied .specify/specs/ to .documentation/specs/"
320+
fi
310321
# Copy any other files in .specify root
311322
find .specify -maxdepth 1 -type f -exec cp {} .documentation/ \; 2>/dev/null || true
312323
print_status "Copied .specify/ root files to .documentation/"
@@ -321,6 +332,7 @@ fi
321332
copy_dir "memory" ".documentation/memory" "memory/"
322333
copy_dir "scripts" ".documentation/scripts" "scripts/"
323334
copy_dir "templates" ".documentation/templates" "templates/"
335+
copy_dir "specs" ".documentation/specs" "specs/"
324336

325337
echo ""
326338
echo -e "${BLUE}Step 3: Updating path references in files${NC}"

src/specify_cli/__init__.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,7 @@ def needs_migration() -> bool:
13091309
Path("memory") if not Path(".documentation/memory").exists() else None,
13101310
Path("scripts") if not Path(".documentation/scripts").exists() else None,
13111311
Path("templates") if not Path(".documentation/templates").exists() else None,
1312+
Path("specs") if not Path(".documentation/specs").exists() else None,
13121313
]
13131314
# Filter out None values
13141315
old_paths = [p for p in old_paths if p is not None]
@@ -1527,29 +1528,24 @@ def upgrade(
15271528
agent_name = AGENT_CONFIG[ai_assistant]["name"]
15281529
console.print(f"[green]✓[/green] Using AI assistant: [cyan]{agent_name}[/cyan] ({ai_assistant})\n")
15291530

1530-
# Step 4: Check for old structure migration
1531+
# Step 4: Check for old structure migration (deferred — runs after templates are installed)
1532+
migration_needed = False
1533+
migration_confirmed = False
15311534
if not skip_migration:
15321535
console.print("[cyan]→[/cyan] Checking for old structure...")
15331536
if needs_migration():
1537+
migration_needed = True
15341538
console.print("[yellow]⚠[/yellow] Old structure detected (.specify/, memory/, scripts/, or templates/)")
1535-
console.print("[dim]Migration to .documentation/ structure is recommended[/dim]")
1539+
console.print("[dim]Migration to .documentation/ structure will run after templates are installed[/dim]")
15361540

15371541
if dry_run:
1538-
console.print("[cyan]Would run migration script in actual upgrade[/cyan]\n")
1542+
console.print("[cyan]Would run migration after templates are installed[/cyan]\n")
1543+
elif force:
1544+
console.print("[cyan]Migration will run automatically after templates are installed (--force)...[/cyan]\n")
1545+
migration_confirmed = True
15391546
else:
1540-
if force:
1541-
console.print("[cyan]Running migration automatically (--force specified)...[/cyan]")
1542-
run_migration = True
1543-
else:
1544-
run_migration = typer.confirm("Run migration now?", default=True)
1545-
1546-
if run_migration:
1547-
success = run_migration_script()
1548-
if success:
1549-
console.print("[green]✓[/green] Migration completed\n")
1550-
else:
1551-
console.print("[yellow]⚠[/yellow] Migration had issues, but continuing...\n")
1552-
else:
1547+
migration_confirmed = typer.confirm("Run migration after templates are installed?", default=True)
1548+
if not migration_confirmed:
15531549
console.print("[yellow]Skipping migration - you can run it later[/yellow]")
15541550
console.print("[dim]See .documentation/migration-guide.md for manual steps[/dim]\n")
15551551
else:
@@ -1606,6 +1602,15 @@ def upgrade(
16061602
console.print(f"\n[red]✗ Upgrade failed:[/red] {e}")
16071603
raise typer.Exit(1)
16081604

1605+
# Step 7.5: Run migration now that templates (including migration scripts) are installed
1606+
if migration_needed and migration_confirmed:
1607+
console.print("[cyan]→[/cyan] Running migration to .documentation/ structure...")
1608+
success = run_migration_script()
1609+
if success:
1610+
console.print("[green]✓[/green] Migration completed\n")
1611+
else:
1612+
console.print("[yellow]⚠[/yellow] Migration had issues. See .documentation/migration-guide.md for manual steps.\n")
1613+
16091614
# Step 8: Post-upgrade guidance
16101615
console.print("\n" + "="*60)
16111616
console.print("[bold green]✓ Upgrade Complete![/bold green]")
@@ -1620,7 +1625,7 @@ def upgrade(
16201625
console.print("[bold]Next steps:[/bold]")
16211626
console.print(" 1. Review changes: [cyan]git status[/cyan] and [cyan]git diff[/cyan]")
16221627
console.print(" 2. Test slash commands in your AI assistant (e.g., [cyan]/speckit.constitution[/cyan])")
1623-
console.print(" 3. Verify your specs are intact: [cyan]ls specs/[/cyan]")
1628+
console.print(" 3. Verify your specs are intact: [cyan]ls .documentation/specs/[/cyan]")
16241629
console.print(" 4. If everything looks good, commit:")
16251630
console.print(" [cyan]git add -A[/cyan]")
16261631
console.print(" [cyan]git commit -m 'chore: upgrade to latest spec-kit version'[/cyan]")

0 commit comments

Comments
 (0)