specfact-cli 0.40.0__tar.gz → 0.40.2__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 (307) hide show
  1. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/PKG-INFO +3 -1
  2. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/README.md +2 -0
  3. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/pyproject.toml +3 -3
  4. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/__init__.py +1 -1
  5. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/__init__.py +1 -1
  6. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/ado.py +15 -0
  7. specfact_cli-0.40.2/src/specfact_cli/backlog/__init__.py +14 -0
  8. specfact_cli-0.40.2/src/specfact_cli/backlog/adapters/__init__.py +8 -0
  9. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/__init__.py +1 -3
  10. specfact_cli-0.40.2/src/specfact_cli/groups/member_group.py +60 -0
  11. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_discovery.py +7 -0
  12. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_packages.py +22 -18
  13. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/ide_setup.py +0 -4
  14. specfact_cli-0.40.2/src/specfact_cli/validation/__init__.py +14 -0
  15. specfact_cli-0.40.2/src/specfact_cli/validation/command_audit.py +165 -0
  16. specfact_cli-0.40.0/resources/prompts/specfact.backlog-add.md +0 -90
  17. specfact_cli-0.40.0/resources/prompts/specfact.backlog-daily.md +0 -125
  18. specfact_cli-0.40.0/resources/prompts/specfact.backlog-refine.md +0 -557
  19. specfact_cli-0.40.0/resources/prompts/specfact.sync-backlog.md +0 -557
  20. specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_agile.yaml +0 -24
  21. specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_default.yaml +0 -24
  22. specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_kanban.yaml +0 -26
  23. specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_safe.yaml +0 -29
  24. specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_scrum.yaml +0 -24
  25. specfact_cli-0.40.0/resources/templates/backlog/frameworks/safe/safe_feature_v1.yaml +0 -26
  26. specfact_cli-0.40.0/resources/templates/backlog/personas/developer/developer_task_v1.yaml +0 -28
  27. specfact_cli-0.40.0/src/specfact_cli/backlog/__init__.py +0 -24
  28. specfact_cli-0.40.0/src/specfact_cli/backlog/adapters/__init__.py +0 -13
  29. specfact_cli-0.40.0/src/specfact_cli/backlog/adapters/local_yaml_adapter.py +0 -177
  30. specfact_cli-0.40.0/src/specfact_cli/backlog/ai_refiner.py +0 -523
  31. specfact_cli-0.40.0/src/specfact_cli/backlog/format_detector.py +0 -50
  32. specfact_cli-0.40.0/src/specfact_cli/backlog/formats/__init__.py +0 -14
  33. specfact_cli-0.40.0/src/specfact_cli/backlog/formats/base.py +0 -98
  34. specfact_cli-0.40.0/src/specfact_cli/backlog/formats/markdown_format.py +0 -130
  35. specfact_cli-0.40.0/src/specfact_cli/backlog/formats/structured_format.py +0 -97
  36. specfact_cli-0.40.0/src/specfact_cli/backlog/template_detector.py +0 -288
  37. specfact_cli-0.40.0/src/specfact_cli/commands/backlog_commands.py +0 -18
  38. specfact_cli-0.40.0/src/specfact_cli/groups/backlog_group.py +0 -63
  39. specfact_cli-0.40.0/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -22
  40. specfact_cli-0.40.0/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -21
  41. specfact_cli-0.40.0/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -20
  42. specfact_cli-0.40.0/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -19
  43. specfact_cli-0.40.0/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -23
  44. specfact_cli-0.40.0/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -24
  45. specfact_cli-0.40.0/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -21
  46. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/.gitignore +0 -0
  47. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/LICENSE +0 -0
  48. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/keys/README.md +0 -0
  49. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/keys/module-signing-public.pem +0 -0
  50. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/node-async.yaml +0 -0
  51. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/python-async.yaml +0 -0
  52. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/speckit-default.yaml +0 -0
  53. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/shared/cli-enforcement.md +0 -0
  54. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.01-import.md +0 -0
  55. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.02-plan.md +0 -0
  56. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.03-review.md +0 -0
  57. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.04-sdd.md +0 -0
  58. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.05-enforce.md +0 -0
  59. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.06-sync.md +0 -0
  60. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.07-contracts.md +0 -0
  61. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.compare.md +0 -0
  62. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.validate.md +0 -0
  63. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/deviation.schema.json +0 -0
  64. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/plan.schema.json +0 -0
  65. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/protocol.schema.json +0 -0
  66. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/github-action.yml.j2 +0 -0
  67. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/architect.md.j2 +0 -0
  68. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/developer.md.j2 +0 -0
  69. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/product-owner.md.j2 +0 -0
  70. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/plan.bundle.yaml.j2 +0 -0
  71. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/kanban.yaml +0 -0
  72. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/mixed.yaml +0 -0
  73. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/safe.yaml +0 -0
  74. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/scrum.yaml +0 -0
  75. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/pr-template.md.j2 +0 -0
  76. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/protocol.yaml.j2 +0 -0
  77. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/telemetry.yaml.example +0 -0
  78. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/__main__.py +0 -0
  79. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/__init__.py +0 -0
  80. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/backlog_base.py +0 -0
  81. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/base.py +0 -0
  82. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/github.py +0 -0
  83. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/openspec.py +0 -0
  84. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/openspec_parser.py +0 -0
  85. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/registry.py +0 -0
  86. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/speckit.py +0 -0
  87. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/__init__.py +0 -0
  88. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/analyze_agent.py +0 -0
  89. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/base.py +0 -0
  90. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/plan_agent.py +0 -0
  91. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/registry.py +0 -0
  92. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/sync_agent.py +0 -0
  93. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/__init__.py +0 -0
  94. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
  95. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
  96. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
  97. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
  98. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
  99. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
  100. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
  101. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
  102. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
  103. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/adapters/base.py +0 -0
  104. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/converter.py +0 -0
  105. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/filters.py +0 -0
  106. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
  107. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/ado_mapper.py +0 -0
  108. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/base.py +0 -0
  109. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
  110. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
  111. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/cli.py +0 -0
  112. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/__init__.py +0 -0
  113. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/_bundle_shim.py +0 -0
  114. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/analyze.py +0 -0
  115. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/contract_cmd.py +0 -0
  116. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/drift.py +0 -0
  117. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/enforce.py +0 -0
  118. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/generate.py +0 -0
  119. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/import_cmd.py +0 -0
  120. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/init.py +0 -0
  121. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/migrate.py +0 -0
  122. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/plan.py +0 -0
  123. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/project_cmd.py +0 -0
  124. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/repro.py +0 -0
  125. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/sdd.py +0 -0
  126. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/spec.py +0 -0
  127. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/sync.py +0 -0
  128. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/update.py +0 -0
  129. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/validate.py +0 -0
  130. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/__init__.py +0 -0
  131. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/bundle_factory.py +0 -0
  132. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/logger_setup.py +0 -0
  133. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/logging_utils.py +0 -0
  134. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/text_utils.py +0 -0
  135. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/utils.py +0 -0
  136. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/comparators/__init__.py +0 -0
  137. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/comparators/plan_comparator.py +0 -0
  138. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/__init__.py +0 -0
  139. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/crosshair_props.py +0 -0
  140. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/module_interface.py +0 -0
  141. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
  142. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
  143. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/__init__.py +0 -0
  144. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/contract_generator.py +0 -0
  145. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/openapi_extractor.py +0 -0
  146. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/persona_exporter.py +0 -0
  147. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/plan_generator.py +0 -0
  148. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/protocol_generator.py +0 -0
  149. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/report_generator.py +0 -0
  150. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/task_generator.py +0 -0
  151. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/test_to_openapi.py +0 -0
  152. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/workflow_generator.py +0 -0
  153. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/codebase_group.py +0 -0
  154. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/govern_group.py +0 -0
  155. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/project_group.py +0 -0
  156. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/spec_group.py +0 -0
  157. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/__init__.py +0 -0
  158. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/speckit_converter.py +0 -0
  159. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/speckit_scanner.py +0 -0
  160. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/integrations/__init__.py +0 -0
  161. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/integrations/specmatic.py +0 -0
  162. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/merge/__init__.py +0 -0
  163. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/merge/resolver.py +0 -0
  164. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/migrations/__init__.py +0 -0
  165. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/migrations/plan_migrator.py +0 -0
  166. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/__init__.py +0 -0
  167. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/backlog_item.py +0 -0
  168. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/bridge.py +0 -0
  169. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/capabilities.py +0 -0
  170. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/change.py +0 -0
  171. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/contract.py +0 -0
  172. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/deviation.py +0 -0
  173. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/dor_config.py +0 -0
  174. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/enforcement.py +0 -0
  175. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/module_package.py +0 -0
  176. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/persona_template.py +0 -0
  177. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/plan.py +0 -0
  178. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/project.py +0 -0
  179. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/protocol.py +0 -0
  180. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/quality.py +0 -0
  181. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/sdd.py +0 -0
  182. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/source_tracking.py +0 -0
  183. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/task.py +0 -0
  184. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/validation.py +0 -0
  185. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/__init__.py +0 -0
  186. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/detector.py +0 -0
  187. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/router.py +0 -0
  188. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/__init__.py +0 -0
  189. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/_bundle_import.py +0 -0
  190. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/module-package.yaml +0 -0
  191. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/__init__.py +0 -0
  192. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/app.py +0 -0
  193. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/commands.py +0 -0
  194. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/first_run_selection.py +0 -0
  195. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_io_shim.py +0 -0
  196. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/module-package.yaml +0 -0
  197. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/__init__.py +0 -0
  198. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/app.py +0 -0
  199. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/commands.py +0 -0
  200. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/module-package.yaml +0 -0
  201. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/__init__.py +0 -0
  202. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/app.py +0 -0
  203. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/commands.py +0 -0
  204. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/parsers/__init__.py +0 -0
  205. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/parsers/persona_importer.py +0 -0
  206. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/__init__.py +0 -0
  207. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/alias_manager.py +0 -0
  208. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/bootstrap.py +0 -0
  209. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/bridge_registry.py +0 -0
  210. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/crypto_validator.py +0 -0
  211. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/custom_registries.py +0 -0
  212. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/dependency_resolver.py +0 -0
  213. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/extension_registry.py +0 -0
  214. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/help_cache.py +0 -0
  215. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/marketplace_client.py +0 -0
  216. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/metadata.py +0 -0
  217. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_grouping.py +0 -0
  218. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_installer.py +0 -0
  219. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_lifecycle.py +0 -0
  220. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_security.py +0 -0
  221. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_state.py +0 -0
  222. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/registry.py +0 -0
  223. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/async.yml +0 -0
  224. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
  225. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
  226. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/runtime.py +0 -0
  227. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/__init__.py +0 -0
  228. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_probe.py +0 -0
  229. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_sync.py +0 -0
  230. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_watch.py +0 -0
  231. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/change_detector.py +0 -0
  232. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/code_to_spec.py +0 -0
  233. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/drift_detector.py +0 -0
  234. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/repository_sync.py +0 -0
  235. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/spec_to_code.py +0 -0
  236. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/spec_to_tests.py +0 -0
  237. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/watcher.py +0 -0
  238. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
  239. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/telemetry.py +0 -0
  240. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/__init__.py +0 -0
  241. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/defect_v1.yaml +0 -0
  242. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/enabler_v1.yaml +0 -0
  243. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/spike_v1.yaml +0 -0
  244. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/user_story_v1.yaml +0 -0
  245. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/frameworks/scrum/user_story_v1.yaml +0 -0
  246. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/personas/product-owner/user_story_v1.yaml +0 -0
  247. {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/providers/ado/work_item_v1.yaml +0 -0
  248. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/registry.py +0 -0
  249. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/specification_templates.py +0 -0
  250. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/__init__.py +0 -0
  251. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
  252. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/auth_tokens.py +0 -0
  253. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/bundle_converters.py +0 -0
  254. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/bundle_loader.py +0 -0
  255. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/code_change_detector.py +0 -0
  256. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/console.py +0 -0
  257. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/content_sanitizer.py +0 -0
  258. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/context_detection.py +0 -0
  259. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/enrichment_context.py +0 -0
  260. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/enrichment_parser.py +0 -0
  261. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/env_manager.py +0 -0
  262. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/feature_keys.py +0 -0
  263. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/git.py +0 -0
  264. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/github_annotations.py +0 -0
  265. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/incremental_check.py +0 -0
  266. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/metadata.py +0 -0
  267. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/optional_deps.py +0 -0
  268. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/performance.py +0 -0
  269. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/persona_ownership.py +0 -0
  270. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/progress.py +0 -0
  271. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
  272. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/prompts.py +0 -0
  273. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/sdd_discovery.py +0 -0
  274. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/source_scanner.py +0 -0
  275. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/startup_checks.py +0 -0
  276. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/structure.py +0 -0
  277. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/structured_io.py +0 -0
  278. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/suggestions.py +0 -0
  279. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/terminal.py +0 -0
  280. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/yaml_utils.py +0 -0
  281. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/__init__.py +0 -0
  282. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/agile_validation.py +0 -0
  283. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
  284. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/cli_first_validator.py +0 -0
  285. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/contract_validator.py +0 -0
  286. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/fsm.py +0 -0
  287. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/repro_checker.py +0 -0
  288. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/schema.py +0 -0
  289. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
  290. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
  291. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
  292. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
  293. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/dependency_installer.py +0 -0
  294. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
  295. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
  296. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
  297. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
  298. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
  299. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
  300. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
  301. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
  302. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/models.py +0 -0
  303. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/orchestrator.py +0 -0
  304. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
  305. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
  306. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/versioning/__init__.py +0 -0
  307. {specfact_cli-0.40.0 → specfact_cli-0.40.2}/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.40.0
3
+ Version: 0.40.2
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
@@ -353,6 +353,8 @@ As of `0.40.0`, flat root commands are removed. Use grouped commands:
353
353
  ### Backlog Bridge (60 seconds)
354
354
 
355
355
  SpecFact's USP is closing the drift gap between **backlog -> specs -> code**.
356
+ These commands require the backlog bundle to be installed first, for example via
357
+ `specfact init --profile backlog-team` or `specfact init --install backlog`.
356
358
 
357
359
  ```bash
358
360
  # 1) Initialize backlog config + field mapping
@@ -74,6 +74,8 @@ As of `0.40.0`, flat root commands are removed. Use grouped commands:
74
74
  ### Backlog Bridge (60 seconds)
75
75
 
76
76
  SpecFact's USP is closing the drift gap between **backlog -> specs -> code**.
77
+ These commands require the backlog bundle to be installed first, for example via
78
+ `specfact init --profile backlog-team` or `specfact init --install backlog`.
77
79
 
78
80
  ```bash
79
81
  # 1) Initialize backlog config + field mapping
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "specfact-cli"
7
- version = "0.40.0"
7
+ version = "0.40.2"
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"
@@ -377,9 +377,10 @@ method = "thread"
377
377
  dev-mode-dirs = ["src","tools"]
378
378
 
379
379
  [tool.hatch.build.targets.wheel]
380
- packages = [
380
+ only-include = [
381
381
  "src/specfact_cli",
382
382
  ]
383
+ sources = ["src"]
383
384
 
384
385
  [tool.hatch.build.targets.wheel.force-include]
385
386
  "resources/prompts" = "specfact_cli/resources/prompts"
@@ -387,7 +388,6 @@ packages = [
387
388
  "resources/schemas" = "specfact_cli/resources/schemas"
388
389
  "resources/mappings" = "specfact_cli/resources/mappings"
389
390
  "resources/keys" = "specfact_cli/resources/keys"
390
- "modules/backlog-core" = "specfact_cli/modules/backlog-core"
391
391
  "modules/bundle-mapper" = "specfact_cli/modules/bundle-mapper"
392
392
  # Note: resources/semgrep files are in src/specfact_cli/resources/semgrep/ and are automatically included
393
393
 
@@ -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.40.0"
6
+ __version__ = "0.40.2"
@@ -42,6 +42,6 @@ def _bootstrap_bundle_paths() -> None:
42
42
 
43
43
  _bootstrap_bundle_paths()
44
44
 
45
- __version__ = "0.40.0"
45
+ __version__ = "0.40.2"
46
46
 
47
47
  __all__ = ["__version__"]
@@ -3414,6 +3414,21 @@ class AdoAdapter(BridgeAdapter, BacklogAdapterMixin, BacklogAdapter):
3414
3414
  }
3415
3415
  )
3416
3416
 
3417
+ provider_fields = payload.get("provider_fields")
3418
+ provider_field_values = provider_fields.get("fields") if isinstance(provider_fields, dict) else None
3419
+ if isinstance(provider_field_values, dict):
3420
+ for field_name, field_value in provider_field_values.items():
3421
+ normalized_field = str(field_name).strip()
3422
+ if not normalized_field:
3423
+ continue
3424
+ patch_document.append(
3425
+ {
3426
+ "op": "add",
3427
+ "path": f"/fields/{normalized_field}",
3428
+ "value": field_value,
3429
+ }
3430
+ )
3431
+
3417
3432
  sprint = str(payload.get("sprint") or "").strip()
3418
3433
  if sprint:
3419
3434
  patch_document.append(
@@ -0,0 +1,14 @@
1
+ """Shared backlog conversion helpers retained by core adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from specfact_cli.backlog.converter import (
6
+ convert_ado_work_item_to_backlog_item,
7
+ convert_github_issue_to_backlog_item,
8
+ )
9
+
10
+
11
+ __all__ = [
12
+ "convert_ado_work_item_to_backlog_item",
13
+ "convert_github_issue_to_backlog_item",
14
+ ]
@@ -0,0 +1,8 @@
1
+ """Backlog adapter contracts retained by core provider integrations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from specfact_cli.backlog.adapters.base import BacklogAdapter
6
+
7
+
8
+ __all__ = ["BacklogAdapter"]
@@ -1,8 +1,7 @@
1
- """Category group commands: project, backlog, code, spec, govern."""
1
+ """Category group commands: project, code, spec, govern."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from specfact_cli.groups.backlog_group import app as backlog_app
6
5
  from specfact_cli.groups.codebase_group import app as codebase_app
7
6
  from specfact_cli.groups.govern_group import app as govern_app
8
7
  from specfact_cli.groups.project_group import app as project_app
@@ -10,7 +9,6 @@ from specfact_cli.groups.spec_group import app as spec_app
10
9
 
11
10
 
12
11
  __all__ = [
13
- "backlog_app",
14
12
  "codebase_app",
15
13
  "govern_app",
16
14
  "project_app",
@@ -0,0 +1,60 @@
1
+ """Generic category group builder for bundle-owned command surfaces."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+
7
+ import typer
8
+ from beartype import beartype
9
+ from icontract import ensure, require
10
+
11
+ from specfact_cli.registry.registry import CommandRegistry
12
+
13
+
14
+ @require(lambda app: app is not None)
15
+ @beartype
16
+ def _register_members(app: typer.Typer, members: Sequence[tuple[str, str]]) -> int:
17
+ """Register member module sub-apps and return how many were added."""
18
+ added = 0
19
+ for display_name, cmd_name in members:
20
+ try:
21
+ member_app = CommandRegistry.get_module_typer(cmd_name)
22
+ if member_app is not None:
23
+ app.add_typer(member_app, name=display_name)
24
+ added += 1
25
+ except ValueError:
26
+ continue
27
+ return added
28
+
29
+
30
+ @require(lambda name: isinstance(name, str) and len(name) > 0)
31
+ @require(lambda help_text: isinstance(help_text, str) and len(help_text) > 0)
32
+ @ensure(lambda result: isinstance(result, typer.Typer))
33
+ @beartype
34
+ def build_member_group(
35
+ *,
36
+ name: str,
37
+ help_text: str,
38
+ members: Sequence[tuple[str, str]],
39
+ flatten_same_name: str | None = None,
40
+ install_hint_module: str | None = None,
41
+ ) -> typer.Typer:
42
+ """Build a lazy category group from registered member modules."""
43
+ app = typer.Typer(name=name, help=help_text, no_args_is_help=True)
44
+ added = _register_members(app, members)
45
+
46
+ if added == 0 and install_hint_module:
47
+ placeholder = typer.Typer(help=f"{help_text} (module not loaded).")
48
+
49
+ @placeholder.command("install")
50
+ def _install_hint() -> None:
51
+ from specfact_cli.utils.prompts import print_warning
52
+
53
+ print_warning(f"No {name} module loaded. Install with: specfact module install {install_hint_module}")
54
+
55
+ app.add_typer(placeholder, name=name)
56
+
57
+ if flatten_same_name:
58
+ app._specfact_flatten_same_name = flatten_same_name
59
+
60
+ return app
@@ -56,7 +56,14 @@ def discover_all_modules(
56
56
  effective_custom_root = custom_root or CUSTOM_MODULES_ROOT
57
57
 
58
58
  roots: list[tuple[str, Path]] = [("builtin", effective_builtin_root)]
59
+ project_matches_user_root = False
59
60
  if effective_project_root is not None:
61
+ try:
62
+ project_matches_user_root = effective_project_root.resolve() == effective_user_root.resolve()
63
+ except OSError:
64
+ project_matches_user_root = effective_project_root == effective_user_root
65
+
66
+ if effective_project_root is not None and not project_matches_user_root:
60
67
  roots.append(("project", effective_project_root))
61
68
  roots.extend(
62
69
  [
@@ -879,14 +879,24 @@ def get_installed_bundles(
879
879
 
880
880
  # Bundle name -> (group_name, help_str, build_app_fn) for conditional category mounting.
881
881
  def _build_bundle_to_group() -> dict[str, tuple[str, str, Any]]:
882
- from specfact_cli.groups.backlog_group import build_app as build_backlog_app
883
882
  from specfact_cli.groups.codebase_group import build_app as build_codebase_app
884
883
  from specfact_cli.groups.govern_group import build_app as build_govern_app
884
+ from specfact_cli.groups.member_group import build_member_group
885
885
  from specfact_cli.groups.project_group import build_app as build_project_app
886
886
  from specfact_cli.groups.spec_group import build_app as build_spec_app
887
887
 
888
888
  return {
889
- "specfact-backlog": ("backlog", "Backlog and policy commands.", build_backlog_app),
889
+ "specfact-backlog": (
890
+ "backlog",
891
+ "Backlog and policy commands.",
892
+ lambda: build_member_group(
893
+ name="backlog",
894
+ help_text="Backlog and policy commands.",
895
+ members=(("backlog", "backlog"), ("policy", "policy")),
896
+ flatten_same_name="backlog",
897
+ install_hint_module="nold-ai/specfact-backlog",
898
+ ),
899
+ ),
890
900
  "specfact-codebase": (
891
901
  "code",
892
902
  "Codebase quality commands: analyze, drift, validate, repro.",
@@ -1171,26 +1181,20 @@ def register_module_package_commands(
1171
1181
  if category_grouping_enabled:
1172
1182
  _mount_installed_category_groups(packages, enabled_map)
1173
1183
  discovered_count = protocol_full + protocol_partial + protocol_legacy
1174
- if discovered_count and (protocol_partial > 0 or protocol_legacy > 0):
1175
- print_warning(
1176
- "Module compatibility check: "
1177
- f"{protocol_full + protocol_partial}/{discovered_count} compliant "
1178
- f"(full={protocol_full}, partial={protocol_partial}, legacy={protocol_legacy})."
1184
+ if discovered_count and (protocol_partial > 0 or protocol_legacy > 0) and is_debug_mode():
1185
+ logger.info(
1186
+ "Module compatibility check: %s/%s compliant (full=%s, partial=%s, legacy=%s)",
1187
+ protocol_full + protocol_partial,
1188
+ discovered_count,
1189
+ protocol_full,
1190
+ protocol_partial,
1191
+ protocol_legacy,
1179
1192
  )
1180
1193
  if partial_modules:
1181
1194
  partial_desc = ", ".join(f"{name} ({'/'.join(ops)})" for name, ops in sorted(partial_modules))
1182
- print_warning(f"Partially compliant modules: {partial_desc}")
1195
+ logger.info("Partially compliant modules: %s", partial_desc)
1183
1196
  if legacy_modules:
1184
- print_warning(f"Legacy modules: {', '.join(sorted(set(legacy_modules)))}")
1185
- if is_debug_mode():
1186
- logger.info(
1187
- "Protocol-compliant: %s/%s modules (Full=%s, Partial=%s, Legacy=%s)",
1188
- protocol_full + protocol_partial,
1189
- discovered_count,
1190
- protocol_full,
1191
- protocol_partial,
1192
- protocol_legacy,
1193
- )
1197
+ logger.info("Legacy modules: %s", ", ".join(sorted(set(legacy_modules))))
1194
1198
  for module_id, reason in skipped:
1195
1199
  logger.debug("Skipped module '%s': %s", module_id, reason)
1196
1200
 
@@ -121,10 +121,6 @@ SPECFACT_COMMANDS = [
121
121
  "specfact.06-sync",
122
122
  "specfact.07-contracts",
123
123
  "specfact.compare",
124
- "specfact.sync-backlog",
125
- "specfact.backlog-daily",
126
- "specfact.backlog-refine",
127
- "specfact.backlog-add",
128
124
  "specfact.validate",
129
125
  ]
130
126
 
@@ -0,0 +1,14 @@
1
+ """Validation helpers for release and command-surface audits."""
2
+
3
+ from specfact_cli.validation.command_audit import (
4
+ CommandAuditCase,
5
+ build_command_audit_cases,
6
+ official_marketplace_module_ids,
7
+ )
8
+
9
+
10
+ __all__ = [
11
+ "CommandAuditCase",
12
+ "build_command_audit_cases",
13
+ "official_marketplace_module_ids",
14
+ ]
@@ -0,0 +1,165 @@
1
+ """Helpers for command-package runtime validation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib
6
+ import os
7
+ import sys
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+ from typing import Literal
11
+
12
+
13
+ AuditMode = Literal["help-only", "fixture-backed", "dry-run"]
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class CommandAuditCase:
18
+ """One command-path audit case."""
19
+
20
+ command_path: str
21
+ argv: tuple[str, ...]
22
+ phase: str
23
+ mode: AuditMode
24
+ owner: str
25
+
26
+
27
+ def _resolve_modules_repo_root() -> Path | None:
28
+ configured = os.environ.get("SPECFACT_MODULES_REPO", "").strip()
29
+ if configured:
30
+ candidate = Path(configured).expanduser().resolve()
31
+ if candidate.exists():
32
+ return candidate
33
+
34
+ current = Path(__file__).resolve()
35
+ for parent in current.parents:
36
+ sibling = parent.parent / "specfact-cli-modules"
37
+ if sibling.exists():
38
+ return sibling.resolve()
39
+ direct = parent / "specfact-cli-modules"
40
+ if direct.exists():
41
+ return direct.resolve()
42
+ return None
43
+
44
+
45
+ def _ensure_bundle_sources_on_sys_path() -> None:
46
+ modules_repo = _resolve_modules_repo_root()
47
+ if modules_repo is None:
48
+ return
49
+ packages_root = modules_repo / "packages"
50
+ if not packages_root.exists():
51
+ return
52
+ for bundle_src in packages_root.glob("*/src"):
53
+ bundle_src_str = str(bundle_src.resolve())
54
+ if bundle_src_str not in sys.path:
55
+ sys.path.insert(0, bundle_src_str)
56
+
57
+
58
+ def _command_info_name(command_info: object) -> str:
59
+ explicit_name = getattr(command_info, "name", None)
60
+ if isinstance(explicit_name, str) and explicit_name:
61
+ return explicit_name
62
+ callback = getattr(command_info, "callback", None)
63
+ callback_name = getattr(callback, "__name__", "")
64
+ return callback_name.replace("_", "-") if callback_name else ""
65
+
66
+
67
+ def _collect_typer_paths(app: object, prefix: str) -> set[str]:
68
+ paths: set[str] = set()
69
+
70
+ for command_info in list(getattr(app, "registered_commands", [])):
71
+ command_name = _command_info_name(command_info)
72
+ if command_name:
73
+ paths.add(f"{prefix} {command_name}")
74
+
75
+ for group_info in list(getattr(app, "registered_groups", [])):
76
+ group_name = getattr(group_info, "name", "") or ""
77
+ if not group_name:
78
+ nested_app = getattr(group_info, "typer_instance", None)
79
+ nested_info = getattr(nested_app, "info", None) if nested_app is not None else None
80
+ group_name = getattr(nested_info, "name", "") or ""
81
+ if not group_name:
82
+ continue
83
+ group_prefix = f"{prefix} {group_name}"
84
+ paths.add(group_prefix)
85
+ nested_app = getattr(group_info, "typer_instance", None)
86
+ if nested_app is not None:
87
+ paths.update(_collect_typer_paths(nested_app, group_prefix))
88
+
89
+ return paths
90
+
91
+
92
+ def _import_typer(module_path: str, attr_name: str = "app") -> object:
93
+ module = importlib.import_module(module_path)
94
+ return getattr(module, attr_name)
95
+
96
+
97
+ def official_marketplace_module_ids() -> tuple[str, ...]:
98
+ """Return the official marketplace module ids that make up the full CLI surface."""
99
+ return (
100
+ "nold-ai/specfact-project",
101
+ "nold-ai/specfact-spec",
102
+ "nold-ai/specfact-codebase",
103
+ "nold-ai/specfact-backlog",
104
+ "nold-ai/specfact-govern",
105
+ )
106
+
107
+
108
+ def _explicit_cases() -> list[CommandAuditCase]:
109
+ return [
110
+ CommandAuditCase("specfact", ("--help",), "root", "help-only", "specfact-core"),
111
+ CommandAuditCase("project", ("project", "--help"), "project", "help-only", "nold-ai/specfact-project"),
112
+ CommandAuditCase("spec", ("spec", "--help"), "spec", "help-only", "nold-ai/specfact-spec"),
113
+ CommandAuditCase("code", ("code", "--help"), "code", "help-only", "nold-ai/specfact-codebase"),
114
+ CommandAuditCase("backlog", ("backlog", "--help"), "backlog", "help-only", "nold-ai/specfact-backlog"),
115
+ CommandAuditCase("govern", ("govern", "--help"), "govern", "help-only", "nold-ai/specfact-govern"),
116
+ CommandAuditCase(
117
+ "module init", ("module", "init", "--scope", "user"), "core", "fixture-backed", "specfact-core"
118
+ ),
119
+ CommandAuditCase("module search", ("module", "search", "specfact"), "core", "fixture-backed", "specfact-core"),
120
+ CommandAuditCase("module list", ("module", "list", "--show-origin"), "core", "fixture-backed", "specfact-core"),
121
+ CommandAuditCase(
122
+ "module show",
123
+ ("module", "show", "nold-ai/specfact-backlog"),
124
+ "core",
125
+ "fixture-backed",
126
+ "specfact-core",
127
+ ),
128
+ ]
129
+
130
+
131
+ def build_command_audit_cases() -> list[CommandAuditCase]:
132
+ """Build the full command audit matrix for core and official bundle command paths."""
133
+ _ensure_bundle_sources_on_sys_path()
134
+ app_specs = [
135
+ ("specfact_cli.modules.init.src.commands", "init", "core", "specfact-core", "import"),
136
+ ("specfact_cli.modules.module_registry.src.commands", "module", "core", "specfact-core", "import"),
137
+ ("specfact_cli.modules.upgrade.src.commands", "upgrade", "core", "specfact-core", "import"),
138
+ ("specfact_project.project.commands", "project", "project", "nold-ai/specfact-project", "import"),
139
+ ("specfact_spec.spec.commands", "spec", "spec", "nold-ai/specfact-spec", "import"),
140
+ ("specfact_codebase.code.commands", "code", "code", "nold-ai/specfact-codebase", "import"),
141
+ ("specfact_backlog.backlog.commands", "backlog", "backlog", "nold-ai/specfact-backlog", "import"),
142
+ ("specfact_govern.govern.commands", "govern", "govern", "nold-ai/specfact-govern", "import"),
143
+ ]
144
+
145
+ cases: dict[str, CommandAuditCase] = {case.command_path: case for case in _explicit_cases()}
146
+ for module_path, prefix, phase, owner, _load_mode in app_specs:
147
+ app = _import_typer(module_path)
148
+ cases.setdefault(
149
+ prefix,
150
+ CommandAuditCase(prefix, (*tuple(prefix.split()), "--help"), phase, "help-only", owner),
151
+ )
152
+ for command_path in sorted(_collect_typer_paths(app, prefix)):
153
+ cases.setdefault(
154
+ command_path,
155
+ CommandAuditCase(
156
+ command_path,
157
+ (*tuple(command_path.split()), "--help"),
158
+ phase,
159
+ "help-only",
160
+ owner,
161
+ ),
162
+ )
163
+
164
+ phase_order = {"root": 0, "core": 1, "project": 2, "spec": 3, "code": 4, "backlog": 5, "govern": 6}
165
+ return sorted(cases.values(), key=lambda case: (phase_order.get(case.phase, 99), case.command_path))
@@ -1,90 +0,0 @@
1
- ---
2
- description: "Create backlog items with guided interactive flow and hierarchy checks"
3
- ---
4
-
5
- # SpecFact Backlog Add Command
6
-
7
- ## User Input
8
-
9
- ```text
10
- $ARGUMENTS
11
- ```
12
-
13
- You **MUST** consider the user input before proceeding (if not empty).
14
-
15
- ## Purpose
16
-
17
- Create a new backlog item in GitHub or Azure DevOps using the `specfact backlog add` workflow. The command supports interactive prompts, parent hierarchy validation, DoR checks, and provider-specific fields.
18
-
19
- **When to use:** Adding new work items (epic/feature/story/task/bug) with consistent quality and parent-child structure.
20
-
21
- **Quick:** `/specfact.backlog-add --adapter github --project-id owner/repo --type story --title "..."`
22
-
23
- ## Parameters
24
-
25
- ### Required
26
-
27
- - `--adapter ADAPTER` - Backlog adapter (`github`, `ado`)
28
- - `--project-id PROJECT` - Project context
29
- - GitHub: `owner/repo`
30
- - ADO: `org/project`
31
-
32
- ### Common options
33
-
34
- - `--type TYPE` - Backlog item type (provider/template specific)
35
- - `--title TITLE` - Item title
36
- - `--body BODY` - Item body/description
37
- - `--parent PARENT_ID` - Optional parent issue/work item id
38
- - `--non-interactive` - Disable prompt flow and require explicit inputs
39
- - `--check-dor` - Run Definition of Ready checks before create
40
- - `--template TEMPLATE` - Optional backlog template override
41
- - `--custom-config PATH` - Optional mapping/config override file
42
-
43
- ### Adapter-specific options
44
-
45
- - GitHub:
46
- - `--repo-owner OWNER`
47
- - `--repo-name NAME`
48
- - `--github-token TOKEN` (or `GITHUB_TOKEN`)
49
- - Azure DevOps:
50
- - `--ado-org ORG`
51
- - `--ado-project PROJECT`
52
- - `--ado-token TOKEN` (or `AZURE_DEVOPS_TOKEN`)
53
- - `--ado-base-url URL` (optional)
54
-
55
- ## Workflow
56
-
57
- ### Step 1: Execute command
58
-
59
- Run the CLI command with user arguments:
60
-
61
- ```bash
62
- specfact backlog add [OPTIONS]
63
- ```
64
-
65
- ### Step 2: Interactive completion (if inputs are missing)
66
-
67
- - Prompt for missing required fields.
68
- - Prompt for optional quality fields (acceptance criteria, points, priority) when supported.
69
- - Validate parent selection and allowed hierarchy before create.
70
-
71
- ### Step 3: Confirm and create
72
-
73
- - Show planned create payload summary.
74
- - Execute provider create operation.
75
- - Return created item id/key/url.
76
-
77
- ## CLI Enforcement
78
-
79
- - Always execute `specfact backlog add` for creation.
80
- - Do not create provider issues/work items directly outside CLI unless user explicitly requests a manual path.
81
-
82
- ## Input Contract
83
-
84
- - This command does not use `--export-to-tmp`/`--import-from-tmp` artifacts.
85
- - Provide values through CLI options or interactive prompts; do not fabricate external tmp-file schemas.
86
- - Do not ask Copilot to output `## Item N:` sections, `**ID**` labels, or markdown tmp files for this command.
87
-
88
- ## Context
89
-
90
- {ARGS}