specfact-cli 0.27.0__tar.gz → 0.30.1__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 (363) hide show
  1. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/.gitignore +4 -0
  2. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/PKG-INFO +51 -4
  3. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/README.md +50 -3
  4. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/pyproject.toml +6 -3
  5. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/__init__.py +1 -1
  6. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/__init__.py +1 -1
  7. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/ado.py +10 -2
  8. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/graph_analyzer.py +6 -6
  9. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/cli.py +50 -1
  10. specfact_cli-0.30.1/src/specfact_cli/commands/analyze.py +6 -0
  11. specfact_cli-0.30.1/src/specfact_cli/commands/auth.py +6 -0
  12. specfact_cli-0.30.1/src/specfact_cli/commands/backlog_commands.py +6 -0
  13. specfact_cli-0.30.1/src/specfact_cli/commands/contract_cmd.py +6 -0
  14. specfact_cli-0.30.1/src/specfact_cli/commands/drift.py +6 -0
  15. specfact_cli-0.30.1/src/specfact_cli/commands/enforce.py +6 -0
  16. specfact_cli-0.30.1/src/specfact_cli/commands/generate.py +6 -0
  17. specfact_cli-0.30.1/src/specfact_cli/commands/import_cmd.py +6 -0
  18. specfact_cli-0.30.1/src/specfact_cli/commands/init.py +6 -0
  19. specfact_cli-0.30.1/src/specfact_cli/commands/migrate.py +6 -0
  20. specfact_cli-0.30.1/src/specfact_cli/commands/plan.py +6 -0
  21. specfact_cli-0.30.1/src/specfact_cli/commands/project_cmd.py +6 -0
  22. specfact_cli-0.30.1/src/specfact_cli/commands/repro.py +6 -0
  23. specfact_cli-0.30.1/src/specfact_cli/commands/sdd.py +6 -0
  24. specfact_cli-0.30.1/src/specfact_cli/commands/spec.py +6 -0
  25. specfact_cli-0.30.1/src/specfact_cli/commands/sync.py +6 -0
  26. specfact_cli-0.30.1/src/specfact_cli/commands/update.py +6 -0
  27. specfact_cli-0.30.1/src/specfact_cli/commands/validate.py +6 -0
  28. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/common/logger_setup.py +9 -2
  29. specfact_cli-0.30.1/src/specfact_cli/contracts/__init__.py +29 -0
  30. specfact_cli-0.30.1/src/specfact_cli/contracts/module_interface.py +30 -0
  31. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/persona_exporter.py +1 -1
  32. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/importers/speckit_converter.py +14 -5
  33. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/merge/resolver.py +1 -1
  34. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/bridge.py +8 -16
  35. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/change.py +13 -0
  36. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/dor_config.py +2 -6
  37. specfact_cli-0.30.1/src/specfact_cli/models/module_package.py +73 -0
  38. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/plan.py +26 -2
  39. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/project.py +33 -4
  40. specfact_cli-0.30.1/src/specfact_cli/models/validation.py +31 -0
  41. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/analyze/module-package.yaml +1 -0
  42. specfact_cli-0.30.1/src/specfact_cli/modules/analyze/src/__init__.py +1 -0
  43. specfact_cli-0.30.1/src/specfact_cli/modules/analyze/src/app.py +6 -0
  44. specfact_cli-0.27.0/src/specfact_cli/commands/analyze.py → specfact_cli-0.30.1/src/specfact_cli/modules/analyze/src/commands.py +7 -0
  45. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/auth/module-package.yaml +1 -0
  46. specfact_cli-0.30.1/src/specfact_cli/modules/auth/src/__init__.py +1 -0
  47. specfact_cli-0.30.1/src/specfact_cli/modules/auth/src/app.py +6 -0
  48. specfact_cli-0.27.0/src/specfact_cli/commands/auth.py → specfact_cli-0.30.1/src/specfact_cli/modules/auth/src/commands.py +19 -1
  49. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/module-package.yaml +24 -0
  50. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/__init__.py +1 -0
  51. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/__init__.py +9 -0
  52. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/ado.py +20 -0
  53. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/base.py +93 -0
  54. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/github.py +20 -0
  55. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/jira.py +20 -0
  56. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/adapters/linear.py +20 -0
  57. specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/app.py +6 -0
  58. specfact_cli-0.27.0/src/specfact_cli/commands/backlog_commands.py → specfact_cli-0.30.1/src/specfact_cli/modules/backlog/src/commands.py +70 -2
  59. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/contract/module-package.yaml +1 -0
  60. specfact_cli-0.30.1/src/specfact_cli/modules/contract/src/__init__.py +1 -0
  61. specfact_cli-0.30.1/src/specfact_cli/modules/contract/src/app.py +6 -0
  62. specfact_cli-0.27.0/src/specfact_cli/commands/contract_cmd.py → specfact_cli-0.30.1/src/specfact_cli/modules/contract/src/commands.py +13 -3
  63. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/drift/module-package.yaml +1 -0
  64. specfact_cli-0.30.1/src/specfact_cli/modules/drift/src/__init__.py +1 -0
  65. specfact_cli-0.30.1/src/specfact_cli/modules/drift/src/app.py +6 -0
  66. specfact_cli-0.27.0/src/specfact_cli/commands/drift.py → specfact_cli-0.30.1/src/specfact_cli/modules/drift/src/commands.py +7 -0
  67. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/enforce/module-package.yaml +3 -1
  68. specfact_cli-0.30.1/src/specfact_cli/modules/enforce/src/__init__.py +1 -0
  69. specfact_cli-0.30.1/src/specfact_cli/modules/enforce/src/app.py +6 -0
  70. specfact_cli-0.27.0/src/specfact_cli/commands/enforce.py → specfact_cli-0.30.1/src/specfact_cli/modules/enforce/src/commands.py +71 -3
  71. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/generate/module-package.yaml +3 -1
  72. specfact_cli-0.30.1/src/specfact_cli/modules/generate/src/__init__.py +1 -0
  73. specfact_cli-0.30.1/src/specfact_cli/modules/generate/src/app.py +6 -0
  74. specfact_cli-0.27.0/src/specfact_cli/commands/generate.py → specfact_cli-0.30.1/src/specfact_cli/modules/generate/src/commands.py +69 -2
  75. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/import_cmd/module-package.yaml +1 -0
  76. specfact_cli-0.30.1/src/specfact_cli/modules/import_cmd/src/__init__.py +1 -0
  77. specfact_cli-0.30.1/src/specfact_cli/modules/import_cmd/src/app.py +6 -0
  78. specfact_cli-0.27.0/src/specfact_cli/commands/import_cmd.py → specfact_cli-0.30.1/src/specfact_cli/modules/import_cmd/src/commands.py +19 -0
  79. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/init/module-package.yaml +2 -1
  80. specfact_cli-0.30.1/src/specfact_cli/modules/init/src/__init__.py +1 -0
  81. specfact_cli-0.30.1/src/specfact_cli/modules/init/src/app.py +6 -0
  82. specfact_cli-0.27.0/src/specfact_cli/commands/init.py → specfact_cli-0.30.1/src/specfact_cli/modules/init/src/commands.py +457 -28
  83. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/migrate/module-package.yaml +1 -0
  84. specfact_cli-0.30.1/src/specfact_cli/modules/migrate/src/__init__.py +1 -0
  85. specfact_cli-0.30.1/src/specfact_cli/modules/migrate/src/app.py +6 -0
  86. specfact_cli-0.27.0/src/specfact_cli/commands/migrate.py → specfact_cli-0.30.1/src/specfact_cli/modules/migrate/src/commands.py +5 -0
  87. specfact_cli-0.30.1/src/specfact_cli/modules/module_io_shim.py +77 -0
  88. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/plan/module-package.yaml +3 -1
  89. specfact_cli-0.30.1/src/specfact_cli/modules/plan/src/__init__.py +1 -0
  90. specfact_cli-0.30.1/src/specfact_cli/modules/plan/src/app.py +6 -0
  91. specfact_cli-0.27.0/src/specfact_cli/commands/plan.py → specfact_cli-0.30.1/src/specfact_cli/modules/plan/src/commands.py +99 -64
  92. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/project/module-package.yaml +1 -0
  93. specfact_cli-0.30.1/src/specfact_cli/modules/project/src/__init__.py +1 -0
  94. specfact_cli-0.30.1/src/specfact_cli/modules/project/src/app.py +6 -0
  95. specfact_cli-0.27.0/src/specfact_cli/commands/project_cmd.py → specfact_cli-0.30.1/src/specfact_cli/modules/project/src/commands.py +49 -15
  96. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/repro/module-package.yaml +1 -0
  97. specfact_cli-0.30.1/src/specfact_cli/modules/repro/src/__init__.py +1 -0
  98. specfact_cli-0.30.1/src/specfact_cli/modules/repro/src/app.py +6 -0
  99. specfact_cli-0.27.0/src/specfact_cli/commands/repro.py → specfact_cli-0.30.1/src/specfact_cli/modules/repro/src/commands.py +25 -3
  100. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/sdd/module-package.yaml +1 -0
  101. specfact_cli-0.30.1/src/specfact_cli/modules/sdd/src/__init__.py +1 -0
  102. specfact_cli-0.30.1/src/specfact_cli/modules/sdd/src/app.py +6 -0
  103. specfact_cli-0.27.0/src/specfact_cli/commands/sdd.py → specfact_cli-0.30.1/src/specfact_cli/modules/sdd/src/commands.py +10 -26
  104. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/spec/module-package.yaml +1 -0
  105. specfact_cli-0.30.1/src/specfact_cli/modules/spec/src/__init__.py +1 -0
  106. specfact_cli-0.30.1/src/specfact_cli/modules/spec/src/app.py +6 -0
  107. specfact_cli-0.27.0/src/specfact_cli/commands/spec.py → specfact_cli-0.30.1/src/specfact_cli/modules/spec/src/commands.py +5 -0
  108. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/sync/module-package.yaml +4 -1
  109. specfact_cli-0.30.1/src/specfact_cli/modules/sync/src/__init__.py +1 -0
  110. specfact_cli-0.30.1/src/specfact_cli/modules/sync/src/app.py +6 -0
  111. specfact_cli-0.27.0/src/specfact_cli/commands/sync.py → specfact_cli-0.30.1/src/specfact_cli/modules/sync/src/commands.py +161 -18
  112. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/upgrade/module-package.yaml +1 -0
  113. specfact_cli-0.30.1/src/specfact_cli/modules/upgrade/src/__init__.py +1 -0
  114. specfact_cli-0.30.1/src/specfact_cli/modules/upgrade/src/app.py +6 -0
  115. specfact_cli-0.27.0/src/specfact_cli/commands/update.py → specfact_cli-0.30.1/src/specfact_cli/modules/upgrade/src/commands.py +9 -0
  116. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/validate/module-package.yaml +1 -0
  117. specfact_cli-0.30.1/src/specfact_cli/modules/validate/src/__init__.py +1 -0
  118. specfact_cli-0.30.1/src/specfact_cli/modules/validate/src/app.py +6 -0
  119. specfact_cli-0.27.0/src/specfact_cli/commands/validate.py → specfact_cli-0.30.1/src/specfact_cli/modules/validate/src/commands.py +7 -0
  120. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/parsers/persona_importer.py +28 -15
  121. specfact_cli-0.30.1/src/specfact_cli/registry/bridge_registry.py +75 -0
  122. specfact_cli-0.30.1/src/specfact_cli/registry/module_packages.py +697 -0
  123. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/module_state.py +32 -0
  124. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/registry.py +17 -3
  125. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/runtime.py +42 -28
  126. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/bridge_probe.py +28 -13
  127. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/telemetry.py +74 -6
  128. specfact_cli-0.30.1/src/specfact_cli/utils/bundle_converters.py +67 -0
  129. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/git.py +3 -3
  130. specfact_cli-0.30.1/src/specfact_cli/utils/persona_ownership.py +34 -0
  131. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/source_scanner.py +14 -11
  132. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/repro_checker.py +83 -9
  133. specfact_cli-0.27.0/src/specfact_cli/contracts/__init__.py +0 -3
  134. specfact_cli-0.27.0/src/specfact_cli/modules/analyze/src/app.py +0 -6
  135. specfact_cli-0.27.0/src/specfact_cli/modules/auth/src/app.py +0 -6
  136. specfact_cli-0.27.0/src/specfact_cli/modules/backlog/module-package.yaml +0 -10
  137. specfact_cli-0.27.0/src/specfact_cli/modules/backlog/src/app.py +0 -6
  138. specfact_cli-0.27.0/src/specfact_cli/modules/contract/src/app.py +0 -6
  139. specfact_cli-0.27.0/src/specfact_cli/modules/drift/src/app.py +0 -6
  140. specfact_cli-0.27.0/src/specfact_cli/modules/enforce/src/app.py +0 -6
  141. specfact_cli-0.27.0/src/specfact_cli/modules/generate/src/app.py +0 -6
  142. specfact_cli-0.27.0/src/specfact_cli/modules/import_cmd/src/app.py +0 -6
  143. specfact_cli-0.27.0/src/specfact_cli/modules/init/src/app.py +0 -6
  144. specfact_cli-0.27.0/src/specfact_cli/modules/migrate/src/app.py +0 -6
  145. specfact_cli-0.27.0/src/specfact_cli/modules/plan/src/app.py +0 -6
  146. specfact_cli-0.27.0/src/specfact_cli/modules/project/src/app.py +0 -6
  147. specfact_cli-0.27.0/src/specfact_cli/modules/repro/src/app.py +0 -6
  148. specfact_cli-0.27.0/src/specfact_cli/modules/sdd/src/app.py +0 -6
  149. specfact_cli-0.27.0/src/specfact_cli/modules/spec/src/app.py +0 -6
  150. specfact_cli-0.27.0/src/specfact_cli/modules/sync/src/app.py +0 -6
  151. specfact_cli-0.27.0/src/specfact_cli/modules/upgrade/src/app.py +0 -6
  152. specfact_cli-0.27.0/src/specfact_cli/modules/validate/src/app.py +0 -6
  153. specfact_cli-0.27.0/src/specfact_cli/registry/module_packages.py +0 -232
  154. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/LICENSE.md +0 -0
  155. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/mappings/node-async.yaml +0 -0
  156. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/mappings/python-async.yaml +0 -0
  157. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/mappings/speckit-default.yaml +0 -0
  158. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/shared/cli-enforcement.md +0 -0
  159. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.01-import.md +0 -0
  160. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.02-plan.md +0 -0
  161. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.03-review.md +0 -0
  162. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.04-sdd.md +0 -0
  163. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.05-enforce.md +0 -0
  164. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.06-sync.md +0 -0
  165. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.07-contracts.md +0 -0
  166. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.backlog-daily.md +0 -0
  167. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.backlog-refine.md +0 -0
  168. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.compare.md +0 -0
  169. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.sync-backlog.md +0 -0
  170. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/prompts/specfact.validate.md +0 -0
  171. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/schemas/deviation.schema.json +0 -0
  172. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/schemas/plan.schema.json +0 -0
  173. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/schemas/protocol.schema.json +0 -0
  174. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/defaults/defect_v1.yaml +0 -0
  175. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/defaults/enabler_v1.yaml +0 -0
  176. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/defaults/spike_v1.yaml +0 -0
  177. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/defaults/user_story_v1.yaml +0 -0
  178. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/field_mappings/ado_agile.yaml +0 -0
  179. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/field_mappings/ado_default.yaml +0 -0
  180. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/field_mappings/ado_kanban.yaml +0 -0
  181. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/field_mappings/ado_safe.yaml +0 -0
  182. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/field_mappings/ado_scrum.yaml +0 -0
  183. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/frameworks/safe/safe_feature_v1.yaml +0 -0
  184. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/frameworks/scrum/user_story_v1.yaml +0 -0
  185. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/personas/developer/developer_task_v1.yaml +0 -0
  186. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/personas/product-owner/user_story_v1.yaml +0 -0
  187. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/backlog/providers/ado/work_item_v1.yaml +0 -0
  188. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/github-action.yml.j2 +0 -0
  189. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/persona/architect.md.j2 +0 -0
  190. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/persona/developer.md.j2 +0 -0
  191. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/persona/product-owner.md.j2 +0 -0
  192. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/plan.bundle.yaml.j2 +0 -0
  193. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/pr-template.md.j2 +0 -0
  194. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/protocol.yaml.j2 +0 -0
  195. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/resources/templates/telemetry.yaml.example +0 -0
  196. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/__main__.py +0 -0
  197. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/__init__.py +0 -0
  198. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/backlog_base.py +0 -0
  199. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/base.py +0 -0
  200. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/github.py +0 -0
  201. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/openspec.py +0 -0
  202. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/openspec_parser.py +0 -0
  203. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/registry.py +0 -0
  204. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/adapters/speckit.py +0 -0
  205. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/__init__.py +0 -0
  206. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/analyze_agent.py +0 -0
  207. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/base.py +0 -0
  208. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/plan_agent.py +0 -0
  209. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/registry.py +0 -0
  210. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/agents/sync_agent.py +0 -0
  211. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/__init__.py +0 -0
  212. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
  213. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
  214. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
  215. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
  216. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
  217. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
  218. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
  219. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
  220. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/__init__.py +0 -0
  221. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/adapters/__init__.py +0 -0
  222. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/adapters/base.py +0 -0
  223. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/adapters/local_yaml_adapter.py +0 -0
  224. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/ai_refiner.py +0 -0
  225. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/converter.py +0 -0
  226. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/filters.py +0 -0
  227. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/format_detector.py +0 -0
  228. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/formats/__init__.py +0 -0
  229. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/formats/base.py +0 -0
  230. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/formats/markdown_format.py +0 -0
  231. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/formats/structured_format.py +0 -0
  232. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
  233. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/mappers/ado_mapper.py +0 -0
  234. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/mappers/base.py +0 -0
  235. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
  236. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
  237. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/backlog/template_detector.py +0 -0
  238. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/commands/__init__.py +0 -0
  239. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/common/__init__.py +0 -0
  240. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/common/logging_utils.py +0 -0
  241. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/common/text_utils.py +0 -0
  242. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/common/utils.py +0 -0
  243. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/comparators/__init__.py +0 -0
  244. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/comparators/plan_comparator.py +0 -0
  245. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/contracts/crosshair_props.py +0 -0
  246. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
  247. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
  248. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/__init__.py +0 -0
  249. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/contract_generator.py +0 -0
  250. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/openapi_extractor.py +0 -0
  251. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/plan_generator.py +0 -0
  252. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/protocol_generator.py +0 -0
  253. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/report_generator.py +0 -0
  254. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/task_generator.py +0 -0
  255. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/test_to_openapi.py +0 -0
  256. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/generators/workflow_generator.py +0 -0
  257. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/importers/__init__.py +0 -0
  258. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/importers/speckit_scanner.py +0 -0
  259. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/integrations/__init__.py +0 -0
  260. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/integrations/specmatic.py +0 -0
  261. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/merge/__init__.py +0 -0
  262. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/migrations/__init__.py +0 -0
  263. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/migrations/plan_migrator.py +0 -0
  264. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/__init__.py +0 -0
  265. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/backlog_item.py +0 -0
  266. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/capabilities.py +0 -0
  267. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/contract.py +0 -0
  268. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/deviation.py +0 -0
  269. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/enforcement.py +0 -0
  270. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/persona_template.py +0 -0
  271. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/protocol.py +0 -0
  272. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/quality.py +0 -0
  273. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/sdd.py +0 -0
  274. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/source_tracking.py +0 -0
  275. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/models/task.py +0 -0
  276. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modes/__init__.py +0 -0
  277. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modes/detector.py +0 -0
  278. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modes/router.py +0 -0
  279. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/modules/__init__.py +0 -0
  280. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/parsers/__init__.py +0 -0
  281. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/__init__.py +0 -0
  282. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/bootstrap.py +0 -0
  283. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/help_cache.py +0 -0
  284. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/registry/metadata.py +0 -0
  285. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/resources/semgrep/async.yml +0 -0
  286. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
  287. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
  288. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/__init__.py +0 -0
  289. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/bridge_sync.py +0 -0
  290. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/bridge_watch.py +0 -0
  291. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/change_detector.py +0 -0
  292. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/code_to_spec.py +0 -0
  293. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/drift_detector.py +0 -0
  294. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/repository_sync.py +0 -0
  295. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/spec_to_code.py +0 -0
  296. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/spec_to_tests.py +0 -0
  297. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/watcher.py +0 -0
  298. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
  299. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/__init__.py +0 -0
  300. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/bridge_templates.py +0 -0
  301. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -0
  302. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -0
  303. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -0
  304. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -0
  305. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -0
  306. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -0
  307. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -0
  308. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/registry.py +0 -0
  309. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/templates/specification_templates.py +0 -0
  310. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/__init__.py +0 -0
  311. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
  312. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/auth_tokens.py +0 -0
  313. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/bundle_loader.py +0 -0
  314. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/code_change_detector.py +0 -0
  315. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/console.py +0 -0
  316. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/content_sanitizer.py +0 -0
  317. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/context_detection.py +0 -0
  318. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/enrichment_context.py +0 -0
  319. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/enrichment_parser.py +0 -0
  320. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/env_manager.py +0 -0
  321. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/feature_keys.py +0 -0
  322. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/github_annotations.py +0 -0
  323. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/ide_setup.py +0 -0
  324. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/incremental_check.py +0 -0
  325. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/metadata.py +0 -0
  326. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/optional_deps.py +0 -0
  327. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/performance.py +0 -0
  328. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/progress.py +0 -0
  329. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
  330. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/prompts.py +0 -0
  331. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/sdd_discovery.py +0 -0
  332. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/startup_checks.py +0 -0
  333. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/structure.py +0 -0
  334. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/structured_io.py +0 -0
  335. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/suggestions.py +0 -0
  336. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/terminal.py +0 -0
  337. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/utils/yaml_utils.py +0 -0
  338. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/__init__.py +0 -0
  339. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/agile_validation.py +0 -0
  340. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
  341. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/cli_first_validator.py +0 -0
  342. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/contract_validator.py +0 -0
  343. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/fsm.py +0 -0
  344. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/schema.py +0 -0
  345. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
  346. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
  347. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
  348. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
  349. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/dependency_installer.py +0 -0
  350. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
  351. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
  352. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
  353. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
  354. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
  355. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
  356. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
  357. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
  358. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/models.py +0 -0
  359. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/orchestrator.py +0 -0
  360. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
  361. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
  362. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/versioning/__init__.py +0 -0
  363. {specfact_cli-0.27.0 → specfact_cli-0.30.1}/src/specfact_cli/versioning/analyzer.py +0 -0
@@ -107,6 +107,10 @@ docs/internal/
107
107
  .github/prompts/specfact.*.md
108
108
  .github/prompts/opsx-*.md
109
109
 
110
+ .claude/commands/opsx/
111
+ .claude/skills/openspec-*/
112
+ !.claude/skills/openspec-workflows/
113
+
110
114
  # Semgrep rules (generated from tools/semgrep/ - source rules are versioned)
111
115
  .semgrep/
112
116
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specfact-cli
3
- Version: 0.27.0
3
+ Version: 0.30.1
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
@@ -309,12 +309,16 @@ uvx specfact-cli@latest
309
309
  pip install -U specfact-cli
310
310
  ```
311
311
 
312
- ### Initialize IDE Integration (optional but recommended)
312
+ ### Bootstrap and IDE Setup
313
313
 
314
314
  ```bash
315
+ # Bootstrap module registry and local config (~/.specfact)
315
316
  specfact init
316
- specfact init --ide cursor
317
- specfact init --ide vscode
317
+
318
+ # Configure IDE prompts/templates (interactive selector by default)
319
+ specfact init ide
320
+ specfact init ide --ide cursor
321
+ specfact init ide --ide vscode
318
322
  ```
319
323
 
320
324
  ### Run Your First Flow
@@ -412,6 +416,49 @@ Most tools help **either** coders **or** agile teams. SpecFact does both:
412
416
  - **Backlogs**: GitHub Issues, Azure DevOps, Jira, Linear
413
417
  - **Contracts**: Specmatic, OpenAPI
414
418
 
419
+ ### Module Lifecycle Baseline
420
+
421
+ SpecFact now has a lifecycle-managed module system:
422
+
423
+ - `specfact init` is bootstrap-first: initializes local CLI state, discovers installed modules, and reports prompt status.
424
+ - `specfact init ide` handles IDE prompt/template sync and IDE settings updates.
425
+ - `specfact init --list-modules` shows effective enabled/disabled state.
426
+ - `specfact init --enable-module` / `--disable-module` support:
427
+ - interactive selection in interactive terminals when no module id is provided
428
+ - explicit ids in non-interactive mode (for automation)
429
+ - dependency-aware safety checks with `--force` cascading enable/disable behavior
430
+ - Module manifests support dependency and core-version compatibility enforcement at registration time.
431
+
432
+ This lifecycle model is the baseline for future granular module updates and enhancements. Module installation from third-party or open-source community providers is planned, but not implemented yet.
433
+
434
+ Contract-first module architecture highlights:
435
+
436
+ - `ModuleIOContract` formalizes module IO operations (`import`, `export`, `sync`, `validate`) on `ProjectBundle`.
437
+ - Core-module isolation is enforced by static analysis (`core` never imports `specfact_cli.modules.*` directly).
438
+ - Registration tracks protocol operation coverage and schema compatibility metadata.
439
+ - Bridge registry support allows module manifests to declare `service_bridges` converters (for example ADO/Jira/Linear/GitHub) loaded at lifecycle startup without direct core-to-module imports.
440
+ - Protocol reporting classifies modules from effective runtime interfaces with a single aggregate summary (`Full/Partial/Legacy`).
441
+
442
+ Why this matters:
443
+
444
+ - Feature areas can evolve independently without repeatedly modifying core CLI wiring.
445
+ - Module teams can ship at different speeds while preserving stable core behavior.
446
+ - Clear IO contracts reduce coupling and make future migrations (e.g., new adapters/modules) lower risk.
447
+ - Core remains focused on lifecycle, registry, and validation orchestration rather than tool-specific command logic.
448
+
449
+ ---
450
+
451
+ ## Developer Note: Command Layout
452
+
453
+ - Primary command implementations live in `src/specfact_cli/modules/<module>/src/commands.py`.
454
+ - Legacy imports from `src/specfact_cli/commands/*.py` are compatibility shims and only guarantee `app` re-exports.
455
+ - Preferred imports for module code:
456
+ - `from specfact_cli.modules.<module>.src.commands import app`
457
+ - `from specfact_cli.modules.<module>.src.commands import <symbol>`
458
+ - Shim deprecation timeline:
459
+ - Legacy shim usage is deprecated for non-`app` symbols now.
460
+ - Shim removal is planned no earlier than `v0.30` (or the next major migration window).
461
+
415
462
  ---
416
463
 
417
464
  ## Where SpecFact Fits
@@ -31,12 +31,16 @@ uvx specfact-cli@latest
31
31
  pip install -U specfact-cli
32
32
  ```
33
33
 
34
- ### Initialize IDE Integration (optional but recommended)
34
+ ### Bootstrap and IDE Setup
35
35
 
36
36
  ```bash
37
+ # Bootstrap module registry and local config (~/.specfact)
37
38
  specfact init
38
- specfact init --ide cursor
39
- specfact init --ide vscode
39
+
40
+ # Configure IDE prompts/templates (interactive selector by default)
41
+ specfact init ide
42
+ specfact init ide --ide cursor
43
+ specfact init ide --ide vscode
40
44
  ```
41
45
 
42
46
  ### Run Your First Flow
@@ -134,6 +138,49 @@ Most tools help **either** coders **or** agile teams. SpecFact does both:
134
138
  - **Backlogs**: GitHub Issues, Azure DevOps, Jira, Linear
135
139
  - **Contracts**: Specmatic, OpenAPI
136
140
 
141
+ ### Module Lifecycle Baseline
142
+
143
+ SpecFact now has a lifecycle-managed module system:
144
+
145
+ - `specfact init` is bootstrap-first: initializes local CLI state, discovers installed modules, and reports prompt status.
146
+ - `specfact init ide` handles IDE prompt/template sync and IDE settings updates.
147
+ - `specfact init --list-modules` shows effective enabled/disabled state.
148
+ - `specfact init --enable-module` / `--disable-module` support:
149
+ - interactive selection in interactive terminals when no module id is provided
150
+ - explicit ids in non-interactive mode (for automation)
151
+ - dependency-aware safety checks with `--force` cascading enable/disable behavior
152
+ - Module manifests support dependency and core-version compatibility enforcement at registration time.
153
+
154
+ This lifecycle model is the baseline for future granular module updates and enhancements. Module installation from third-party or open-source community providers is planned, but not implemented yet.
155
+
156
+ Contract-first module architecture highlights:
157
+
158
+ - `ModuleIOContract` formalizes module IO operations (`import`, `export`, `sync`, `validate`) on `ProjectBundle`.
159
+ - Core-module isolation is enforced by static analysis (`core` never imports `specfact_cli.modules.*` directly).
160
+ - Registration tracks protocol operation coverage and schema compatibility metadata.
161
+ - Bridge registry support allows module manifests to declare `service_bridges` converters (for example ADO/Jira/Linear/GitHub) loaded at lifecycle startup without direct core-to-module imports.
162
+ - Protocol reporting classifies modules from effective runtime interfaces with a single aggregate summary (`Full/Partial/Legacy`).
163
+
164
+ Why this matters:
165
+
166
+ - Feature areas can evolve independently without repeatedly modifying core CLI wiring.
167
+ - Module teams can ship at different speeds while preserving stable core behavior.
168
+ - Clear IO contracts reduce coupling and make future migrations (e.g., new adapters/modules) lower risk.
169
+ - Core remains focused on lifecycle, registry, and validation orchestration rather than tool-specific command logic.
170
+
171
+ ---
172
+
173
+ ## Developer Note: Command Layout
174
+
175
+ - Primary command implementations live in `src/specfact_cli/modules/<module>/src/commands.py`.
176
+ - Legacy imports from `src/specfact_cli/commands/*.py` are compatibility shims and only guarantee `app` re-exports.
177
+ - Preferred imports for module code:
178
+ - `from specfact_cli.modules.<module>.src.commands import app`
179
+ - `from specfact_cli.modules.<module>.src.commands import <symbol>`
180
+ - Shim deprecation timeline:
181
+ - Legacy shim usage is deprecated for non-`app` symbols now.
182
+ - Shim removal is planned no earlier than `v0.30` (or the next major migration window).
183
+
137
184
  ---
138
185
 
139
186
  ## Where SpecFact Fits
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "specfact-cli"
7
- version = "0.27.0"
7
+ version = "0.30.1"
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"
@@ -193,8 +193,8 @@ validate-prompts = "python tools/validate_prompts.py"
193
193
  # Development scripts
194
194
  test = "pytest {args}"
195
195
  test-cov = "pytest --cov=src --cov-report=term-missing {args}"
196
- type-check = "basedpyright {args}"
197
- lint = "ruff format . --check && basedpyright && ruff check . && pylint src tests tools"
196
+ type-check = "basedpyright --pythonpath $(python -c 'import sys; print(sys.executable)') {args}"
197
+ lint = "ruff format . --check && basedpyright --pythonpath $(python -c 'import sys; print(sys.executable)') && ruff check . && pylint src tests tools"
198
198
  governance = "pylint src tests tools --reports=y --output-format=parseable"
199
199
  format = "ruff check . --fix && ruff format ."
200
200
 
@@ -705,6 +705,9 @@ ignore = [
705
705
  "src/specfact_cli/commands/**/*" = [
706
706
  "B008", # typer.Option/Argument in defaults (common Typer pattern)
707
707
  ]
708
+ "src/specfact_cli/modules/**/src/commands.py" = [
709
+ "B008", # typer.Option/Argument in defaults (common Typer pattern)
710
+ ]
708
711
 
709
712
  [tool.ruff.lint.isort]
710
713
  # Match isort ruff profile configuration
@@ -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.27.0"
6
+ __version__ = "0.30.1"
@@ -8,6 +8,6 @@ This package provides command-line tools for:
8
8
  - Supporting agile ceremonies and team workflows
9
9
  """
10
10
 
11
- __version__ = "0.27.0"
11
+ __version__ = "0.30.1"
12
12
 
13
13
  __all__ = ["__version__"]
@@ -14,7 +14,7 @@ import os
14
14
  import re
15
15
  from datetime import UTC, datetime
16
16
  from pathlib import Path
17
- from typing import Any
17
+ from typing import Any, cast
18
18
  from urllib.parse import urlparse
19
19
 
20
20
  import requests
@@ -549,7 +549,15 @@ class AdoAdapter(BridgeAdapter, BacklogAdapterMixin, BacklogAdapter):
549
549
  assigned_to = fields.get("System.AssignedTo")
550
550
  if assigned_to:
551
551
  if isinstance(assigned_to, dict):
552
- assignee_name = assigned_to.get("displayName") or assigned_to.get("uniqueName", "")
552
+ assignee_dict = cast(dict[str, Any], assigned_to)
553
+ display_name = assignee_dict.get("displayName")
554
+ unique_name = assignee_dict.get("uniqueName")
555
+ if isinstance(display_name, str) and display_name.strip():
556
+ assignee_name = display_name.strip()
557
+ elif isinstance(unique_name, str):
558
+ assignee_name = unique_name
559
+ else:
560
+ assignee_name = ""
553
561
  else:
554
562
  assignee_name = str(assigned_to)
555
563
  if assignee_name and not owner:
@@ -370,11 +370,11 @@ class GraphAnalyzer:
370
370
 
371
371
  Tries multiple strategies:
372
372
  1. Exact match
373
- 2. Last part match (e.g., "import_cmd" matches "src.specfact_cli.commands.import_cmd")
374
- 3. Partial path match (e.g., "specfact_cli.commands" matches "src.specfact_cli.commands.import_cmd")
373
+ 2. Last part match (e.g., "import_cmd" matches "src.specfact_cli.modules.import_cmd.src.commands")
374
+ 3. Partial path match (e.g., "specfact_cli.commands" matches "src.specfact_cli.modules.import_cmd.src.commands")
375
375
 
376
376
  Args:
377
- imported: Imported module name (e.g., "specfact_cli.commands.import_cmd")
377
+ imported: Imported module name (e.g., "specfact_cli.modules.import_cmd.src.commands")
378
378
  known_modules: List of known module names in the graph
379
379
 
380
380
  Returns:
@@ -385,14 +385,14 @@ class GraphAnalyzer:
385
385
  return imported
386
386
 
387
387
  # Strategy 2: Last part match
388
- # e.g., "import_cmd" matches "src.specfact_cli.commands.import_cmd"
388
+ # e.g., "import_cmd" matches "src.specfact_cli.modules.import_cmd.src.commands"
389
389
  imported_last = imported.split(".")[-1]
390
390
  for module in known_modules:
391
391
  if module.endswith(f".{imported_last}") or module == imported_last:
392
392
  return module
393
393
 
394
394
  # Strategy 3: Partial path match
395
- # e.g., "specfact_cli.commands" matches "src.specfact_cli.commands.import_cmd"
395
+ # e.g., "specfact_cli.commands" matches "src.specfact_cli.modules.import_cmd.src.commands"
396
396
  for module in known_modules:
397
397
  # Check if imported is a prefix of module
398
398
  if module.startswith(imported + ".") or module == imported:
@@ -406,7 +406,7 @@ class GraphAnalyzer:
406
406
  for module in known_modules:
407
407
  module_parts = module.split(".")
408
408
  # Check if there's overlap in the path
409
- # e.g., "commands.import_cmd" might match "src.specfact_cli.commands.import_cmd"
409
+ # e.g., "commands.import_cmd" might match "src.specfact_cli.modules.import_cmd.src.commands"
410
410
  if len(imported_parts) >= 2 and len(module_parts) >= 2 and imported_parts[-2:] == module_parts[-2:]:
411
411
  return module
412
412
 
@@ -257,7 +257,7 @@ def main(
257
257
  bool | None,
258
258
  typer.Option(
259
259
  "--interactive/--no-interactive",
260
- help="Force interaction mode (default auto based on CI/CD detection)",
260
+ help="Force interaction mode (default auto based on terminal/CI detection)",
261
261
  ),
262
262
  ] = None,
263
263
  ) -> None:
@@ -274,6 +274,10 @@ def main(
274
274
  - Explicit --mode flag (highest priority)
275
275
  - Auto-detect from environment (CoPilot API, IDE integration)
276
276
  - Default to CI/CD mode
277
+
278
+ Interaction Detection:
279
+ - Explicit --interactive/--no-interactive (highest priority)
280
+ - Auto-detect from terminal and CI environment
277
281
  """
278
282
  global _show_banner
279
283
  # Set banner flag based on --banner option
@@ -332,6 +336,33 @@ class _LazyDelegateGroup(click.Group):
332
336
  def _make_delegate_command(self) -> click.Command:
333
337
  cmd_name = self._lazy_cmd_name
334
338
 
339
+ def _normalize_init_optional_module_flags(argv: list[str]) -> list[str]:
340
+ """
341
+ Normalize bare init module flags to sentinel values.
342
+
343
+ Typer/Click options declared with value types require an argument. To support
344
+ UX like `specfact init --enable-module` in interactive mode, rewrite bare flags
345
+ to include a sentinel token consumed by init command logic.
346
+ """
347
+ if cmd_name != "init":
348
+ return argv
349
+ out: list[str] = []
350
+ i = 0
351
+ while i < len(argv):
352
+ token = argv[i]
353
+ if token in ("--enable-module", "--disable-module"):
354
+ out.append(token)
355
+ if i + 1 < len(argv) and not argv[i + 1].startswith("-"):
356
+ out.append(argv[i + 1])
357
+ i += 2
358
+ continue
359
+ out.append("__interactive_select__")
360
+ i += 1
361
+ continue
362
+ out.append(token)
363
+ i += 1
364
+ return out
365
+
335
366
  def _invoke(args: tuple[str, ...]) -> None:
336
367
  from typer.main import get_command
337
368
 
@@ -348,6 +379,7 @@ class _LazyDelegateGroup(click.Group):
348
379
  p = getattr(p, "parent", None)
349
380
  prog_name = " ".join(reversed(parts)) if parts else cmd_name
350
381
  args_list = list(args)
382
+ args_list = _normalize_init_optional_module_flags(args_list)
351
383
  # When the real app is a single command (e.g. drift has only "detect"), Typer
352
384
  # builds a TyperCommand, not a Group. Then args are ["detect", "bundle", "--repo", ...]
353
385
  # and the command expects ["bundle", "--repo", ...] (no leading "detect").
@@ -503,6 +535,23 @@ def cli_main() -> None:
503
535
  # Normalize shell names in argv for Typer's built-in completion commands
504
536
  normalize_shell_in_argv()
505
537
 
538
+ # Initialize debug mode early so --debug works even for eager flags like --help/--version.
539
+ debug_requested = "--debug" in sys.argv[1:]
540
+ if debug_requested:
541
+ set_debug_mode(True)
542
+ init_debug_log_file()
543
+ debug_log_path = runtime.get_debug_log_path()
544
+ if debug_log_path:
545
+ sys.stderr.write(f"[debug] log file: {debug_log_path}\n")
546
+ else:
547
+ sys.stderr.write("[debug] log file unavailable (no writable debug log path)\n")
548
+ runtime.debug_log_operation(
549
+ "cli_start",
550
+ "specfact",
551
+ "started",
552
+ extra={"argv": sys.argv[1:], "pid": os.getpid()},
553
+ )
554
+
506
555
  # Check if --banner flag is present (before Typer processes it)
507
556
  banner_requested = "--banner" in sys.argv
508
557
 
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/analyze/."""
2
+
3
+ from specfact_cli.modules.analyze.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/auth/."""
2
+
3
+ from specfact_cli.modules.auth.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/backlog/."""
2
+
3
+ from specfact_cli.modules.backlog.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/contract/."""
2
+
3
+ from specfact_cli.modules.contract.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/drift/."""
2
+
3
+ from specfact_cli.modules.drift.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/enforce/."""
2
+
3
+ from specfact_cli.modules.enforce.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/generate/."""
2
+
3
+ from specfact_cli.modules.generate.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/import_cmd/."""
2
+
3
+ from specfact_cli.modules.import_cmd.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/init/."""
2
+
3
+ from specfact_cli.modules.init.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/migrate/."""
2
+
3
+ from specfact_cli.modules.migrate.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/plan/."""
2
+
3
+ from specfact_cli.modules.plan.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/project/."""
2
+
3
+ from specfact_cli.modules.project.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/repro/."""
2
+
3
+ from specfact_cli.modules.repro.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/sdd/."""
2
+
3
+ from specfact_cli.modules.sdd.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/spec/."""
2
+
3
+ from specfact_cli.modules.spec.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/sync/."""
2
+
3
+ from specfact_cli.modules.sync.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/upgrade/."""
2
+
3
+ from specfact_cli.modules.upgrade.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -0,0 +1,6 @@
1
+ """Backward-compatible app shim. Implementation moved to modules/validate/."""
2
+
3
+ from specfact_cli.modules.validate.src.commands import app
4
+
5
+
6
+ __all__ = ["app"]
@@ -1,5 +1,7 @@
1
1
  """
2
2
  Logging utility for standardized log setup across all modules
3
+
4
+ CrossHair: skip (logging internals and logger object realization are not symbolic-safe)
3
5
  """
4
6
 
5
7
  import atexit
@@ -526,8 +528,13 @@ class LoggerSetup:
526
528
  queue_handler = QueueHandler(log_queue)
527
529
  logger.addHandler(queue_handler)
528
530
 
529
- # Add a console handler for non-test environments or when no file is specified
530
- if "pytest" not in sys.modules and not any(isinstance(h, logging.StreamHandler) for h in logger.handlers):
531
+ # Add a direct console handler only when no queue listener is active for this logger.
532
+ # Otherwise logs are already streamed by the QueueListener handler and would be duplicated.
533
+ if (
534
+ "pytest" not in sys.modules
535
+ and logger_name not in cls._log_listeners
536
+ and not any(isinstance(h, logging.StreamHandler) for h in logger.handlers)
537
+ ):
531
538
  console_handler = logging.StreamHandler(_safe_console_stream())
532
539
  console_handler.setFormatter(log_format)
533
540
  console_handler.setLevel(level)
@@ -0,0 +1,29 @@
1
+ """Contract exports for protocol and validation integrations.
2
+
3
+ Keep this package import side-effect free so CrossHair can import
4
+ ``specfact_cli.contracts.crosshair_props`` without loading heavy model/utils
5
+ packages that trigger subprocess-based initializers.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from importlib import import_module
11
+ from typing import TYPE_CHECKING, Any
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from specfact_cli.models.validation import ValidationReport
16
+
17
+
18
+ __all__ = ["ValidationReport", "crosshair_props"]
19
+
20
+
21
+ def __getattr__(name: str) -> Any:
22
+ """Lazily resolve exported symbols to avoid import-time side effects."""
23
+ if name == "ValidationReport":
24
+ from specfact_cli.models.validation import ValidationReport as _ValidationReport
25
+
26
+ return _ValidationReport
27
+ if name == "crosshair_props":
28
+ return import_module(".crosshair_props", __name__)
29
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
@@ -0,0 +1,30 @@
1
+ """Module IO protocol contract for module bundle interactions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import abstractmethod
6
+ from pathlib import Path
7
+ from typing import Any, Protocol
8
+
9
+ from specfact_cli.models.project import ProjectBundle
10
+ from specfact_cli.models.validation import ValidationReport
11
+
12
+
13
+ class ModuleIOContract(Protocol):
14
+ """Protocol for module implementations that exchange data via ProjectBundle."""
15
+
16
+ @abstractmethod
17
+ def import_to_bundle(self, source: Path, config: dict[str, Any]) -> ProjectBundle:
18
+ """Import an external artifact and convert it into a ProjectBundle."""
19
+
20
+ @abstractmethod
21
+ def export_from_bundle(self, bundle: ProjectBundle, target: Path, config: dict[str, Any]) -> None:
22
+ """Export a ProjectBundle to an external artifact format."""
23
+
24
+ @abstractmethod
25
+ def sync_with_bundle(self, bundle: ProjectBundle, external_source: str, config: dict[str, Any]) -> ProjectBundle:
26
+ """Synchronize a bundle with an external source and return the updated bundle."""
27
+
28
+ @abstractmethod
29
+ def validate_bundle(self, bundle: ProjectBundle, rules: dict[str, Any]) -> ValidationReport:
30
+ """Run module-specific validation on a ProjectBundle."""
@@ -108,7 +108,7 @@ class PersonaExporter:
108
108
  Returns:
109
109
  Template context dictionary
110
110
  """
111
- from specfact_cli.commands.project_cmd import match_section_pattern
111
+ from specfact_cli.utils.persona_ownership import match_section_pattern
112
112
 
113
113
  context: dict[str, Any] = {
114
114
  "bundle_name": bundle.bundle_name,