@@ -135,3 +135,45 @@ function Test-DirHasFiles {
135135 }
136136}
137137
138+ # Resolve a template name to a file path using the priority stack:
139+ # 1. .specify/templates/overrides/
140+ # 2. .specify/templates/packs/<pack-id>/templates/
141+ # 3. .specify/extensions/<ext-id>/templates/
142+ # 4. .specify/templates/ (core)
143+ function Resolve-Template {
144+ param (
145+ [Parameter (Mandatory = $true )][string ]$TemplateName ,
146+ [Parameter (Mandatory = $true )][string ]$RepoRoot
147+ )
148+
149+ $base = Join-Path $RepoRoot ' .specify/templates'
150+
151+ # Priority 1: Project overrides
152+ $override = Join-Path $base " overrides/$TemplateName .md"
153+ if (Test-Path $override ) { return $override }
154+
155+ # Priority 2: Installed packs (by directory order)
156+ $packsDir = Join-Path $base ' packs'
157+ if (Test-Path $packsDir ) {
158+ foreach ($pack in Get-ChildItem - Path $packsDir - Directory - ErrorAction SilentlyContinue) {
159+ $candidate = Join-Path $pack.FullName " templates/$TemplateName .md"
160+ if (Test-Path $candidate ) { return $candidate }
161+ }
162+ }
163+
164+ # Priority 3: Extension-provided templates
165+ $extDir = Join-Path $RepoRoot ' .specify/extensions'
166+ if (Test-Path $extDir ) {
167+ foreach ($ext in Get-ChildItem - Path $extDir - Directory - ErrorAction SilentlyContinue) {
168+ $candidate = Join-Path $ext.FullName " templates/$TemplateName .md"
169+ if (Test-Path $candidate ) { return $candidate }
170+ }
171+ }
172+
173+ # Priority 4: Core templates
174+ $core = Join-Path $base " $TemplateName .md"
175+ if (Test-Path $core ) { return $core }
176+
177+ return $null
178+ }
179+
0 commit comments