specfact-cli 0.42.4__tar.gz → 0.42.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/PKG-INFO +1 -1
  2. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/pyproject.toml +1 -1
  3. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/__init__.py +1 -1
  4. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/__init__.py +1 -1
  5. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/cli.py +17 -0
  6. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/init/module-package.yaml +3 -3
  7. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/init/src/commands.py +126 -37
  8. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/ide_setup.py +418 -30
  9. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/startup_checks.py +16 -2
  10. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/.gitignore +0 -0
  11. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/LICENSE +0 -0
  12. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/README.md +0 -0
  13. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/keys/README.md +0 -0
  14. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/keys/module-signing-public.pem +0 -0
  15. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/mappings/node-async.yaml +0 -0
  16. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/mappings/python-async.yaml +0 -0
  17. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/mappings/speckit-default.yaml +0 -0
  18. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/shared/cli-enforcement.md +0 -0
  19. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.01-import.md +0 -0
  20. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.02-plan.md +0 -0
  21. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.03-review.md +0 -0
  22. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.04-sdd.md +0 -0
  23. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.05-enforce.md +0 -0
  24. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.06-sync.md +0 -0
  25. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.07-contracts.md +0 -0
  26. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.compare.md +0 -0
  27. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/prompts/specfact.validate.md +0 -0
  28. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/schemas/deviation.schema.json +0 -0
  29. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/schemas/plan.schema.json +0 -0
  30. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/schemas/protocol.schema.json +0 -0
  31. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/github-action.yml.j2 +0 -0
  32. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/persona/architect.md.j2 +0 -0
  33. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/persona/developer.md.j2 +0 -0
  34. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/persona/product-owner.md.j2 +0 -0
  35. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/plan.bundle.yaml.j2 +0 -0
  36. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/policies/kanban.yaml +0 -0
  37. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/policies/mixed.yaml +0 -0
  38. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/policies/safe.yaml +0 -0
  39. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/policies/scrum.yaml +0 -0
  40. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/pr-template.md.j2 +0 -0
  41. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/protocol.yaml.j2 +0 -0
  42. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/resources/templates/telemetry.yaml.example +0 -0
  43. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/__main__.py +0 -0
  44. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/__init__.py +0 -0
  45. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/ado.py +0 -0
  46. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/backlog_base.py +0 -0
  47. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/base.py +0 -0
  48. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/github.py +0 -0
  49. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/openspec.py +0 -0
  50. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/openspec_parser.py +0 -0
  51. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/registry.py +0 -0
  52. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/adapters/speckit.py +0 -0
  53. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/__init__.py +0 -0
  54. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/analyze_agent.py +0 -0
  55. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/base.py +0 -0
  56. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/plan_agent.py +0 -0
  57. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/registry.py +0 -0
  58. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/agents/sync_agent.py +0 -0
  59. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/__init__.py +0 -0
  60. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
  61. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
  62. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
  63. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
  64. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
  65. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
  66. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
  67. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
  68. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
  69. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/__init__.py +0 -0
  70. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/adapters/__init__.py +0 -0
  71. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/adapters/base.py +0 -0
  72. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/converter.py +0 -0
  73. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/filters.py +0 -0
  74. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
  75. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/mappers/ado_mapper.py +0 -0
  76. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/mappers/base.py +0 -0
  77. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
  78. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
  79. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/__init__.py +0 -0
  80. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/_bundle_shim.py +0 -0
  81. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/analyze.py +0 -0
  82. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/contract_cmd.py +0 -0
  83. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/drift.py +0 -0
  84. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/enforce.py +0 -0
  85. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/generate.py +0 -0
  86. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/import_cmd.py +0 -0
  87. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/init.py +0 -0
  88. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/migrate.py +0 -0
  89. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/plan.py +0 -0
  90. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/project_cmd.py +0 -0
  91. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/repro.py +0 -0
  92. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/sdd.py +0 -0
  93. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/spec.py +0 -0
  94. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/sync.py +0 -0
  95. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/update.py +0 -0
  96. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/commands/validate.py +0 -0
  97. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/__init__.py +0 -0
  98. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/bundle_factory.py +0 -0
  99. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/logger_setup.py +0 -0
  100. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/logging_utils.py +0 -0
  101. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/text_utils.py +0 -0
  102. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/common/utils.py +0 -0
  103. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/comparators/__init__.py +0 -0
  104. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/comparators/plan_comparator.py +0 -0
  105. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/contracts/__init__.py +0 -0
  106. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/contracts/crosshair_props.py +0 -0
  107. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/contracts/module_interface.py +0 -0
  108. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
  109. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
  110. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/__init__.py +0 -0
  111. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/contract_generator.py +0 -0
  112. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/openapi_extractor.py +0 -0
  113. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/persona_exporter.py +0 -0
  114. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/plan_generator.py +0 -0
  115. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/protocol_generator.py +0 -0
  116. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/report_generator.py +0 -0
  117. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/task_generator.py +0 -0
  118. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/test_to_openapi.py +0 -0
  119. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/generators/workflow_generator.py +0 -0
  120. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/__init__.py +0 -0
  121. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/codebase_group.py +0 -0
  122. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/govern_group.py +0 -0
  123. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/member_group.py +0 -0
  124. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/project_group.py +0 -0
  125. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/groups/spec_group.py +0 -0
  126. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/importers/__init__.py +0 -0
  127. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/importers/speckit_converter.py +0 -0
  128. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/importers/speckit_scanner.py +0 -0
  129. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/integrations/__init__.py +0 -0
  130. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/integrations/specmatic.py +0 -0
  131. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/merge/__init__.py +0 -0
  132. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/merge/resolver.py +0 -0
  133. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/migrations/__init__.py +0 -0
  134. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/migrations/plan_migrator.py +0 -0
  135. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/__init__.py +0 -0
  136. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/backlog_item.py +0 -0
  137. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/bridge.py +0 -0
  138. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/capabilities.py +0 -0
  139. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/change.py +0 -0
  140. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/contract.py +0 -0
  141. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/deviation.py +0 -0
  142. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/dor_config.py +0 -0
  143. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/enforcement.py +0 -0
  144. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/module_package.py +0 -0
  145. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/persona_template.py +0 -0
  146. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/plan.py +0 -0
  147. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/project.py +0 -0
  148. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/protocol.py +0 -0
  149. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/quality.py +0 -0
  150. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/sdd.py +0 -0
  151. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/source_tracking.py +0 -0
  152. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/task.py +0 -0
  153. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/models/validation.py +0 -0
  154. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modes/__init__.py +0 -0
  155. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modes/detector.py +0 -0
  156. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modes/router.py +0 -0
  157. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/__init__.py +0 -0
  158. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/_bundle_import.py +0 -0
  159. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/init/src/__init__.py +0 -0
  160. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/init/src/app.py +0 -0
  161. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/init/src/first_run_selection.py +0 -0
  162. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/module_io_shim.py +0 -0
  163. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/module_registry/module-package.yaml +0 -0
  164. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/module_registry/src/__init__.py +0 -0
  165. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/module_registry/src/app.py +0 -0
  166. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/module_registry/src/commands.py +0 -0
  167. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/upgrade/module-package.yaml +0 -0
  168. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/upgrade/src/__init__.py +0 -0
  169. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/upgrade/src/app.py +0 -0
  170. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/modules/upgrade/src/commands.py +0 -0
  171. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/parsers/__init__.py +0 -0
  172. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/parsers/persona_importer.py +0 -0
  173. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/__init__.py +0 -0
  174. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/alias_manager.py +0 -0
  175. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/bootstrap.py +0 -0
  176. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/bridge_registry.py +0 -0
  177. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/crypto_validator.py +0 -0
  178. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/custom_registries.py +0 -0
  179. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/dependency_resolver.py +0 -0
  180. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/extension_registry.py +0 -0
  181. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/help_cache.py +0 -0
  182. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/marketplace_client.py +0 -0
  183. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/metadata.py +0 -0
  184. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_discovery.py +0 -0
  185. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_grouping.py +0 -0
  186. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_installer.py +0 -0
  187. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_lifecycle.py +0 -0
  188. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_packages.py +0 -0
  189. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_security.py +0 -0
  190. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/module_state.py +0 -0
  191. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/registry/registry.py +0 -0
  192. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/resources/semgrep/async.yml +0 -0
  193. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
  194. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
  195. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/runtime.py +0 -0
  196. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/__init__.py +0 -0
  197. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_probe.py +0 -0
  198. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync.py +0 -0
  199. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_openspec_md_parse.py +0 -0
  200. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_requirement_from_proposal.py +0 -0
  201. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_requirement_helpers.py +0 -0
  202. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_tasks_from_proposal.py +0 -0
  203. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_what_changes_format.py +0 -0
  204. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_sync_write_openspec_from_proposal.py +0 -0
  205. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/bridge_watch.py +0 -0
  206. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/change_detector.py +0 -0
  207. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/code_to_spec.py +0 -0
  208. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/drift_detector.py +0 -0
  209. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/repository_sync.py +0 -0
  210. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/spec_to_code.py +0 -0
  211. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/spec_to_tests.py +0 -0
  212. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/watcher.py +0 -0
  213. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
  214. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/telemetry.py +0 -0
  215. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/__init__.py +0 -0
  216. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -0
  217. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -0
  218. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -0
  219. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -0
  220. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -0
  221. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -0
  222. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -0
  223. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/registry.py +0 -0
  224. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/templates/specification_templates.py +0 -0
  225. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/__init__.py +0 -0
  226. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
  227. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/auth_tokens.py +0 -0
  228. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/bundle_converters.py +0 -0
  229. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/bundle_loader.py +0 -0
  230. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/code_change_detector.py +0 -0
  231. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/console.py +0 -0
  232. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/content_sanitizer.py +0 -0
  233. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/context_detection.py +0 -0
  234. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/contract_predicates.py +0 -0
  235. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/enrichment_context.py +0 -0
  236. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/enrichment_parser.py +0 -0
  237. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/env_manager.py +0 -0
  238. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/feature_keys.py +0 -0
  239. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/git.py +0 -0
  240. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/github_annotations.py +0 -0
  241. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/icontract_helpers.py +0 -0
  242. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/incremental_check.py +0 -0
  243. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/metadata.py +0 -0
  244. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/optional_deps.py +0 -0
  245. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/performance.py +0 -0
  246. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/persona_ownership.py +0 -0
  247. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/progress.py +0 -0
  248. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
  249. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/prompts.py +0 -0
  250. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/sdd_discovery.py +0 -0
  251. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/source_scanner.py +0 -0
  252. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/structure.py +0 -0
  253. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/structured_io.py +0 -0
  254. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/suggestions.py +0 -0
  255. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/terminal.py +0 -0
  256. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/utils/yaml_utils.py +0 -0
  257. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validation/__init__.py +0 -0
  258. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validation/command_audit.py +0 -0
  259. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/__init__.py +0 -0
  260. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/agile_validation.py +0 -0
  261. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
  262. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/cli_first_validator.py +0 -0
  263. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/contract_validator.py +0 -0
  264. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/fsm.py +0 -0
  265. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/repro_checker.py +0 -0
  266. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/schema.py +0 -0
  267. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
  268. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
  269. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
  270. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
  271. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/dependency_installer.py +0 -0
  272. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
  273. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
  274. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
  275. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
  276. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
  277. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
  278. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
  279. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
  280. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/models.py +0 -0
  281. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/orchestrator.py +0 -0
  282. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
  283. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
  284. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/versioning/__init__.py +0 -0
  285. {specfact_cli-0.42.4 → specfact_cli-0.42.5}/src/specfact_cli/versioning/analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specfact-cli
3
- Version: 0.42.4
3
+ Version: 0.42.5
4
4
  Summary: The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases.
5
5
  Project-URL: Homepage, https://github.com/nold-ai/specfact-cli
6
6
  Project-URL: Repository, https://github.com/nold-ai/specfact-cli.git
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "specfact-cli"
7
- version = "0.42.4"
7
+ version = "0.42.5"
8
8
  description = "The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -3,4 +3,4 @@ SpecFact CLI - Spec→Contract→Sentinel tool for contract-driven development.
3
3
  """
4
4
 
5
5
  # Package version: keep in sync with pyproject.toml, setup.py, src/specfact_cli/__init__.py
6
- __version__ = "0.42.4"
6
+ __version__ = "0.42.5"
@@ -42,6 +42,6 @@ def _bootstrap_bundle_paths() -> None:
42
42
 
43
43
  _bootstrap_bundle_paths()
44
44
 
45
- __version__ = "0.42.4"
45
+ __version__ = "0.42.5"
46
46
 
47
47
  __all__ = ["__version__"]
@@ -653,6 +653,23 @@ for _name, _meta in _grouped_command_order(CommandRegistry.list_commands_for_hel
653
653
  app.add_typer(_make_lazy_typer(_name, _meta.help), name=_name, help=_meta.help)
654
654
 
655
655
 
656
+ @beartype
657
+ @require(lambda: isinstance(app, typer.Typer), "Root CLI app must be initialized")
658
+ @ensure(lambda result: result is None, "Must return None")
659
+ def rebuild_root_app_from_registry() -> None:
660
+ """Rebuild root Typer ``app`` from the current ``CommandRegistry``.
661
+
662
+ Call after ``register_builtin_commands()`` when tests clear and re-register the registry.
663
+ Otherwise ``get_command(app)`` still reflects lazy groups from ``cli`` import time while
664
+ ``CommandRegistry`` lists only the newly registered commands (breaks CI core-only installs).
665
+ """
666
+ app.registered_groups = []
667
+ if hasattr(app, "registered_commands"):
668
+ app.registered_commands = []
669
+ for _name, _meta in _grouped_command_order(CommandRegistry.list_commands_for_help()):
670
+ app.add_typer(_make_lazy_typer(_name, _meta.help), name=_name, help=_meta.help)
671
+
672
+
656
673
  _CLI_SKIP_OUTPUT_ARGS: frozenset[str] = frozenset(
657
674
  ("--help", "-h", "--version", "-v", "--show-completion", "--install-completion")
658
675
  )
@@ -1,5 +1,5 @@
1
1
  name: init
2
- version: 0.1.13
2
+ version: 0.1.17
3
3
  commands:
4
4
  - init
5
5
  category: core
@@ -17,5 +17,5 @@ publisher:
17
17
  description: Initialize SpecFact workspace and bootstrap local configuration.
18
18
  license: Apache-2.0
19
19
  integrity:
20
- checksum: sha256:4f929d90edc481d21cf1aa9c2782f569a34baf560e25d3317067f1c5951509e9
21
- signature: Sa60QWb6UaZRp40885CzkWMCGwT809/qQj1dnWIJcocwfLwT7Je+BR2STbGQv2RbTbTBBXmQ0Qwj/+AM3U0qAA==
20
+ checksum: sha256:589ec7f24e7d0129cf61ad972e9f505c744ae14bd84db32cc241bc5013834163
21
+ signature: 9hiFgBYZZwCTMBRDBgly07v5JejhDHWXyX3/tTkTYOjjtkFT7xjZs2Pyea7l1mt2dhUZ/Tet4bdDRXyeSNcYCg==
@@ -29,11 +29,18 @@ from specfact_cli.utils.contract_predicates import repo_path_exists, repo_path_i
29
29
  from specfact_cli.utils.env_manager import EnvManager, EnvManagerInfo, build_tool_command, detect_env_manager
30
30
  from specfact_cli.utils.ide_setup import (
31
31
  IDE_CONFIG,
32
+ PROMPT_SOURCE_CORE,
32
33
  _copy_template_files_to_ide,
33
34
  _discover_module_resource_dirs,
35
+ copy_prompts_by_source_to_ide,
36
+ count_outdated_ide_prompt_exports,
34
37
  detect_ide,
38
+ discover_prompt_sources_catalog,
35
39
  discover_prompt_template_files,
40
+ expected_ide_prompt_export_paths,
36
41
  find_package_resources_path,
42
+ load_ide_prompt_export_source_ids,
43
+ write_ide_prompt_export_state,
37
44
  )
38
45
 
39
46
 
@@ -65,8 +72,16 @@ is_first_run = first_run_selection.is_first_run
65
72
  ),
66
73
  "Must return copied files and optional settings path",
67
74
  )
68
- def copy_templates_to_ide(repo_path: Path, ide: str, force: bool = False) -> tuple[list[Path], Path | None]:
69
- """Compatibility wrapper that discovers prompt templates before copying them."""
75
+ def copy_templates_to_ide(
76
+ repo_path: Path,
77
+ ide: str,
78
+ force: bool = False,
79
+ *,
80
+ prompts_by_source: dict[str, list[Path]] | None = None,
81
+ ) -> tuple[list[Path], Path | None]:
82
+ """Discover prompt templates and copy them; use ``prompts_by_source`` for namespaced multi-source export."""
83
+ if prompts_by_source is not None:
84
+ return copy_prompts_by_source_to_ide(repo_path, ide, prompts_by_source, force)
70
85
  return _copy_template_files_to_ide(repo_path, ide, discover_prompt_template_files(repo_path), force)
71
86
 
72
87
 
@@ -307,36 +322,13 @@ def _resolve_templates_dir(repo_path: Path) -> Path | None:
307
322
  return find_package_resources_path("specfact_cli", "resources/prompts")
308
323
 
309
324
 
310
- def _expected_ide_prompt_basenames(repo_path: Path, format_type: str) -> list[str]:
311
- prompt_files = discover_prompt_template_files(repo_path)
312
- if format_type == "prompt.md":
313
- return [f"{path.stem}.prompt.md" for path in prompt_files]
314
- if format_type == "toml":
315
- return [f"{path.stem}.toml" for path in prompt_files]
316
- return [path.name for path in prompt_files]
317
-
318
-
319
- def _count_outdated_ide_prompts(ide_dir: Path, prompt_files: list[Path], format_type: str) -> int:
320
- outdated = 0
321
- for src in prompt_files:
322
- if format_type == "prompt.md":
323
- dest = ide_dir / f"{src.stem}.prompt.md"
324
- elif format_type == "toml":
325
- dest = ide_dir / f"{src.stem}.toml"
326
- else:
327
- dest = ide_dir / src.name
328
- if src.exists() and dest.exists() and dest.stat().st_mtime < src.stat().st_mtime:
329
- outdated += 1
330
- return outdated
331
-
332
-
333
325
  def _audit_prompt_installation(repo_path: Path) -> None:
334
326
  """Report prompt installation health and next steps without mutating files."""
335
327
  detected_ide = detect_ide("auto")
336
328
  config = IDE_CONFIG[detected_ide]
337
329
  ide_dir = repo_path / str(config["folder"])
338
- format_type = str(config["format"])
339
- expected_files = _expected_ide_prompt_basenames(repo_path, format_type)
330
+ prompt_subset = load_ide_prompt_export_source_ids(repo_path, detected_ide)
331
+ expected_paths = expected_ide_prompt_export_paths(repo_path, detected_ide, prompt_source_ids=prompt_subset)
340
332
 
341
333
  if not ide_dir.exists():
342
334
  console.print(
@@ -345,9 +337,12 @@ def _audit_prompt_installation(repo_path: Path) -> None:
345
337
  )
346
338
  return
347
339
 
348
- missing = [name for name in expected_files if not (ide_dir / name).exists()]
349
- prompt_files = discover_prompt_template_files(repo_path)
350
- outdated = _count_outdated_ide_prompts(ide_dir, prompt_files, format_type) if prompt_files else 0
340
+ missing = [p for p in expected_paths if not p.exists()]
341
+ outdated = (
342
+ count_outdated_ide_prompt_exports(repo_path, detected_ide, prompt_source_ids=prompt_subset)
343
+ if expected_paths
344
+ else 0
345
+ )
351
346
 
352
347
  if not missing and outdated == 0:
353
348
  console.print(f"[green]Prompt status:[/green] {detected_ide} prompts are present and up to date.")
@@ -359,6 +354,78 @@ def _audit_prompt_installation(repo_path: Path) -> None:
359
354
  console.print(f"[dim]Run: specfact init ide --ide {detected_ide}{' --force' if outdated > 0 else ''}[/dim]")
360
355
 
361
356
 
357
+ def _raise_missing_prompt_source(token: str, catalog: dict[str, list[Path]]) -> None:
358
+ avail = ", ".join(sorted(catalog.keys()))
359
+ console.print(f"[red]Error:[/red] Prompt source [bold]{token}[/bold] is not available or has no prompt resources.")
360
+ console.print(f"[dim]Available sources: {avail}[/dim]")
361
+ console.print(
362
+ "[dim]Install modules with [bold]specfact module install --scope user|project[/bold] "
363
+ "or seed bundled artifacts with [bold]specfact module init --scope user|project[/bold].[/dim]"
364
+ )
365
+ raise typer.Exit(1)
366
+
367
+
368
+ @beartype
369
+ def _parse_prompts_option_to_catalog(catalog: dict[str, list[Path]], prompts: str) -> dict[str, list[Path]]:
370
+ tokens = [t.strip() for t in prompts.split(",") if t.strip()]
371
+ if not tokens:
372
+ console.print("[red]Error:[/red] --prompts must list at least one source or `all`.")
373
+ raise typer.Exit(1)
374
+ if len(tokens) == 1 and tokens[0].lower() == "all":
375
+ return dict(catalog)
376
+ result: dict[str, list[Path]] = {}
377
+ for token in tokens:
378
+ key = PROMPT_SOURCE_CORE if token.lower() == "core" else token
379
+ if key not in catalog:
380
+ _raise_missing_prompt_source(token, catalog)
381
+ result[key] = catalog[key]
382
+ return result
383
+
384
+
385
+ def _select_prompt_sources_interactive(catalog: dict[str, list[Path]]) -> dict[str, list[Path]]:
386
+ keys = sorted(catalog.keys(), key=lambda k: (k != PROMPT_SOURCE_CORE, k))
387
+ if len(keys) <= 1:
388
+ return dict(catalog)
389
+ try:
390
+ import questionary # type: ignore[reportMissingImports]
391
+ except ImportError as e:
392
+ console.print(
393
+ "[red]Interactive prompt source selection requires 'questionary'. "
394
+ "Install with: pip install questionary[/red]"
395
+ )
396
+ raise typer.Exit(1) from e
397
+
398
+ console.print()
399
+ console.print(
400
+ Panel(
401
+ "[bold cyan]Prompt sources[/bold cyan]\n"
402
+ "Choose which prompt bundles to export (core and installed modules with prompt resources).",
403
+ border_style="cyan",
404
+ )
405
+ )
406
+ console.print("[dim]Controls: ↑↓ navigate • Space toggle • Enter confirm • Type to filter • Ctrl+C cancel[/dim]")
407
+
408
+ labels = [f"{k} ({len(catalog[k])} template(s))" for k in keys]
409
+ label_to_key = {labels[i]: keys[i] for i in range(len(keys))}
410
+
411
+ q = cast(Any, questionary)
412
+ choices_with_default = [q.Choice(title=lab, checked=True) for lab in labels]
413
+ selected = q.checkbox(
414
+ "Select prompt sources:",
415
+ choices=choices_with_default,
416
+ style=_questionary_style(),
417
+ ).ask()
418
+ if not selected:
419
+ console.print("[red]Error:[/red] Select at least one prompt source.")
420
+ raise typer.Exit(1)
421
+ chosen: dict[str, list[Path]] = {}
422
+ for label in selected:
423
+ sid = label_to_key.get(label)
424
+ if sid is not None:
425
+ chosen[sid] = catalog[sid]
426
+ return chosen
427
+
428
+
362
429
  def _select_ide_interactive(default_ide: str) -> str:
363
430
  """Select IDE interactively with up/down controls."""
364
431
  try:
@@ -561,8 +628,16 @@ def init_ide(
561
628
  "--ide",
562
629
  help="IDE type (cursor, vscode, copilot, claude, gemini, qwen, opencode, windsurf, kilocode, auggie, roo, codebuddy, amp, q, auto)",
563
630
  ),
631
+ prompts: str | None = typer.Option(
632
+ None,
633
+ "--prompts",
634
+ help=(
635
+ "Comma-separated prompt sources: 'all', 'core', and/or module ids (e.g. nold-ai/specfact-backlog). "
636
+ "Default: all discovered sources. Omitted in interactive mode opens a multi-select."
637
+ ),
638
+ ),
564
639
  ) -> None:
565
- """Initialize IDE prompt templates and settings."""
640
+ """Initialize IDE prompt templates and settings (exports core + installed module prompts; re-sync anytime)."""
566
641
  repo_path = repo.resolve()
567
642
  detected_default = detect_ide("auto")
568
643
  if ide is not None:
@@ -595,14 +670,28 @@ def init_ide(
595
670
  if install_deps:
596
671
  _install_contract_enhancement_dependencies(repo_path, env_info)
597
672
 
598
- prompt_files = discover_prompt_template_files(repo_path)
599
- if not prompt_files:
600
- console.print("[red]Error:[/red] Templates directory not found.")
673
+ catalog = discover_prompt_sources_catalog(repo_path)
674
+ if not catalog:
675
+ console.print("[red]Error:[/red] No prompt templates found.")
676
+ console.print(
677
+ "[dim]Seed or install modules first, e.g. [bold]specfact module init --scope project[/bold] "
678
+ "or [bold]specfact module install --scope user[/bold].[/dim]"
679
+ )
601
680
  raise typer.Exit(1)
602
681
 
603
- template_sources = ", ".join(sorted({str(path.parent) for path in prompt_files}))
604
- console.print(f"[cyan]Templates:[/cyan] {template_sources}")
605
- copied_files, settings_path = copy_templates_to_ide(repo_path, selected_ide, force)
682
+ if prompts is not None:
683
+ selected_catalog = _parse_prompts_option_to_catalog(catalog, prompts)
684
+ elif is_non_interactive():
685
+ selected_catalog = dict(catalog)
686
+ else:
687
+ selected_catalog = _select_prompt_sources_interactive(catalog)
688
+
689
+ source_summary = ", ".join(sorted(selected_catalog.keys()))
690
+ console.print(f"[cyan]Prompt sources:[/cyan] {source_summary}")
691
+ copied_files, settings_path = copy_templates_to_ide(
692
+ repo_path, selected_ide, force, prompts_by_source=selected_catalog
693
+ )
694
+ write_ide_prompt_export_state(repo_path, selected_ide, sorted(selected_catalog.keys()))
606
695
  _copy_backlog_field_mapping_templates(repo_path, force, console)
607
696
 
608
697
  console.print()