@@ -621,6 +621,31 @@ def _locate_bundled_extension(extension_id: str) -> Path | None:
621621 return None
622622
623623
624+ def _locate_bundled_workflow (workflow_id : str ) -> Path | None :
625+ """Return the path to a bundled workflow directory, or None.
626+
627+ Checks the wheel's core_pack first, then falls back to the
628+ source-checkout ``workflows/<id>/`` directory.
629+ """
630+ import re as _re
631+ if not _re .match (r'^[a-z0-9-]+$' , workflow_id ):
632+ return None
633+
634+ core = _locate_core_pack ()
635+ if core is not None :
636+ candidate = core / "workflows" / workflow_id
637+ if (candidate / "workflow.yml" ).is_file ():
638+ return candidate
639+
640+ # Source-checkout / editable install: look relative to repo root
641+ repo_root = Path (__file__ ).parent .parent .parent
642+ candidate = repo_root / "workflows" / workflow_id
643+ if (candidate / "workflow.yml" ).is_file ():
644+ return candidate
645+
646+ return None
647+
648+
624649def _install_shared_infra (
625650 project_path : Path ,
626651 script_type : str ,
@@ -1134,6 +1159,7 @@ def init(
11341159 ("chmod" , "Ensure scripts executable" ),
11351160 ("constitution" , "Constitution setup" ),
11361161 ("git" , "Install git extension" ),
1162+ ("workflow" , "Install bundled workflow" ),
11371163 ("final" , "Finalize" ),
11381164 ]:
11391165 tracker .add (key , label )
@@ -1237,6 +1263,37 @@ def init(
12371263 else :
12381264 tracker .skip ("git" , "--no-git flag" )
12391265
1266+ # Install bundled speckit workflow
1267+ try :
1268+ bundled_wf = _locate_bundled_workflow ("speckit" )
1269+ if bundled_wf :
1270+ from .workflows .catalog import WorkflowRegistry
1271+ from .workflows .engine import WorkflowDefinition
1272+ wf_registry = WorkflowRegistry (project_path )
1273+ if wf_registry .is_installed ("speckit" ):
1274+ tracker .complete ("workflow" , "already installed" )
1275+ else :
1276+ import shutil as _shutil
1277+ dest_wf = project_path / ".specify" / "workflows" / "speckit"
1278+ dest_wf .mkdir (parents = True , exist_ok = True )
1279+ _shutil .copy2 (
1280+ bundled_wf / "workflow.yml" ,
1281+ dest_wf / "workflow.yml" ,
1282+ )
1283+ definition = WorkflowDefinition .from_yaml (dest_wf / "workflow.yml" )
1284+ wf_registry .add ("speckit" , {
1285+ "name" : definition .name ,
1286+ "version" : definition .version ,
1287+ "description" : definition .description ,
1288+ "source" : "bundled" ,
1289+ })
1290+ tracker .complete ("workflow" , "speckit installed" )
1291+ else :
1292+ tracker .skip ("workflow" , "bundled workflow not found" )
1293+ except Exception as wf_err :
1294+ sanitized_wf = str (wf_err ).replace ('\n ' , ' ' ).strip ()
1295+ tracker .error ("workflow" , f"install failed: { sanitized_wf [:120 ]} " )
1296+
12401297 # Fix permissions after all installs (scripts + extensions)
12411298 ensure_executable_scripts (project_path , tracker = tracker )
12421299
0 commit comments