specfact-cli 0.43.3__tar.gz → 0.44.0__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 (275) hide show
  1. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/PKG-INFO +1 -1
  2. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/pyproject.toml +1 -1
  3. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/__init__.py +1 -1
  4. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/speckit.py +1 -1
  5. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/analyze_agent.py +1 -1
  6. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/ambiguity_scanner.py +3 -3
  7. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/code_analyzer.py +2 -2
  8. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/contract_extractor.py +3 -3
  9. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/graph_analyzer.py +2 -2
  10. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/relationship_mapper.py +2 -2
  11. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/logger_setup.py +2 -2
  12. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/enrichers/constitution_enricher.py +5 -5
  13. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/persona_exporter.py +2 -2
  14. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/_bundle_import.py +7 -3
  15. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/init/module-package.yaml +3 -3
  16. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/init/src/commands.py +0 -50
  17. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/module_io_shim.py +0 -4
  18. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/bootstrap.py +1 -1
  19. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_packages.py +0 -19
  20. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync.py +4 -4
  21. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/spec_to_code.py +1 -1
  22. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/context_detection.py +2 -2
  23. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/progress.py +3 -3
  24. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/progressive_disclosure.py +0 -16
  25. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/source_scanner.py +2 -2
  26. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/structure.py +2 -2
  27. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/dependency_installer.py +1 -1
  28. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/orchestrator.py +1 -1
  29. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/.gitignore +0 -0
  30. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/LICENSE +0 -0
  31. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/README.md +0 -0
  32. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/keys/README.md +0 -0
  33. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/keys/module-signing-public.pem +0 -0
  34. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/mappings/node-async.yaml +0 -0
  35. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/mappings/python-async.yaml +0 -0
  36. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/mappings/speckit-default.yaml +0 -0
  37. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/schemas/deviation.schema.json +0 -0
  38. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/schemas/plan.schema.json +0 -0
  39. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/schemas/protocol.schema.json +0 -0
  40. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/github-action.yml.j2 +0 -0
  41. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/persona/architect.md.j2 +0 -0
  42. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/persona/developer.md.j2 +0 -0
  43. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/persona/product-owner.md.j2 +0 -0
  44. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/plan.bundle.yaml.j2 +0 -0
  45. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/policies/kanban.yaml +0 -0
  46. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/policies/mixed.yaml +0 -0
  47. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/policies/safe.yaml +0 -0
  48. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/policies/scrum.yaml +0 -0
  49. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/pr-template.md.j2 +0 -0
  50. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/protocol.yaml.j2 +0 -0
  51. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/resources/templates/telemetry.yaml.example +0 -0
  52. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/__init__.py +0 -0
  53. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/__main__.py +0 -0
  54. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/__init__.py +0 -0
  55. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/ado.py +0 -0
  56. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/backlog_base.py +0 -0
  57. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/base.py +0 -0
  58. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/github.py +0 -0
  59. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/openspec.py +0 -0
  60. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/openspec_parser.py +0 -0
  61. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/adapters/registry.py +0 -0
  62. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/__init__.py +0 -0
  63. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/base.py +0 -0
  64. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/plan_agent.py +0 -0
  65. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/registry.py +0 -0
  66. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/agents/sync_agent.py +0 -0
  67. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/__init__.py +0 -0
  68. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
  69. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
  70. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
  71. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
  72. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/__init__.py +0 -0
  73. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/adapters/__init__.py +0 -0
  74. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/adapters/base.py +0 -0
  75. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/converter.py +0 -0
  76. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/filters.py +0 -0
  77. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
  78. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/mappers/ado_mapper.py +0 -0
  79. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/mappers/base.py +0 -0
  80. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
  81. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
  82. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/cli.py +0 -0
  83. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/__init__.py +0 -0
  84. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/_bundle_shim.py +0 -0
  85. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/analyze.py +0 -0
  86. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/contract_cmd.py +0 -0
  87. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/drift.py +0 -0
  88. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/enforce.py +0 -0
  89. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/generate.py +0 -0
  90. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/import_cmd.py +0 -0
  91. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/init.py +0 -0
  92. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/migrate.py +0 -0
  93. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/plan.py +0 -0
  94. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/project_cmd.py +0 -0
  95. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/repro.py +0 -0
  96. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/sdd.py +0 -0
  97. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/spec.py +0 -0
  98. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/sync.py +0 -0
  99. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/update.py +0 -0
  100. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/commands/validate.py +0 -0
  101. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/__init__.py +0 -0
  102. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/bundle_factory.py +0 -0
  103. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/logging_utils.py +0 -0
  104. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/text_utils.py +0 -0
  105. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/common/utils.py +0 -0
  106. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/comparators/__init__.py +0 -0
  107. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/comparators/plan_comparator.py +0 -0
  108. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/contracts/__init__.py +0 -0
  109. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/contracts/crosshair_props.py +0 -0
  110. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/contracts/module_interface.py +0 -0
  111. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
  112. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/__init__.py +0 -0
  113. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/contract_generator.py +0 -0
  114. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/openapi_extractor.py +0 -0
  115. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/plan_generator.py +0 -0
  116. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/protocol_generator.py +0 -0
  117. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/report_generator.py +0 -0
  118. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/task_generator.py +0 -0
  119. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/test_to_openapi.py +0 -0
  120. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/generators/workflow_generator.py +0 -0
  121. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/__init__.py +0 -0
  122. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/codebase_group.py +0 -0
  123. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/govern_group.py +0 -0
  124. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/member_group.py +0 -0
  125. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/project_group.py +0 -0
  126. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/groups/spec_group.py +0 -0
  127. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/importers/__init__.py +0 -0
  128. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/importers/speckit_converter.py +0 -0
  129. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/importers/speckit_scanner.py +0 -0
  130. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/integrations/__init__.py +0 -0
  131. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/integrations/specmatic.py +0 -0
  132. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/merge/__init__.py +0 -0
  133. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/merge/resolver.py +0 -0
  134. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/migrations/__init__.py +0 -0
  135. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/migrations/plan_migrator.py +0 -0
  136. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/__init__.py +0 -0
  137. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/backlog_item.py +0 -0
  138. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/bridge.py +0 -0
  139. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/capabilities.py +0 -0
  140. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/change.py +0 -0
  141. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/contract.py +0 -0
  142. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/deviation.py +0 -0
  143. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/dor_config.py +0 -0
  144. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/enforcement.py +0 -0
  145. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/module_package.py +0 -0
  146. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/persona_template.py +0 -0
  147. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/plan.py +0 -0
  148. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/project.py +0 -0
  149. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/protocol.py +0 -0
  150. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/quality.py +0 -0
  151. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/sdd.py +0 -0
  152. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/source_tracking.py +0 -0
  153. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/task.py +0 -0
  154. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/models/validation.py +0 -0
  155. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modes/__init__.py +0 -0
  156. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modes/detector.py +0 -0
  157. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modes/router.py +0 -0
  158. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/__init__.py +0 -0
  159. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/init/src/__init__.py +0 -0
  160. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/init/src/app.py +0 -0
  161. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/init/src/first_run_selection.py +0 -0
  162. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/module_registry/module-package.yaml +0 -0
  163. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/module_registry/src/__init__.py +0 -0
  164. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/module_registry/src/app.py +0 -0
  165. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/module_registry/src/commands.py +0 -0
  166. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/upgrade/module-package.yaml +0 -0
  167. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/upgrade/src/__init__.py +0 -0
  168. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/upgrade/src/app.py +0 -0
  169. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/modules/upgrade/src/commands.py +0 -0
  170. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/parsers/__init__.py +0 -0
  171. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/parsers/persona_importer.py +0 -0
  172. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/__init__.py +0 -0
  173. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/alias_manager.py +0 -0
  174. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/bridge_registry.py +0 -0
  175. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/crypto_validator.py +0 -0
  176. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/custom_registries.py +0 -0
  177. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/dependency_resolver.py +0 -0
  178. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/extension_registry.py +0 -0
  179. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/help_cache.py +0 -0
  180. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/marketplace_client.py +0 -0
  181. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/metadata.py +0 -0
  182. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_discovery.py +0 -0
  183. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_grouping.py +0 -0
  184. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_installer.py +0 -0
  185. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_lifecycle.py +0 -0
  186. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_security.py +0 -0
  187. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/module_state.py +0 -0
  188. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/registry/registry.py +0 -0
  189. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/resources/semgrep/async.yml +0 -0
  190. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
  191. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
  192. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/runtime.py +0 -0
  193. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/__init__.py +0 -0
  194. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_probe.py +0 -0
  195. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_openspec_md_parse.py +0 -0
  196. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_requirement_from_proposal.py +0 -0
  197. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_requirement_helpers.py +0 -0
  198. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_tasks_from_proposal.py +0 -0
  199. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_what_changes_format.py +0 -0
  200. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_sync_write_openspec_from_proposal.py +0 -0
  201. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/bridge_watch.py +0 -0
  202. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/change_detector.py +0 -0
  203. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/code_to_spec.py +0 -0
  204. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/drift_detector.py +0 -0
  205. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/repository_sync.py +0 -0
  206. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/spec_to_tests.py +0 -0
  207. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/watcher.py +0 -0
  208. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
  209. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/telemetry.py +0 -0
  210. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/__init__.py +0 -0
  211. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -0
  212. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -0
  213. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -0
  214. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -0
  215. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -0
  216. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -0
  217. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -0
  218. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/registry.py +0 -0
  219. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/templates/specification_templates.py +0 -0
  220. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/__init__.py +0 -0
  221. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
  222. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/auth_tokens.py +0 -0
  223. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/bundle_converters.py +0 -0
  224. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/bundle_loader.py +0 -0
  225. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/code_change_detector.py +0 -0
  226. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/console.py +0 -0
  227. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/content_sanitizer.py +0 -0
  228. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/contract_predicates.py +0 -0
  229. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/enrichment_context.py +0 -0
  230. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/enrichment_parser.py +0 -0
  231. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/env_manager.py +0 -0
  232. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/feature_keys.py +0 -0
  233. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/git.py +0 -0
  234. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/github_annotations.py +0 -0
  235. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/icontract_helpers.py +0 -0
  236. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/ide_setup.py +0 -0
  237. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/incremental_check.py +0 -0
  238. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/metadata.py +0 -0
  239. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/optional_deps.py +0 -0
  240. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/performance.py +0 -0
  241. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/persona_ownership.py +0 -0
  242. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/prompts.py +0 -0
  243. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/sdd_discovery.py +0 -0
  244. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/startup_checks.py +0 -0
  245. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/structured_io.py +0 -0
  246. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/suggestions.py +0 -0
  247. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/terminal.py +0 -0
  248. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/utils/yaml_utils.py +0 -0
  249. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validation/__init__.py +0 -0
  250. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validation/command_audit.py +0 -0
  251. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/__init__.py +0 -0
  252. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/agile_validation.py +0 -0
  253. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
  254. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/cli_first_validator.py +0 -0
  255. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/contract_validator.py +0 -0
  256. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/fsm.py +0 -0
  257. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/repro_checker.py +0 -0
  258. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/schema.py +0 -0
  259. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
  260. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
  261. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
  262. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
  263. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
  264. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
  265. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
  266. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
  267. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
  268. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
  269. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
  270. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
  271. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/models.py +0 -0
  272. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
  273. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
  274. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/src/specfact_cli/versioning/__init__.py +0 -0
  275. {specfact_cli-0.43.3 → specfact_cli-0.44.0}/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.43.3
3
+ Version: 0.44.0
4
4
  Summary: The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases.
5
5
  Project-URL: Homepage, https://github.com/nold-ai/specfact-cli
6
6
  Project-URL: Repository, https://github.com/nold-ai/specfact-cli.git
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "specfact-cli"
7
- version = "0.43.3"
7
+ version = "0.44.0"
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"
@@ -45,6 +45,6 @@ def _bootstrap_bundle_paths() -> None:
45
45
 
46
46
  _bootstrap_bundle_paths()
47
47
 
48
- __version__ = "0.43.3"
48
+ __version__ = "0.44.0"
49
49
 
50
50
  __all__ = ["__version__"]
@@ -426,7 +426,7 @@ class SpecKitAdapter(BridgeAdapter):
426
426
  )
427
427
  if title_match:
428
428
  feature_title = title_match.group(1).strip()
429
- except Exception:
429
+ except (OSError, UnicodeDecodeError):
430
430
  pass
431
431
  if not feature_title or feature_title.strip() == "":
432
432
  return "Unknown Feature"
@@ -262,7 +262,7 @@ Focus on semantic understanding, not just structural parsing. Generate the plan
262
262
  try:
263
263
  content = dep_file.read_text(encoding="utf-8")[:500]
264
264
  dependencies.append(f"{dep_file.name}: {content[:100]}...")
265
- except Exception:
265
+ except (OSError, UnicodeDecodeError):
266
266
  pass
267
267
  return dependencies
268
268
 
@@ -772,7 +772,7 @@ class AmbiguityScanner:
772
772
  continue
773
773
  if user_clean and len(user_clean) > 2 and user_lower not in excluded and len(user_clean.split()) <= 3:
774
774
  result.add(user_clean.title())
775
- except Exception:
775
+ except (OSError, UnicodeDecodeError, re.error):
776
776
  pass
777
777
  return result
778
778
 
@@ -898,9 +898,9 @@ class AmbiguityScanner:
898
898
  continue
899
899
  try:
900
900
  self._personas_from_py_file(py_file, result, excluded)
901
- except Exception:
901
+ except (OSError, UnicodeDecodeError, re.error):
902
902
  continue
903
- except Exception:
903
+ except (OSError, UnicodeDecodeError, re.error):
904
904
  pass
905
905
  return result
906
906
 
@@ -1794,14 +1794,14 @@ class CodeAnalyzer:
1794
1794
  for commit in commits:
1795
1795
  try:
1796
1796
  self._process_commit_for_feature_bounds(commit)
1797
- except Exception:
1797
+ except (OSError, ValueError):
1798
1798
  # Skip individual commits that fail (corrupted, etc.)
1799
1799
  continue
1800
1800
 
1801
1801
  except ImportError:
1802
1802
  # GitPython not available, skip
1803
1803
  pass
1804
- except Exception:
1804
+ except OSError:
1805
1805
  # Git operations failed, skip gracefully
1806
1806
  pass
1807
1807
 
@@ -240,7 +240,7 @@ class ContractExtractor:
240
240
  if hasattr(ast, "unparse"):
241
241
  try:
242
242
  return ast.unparse(node)
243
- except Exception:
243
+ except (ValueError, TypeError):
244
244
  pass
245
245
 
246
246
  # Fallback: manual conversion
@@ -282,7 +282,7 @@ class ContractExtractor:
282
282
  if hasattr(ast, "unparse"):
283
283
  try:
284
284
  return ast.unparse(node)
285
- except Exception:
285
+ except (ValueError, TypeError):
286
286
  pass
287
287
 
288
288
  return "..."
@@ -295,7 +295,7 @@ class ContractExtractor:
295
295
  if hasattr(ast, "unparse"):
296
296
  try:
297
297
  return ast.unparse(node)
298
- except Exception:
298
+ except (ValueError, TypeError):
299
299
  pass
300
300
 
301
301
  # Fallback: basic conversion
@@ -178,7 +178,7 @@ class GraphAnalyzer:
178
178
  edges = future.result()
179
179
  for module_name, matching_module in edges:
180
180
  graph.add_edge(module_name, matching_module)
181
- except Exception:
181
+ except (OSError, RuntimeError):
182
182
  pass
183
183
  completed += 1
184
184
  if progress_callback:
@@ -211,7 +211,7 @@ class GraphAnalyzer:
211
211
  callee_module = self._resolve_module_from_function(callee, python_files)
212
212
  if callee_module and callee_module in graph:
213
213
  graph.add_edge(module_name, callee_module)
214
- except Exception:
214
+ except (OSError, RuntimeError):
215
215
  pass
216
216
  completed += 1
217
217
  if progress_callback:
@@ -306,7 +306,7 @@ class RelationshipMapper:
306
306
  if file_hash:
307
307
  self.analysis_cache[file_hash] = empty_result
308
308
  return (file_key, empty_result)
309
- except Exception:
309
+ except (OSError, PermissionError):
310
310
  pass
311
311
 
312
312
  try:
@@ -354,7 +354,7 @@ class RelationshipMapper:
354
354
  if not f.done():
355
355
  f.cancel()
356
356
  raise
357
- except Exception:
357
+ except (OSError, ValueError):
358
358
  pass
359
359
  completed_count += 1
360
360
  if progress_callback:
@@ -426,11 +426,11 @@ class LoggerSetup:
426
426
  log_file_path = os.path.join(logs_dir, log_file)
427
427
 
428
428
  log_file_dir = os.path.dirname(log_file_path)
429
- os.makedirs(log_file_dir, mode=0o777, exist_ok=True)
429
+ os.makedirs(log_file_dir, mode=0o755, exist_ok=True)
430
430
  try:
431
431
  with open(log_file_path, "a", encoding="utf-8"):
432
432
  pass
433
- except Exception:
433
+ except OSError:
434
434
  pass
435
435
 
436
436
  try:
@@ -145,7 +145,7 @@ class ConstitutionEnricher:
145
145
  # Simple dependency name without version constraints
146
146
  result["technology_stack"].append(dep)
147
147
 
148
- except Exception:
148
+ except (OSError, UnicodeDecodeError, ValueError):
149
149
  pass # If parsing fails, return empty result
150
150
 
151
151
  return result
@@ -190,7 +190,7 @@ class ConstitutionEnricher:
190
190
  else:
191
191
  result["technology_stack"].append(dep)
192
192
 
193
- except Exception:
193
+ except (OSError, UnicodeDecodeError, ValueError):
194
194
  pass
195
195
 
196
196
  return result
@@ -235,7 +235,7 @@ class ConstitutionEnricher:
235
235
  users = [u.strip() for u in re.split(r"[,;]", users_text)]
236
236
  result["target_users"] = users[:5]
237
237
 
238
- except Exception:
238
+ except (OSError, UnicodeDecodeError, ValueError):
239
239
  pass
240
240
 
241
241
  return result
@@ -265,7 +265,7 @@ class ConstitutionEnricher:
265
265
  # Extract principles from headings and key sections
266
266
  extracted = self._extract_principles_from_markdown(content, rule_file)
267
267
  principles.extend(extracted)
268
- except Exception:
268
+ except (OSError, UnicodeDecodeError, ValueError):
269
269
  pass
270
270
 
271
271
  return principles
@@ -293,7 +293,7 @@ class ConstitutionEnricher:
293
293
  # Extract quality standards
294
294
  extracted = self._extract_quality_standards(content)
295
295
  standards.extend(extracted)
296
- except Exception:
296
+ except (OSError, UnicodeDecodeError, ValueError):
297
297
  pass
298
298
 
299
299
  return standards
@@ -242,7 +242,7 @@ class PersonaExporter:
242
242
  protocol_data = load_structured_file(protocol_file)
243
243
  protocol_name = protocol_file.stem.replace(".protocol", "")
244
244
  protocols[protocol_name] = protocol_data
245
- except Exception:
245
+ except (OSError, ValueError):
246
246
  pass
247
247
  return protocols
248
248
 
@@ -267,7 +267,7 @@ class PersonaExporter:
267
267
  contract_data = load_structured_file(contract_file)
268
268
  contract_name = contract_file.stem.replace(".openapi", "").replace(".asyncapi", "")
269
269
  contracts[contract_name] = contract_data
270
- except Exception:
270
+ except (OSError, ValueError):
271
271
  pass
272
272
  return contracts
273
273
 
@@ -19,9 +19,13 @@ def bootstrap_local_bundle_sources(anchor_file: str) -> None:
19
19
  anchor = Path(anchor_file).resolve()
20
20
  candidates: list[Path] = []
21
21
 
22
- env_repo = os.environ.get("SPECFACT_CLI_MODULES_REPO")
23
- if env_repo:
24
- candidates.append(Path(env_repo).expanduser().resolve())
22
+ for env_name in ("SPECFACT_CLI_MODULES_REPO", "SPECFACT_MODULES_REPO"):
23
+ env_repo = os.environ.get(env_name)
24
+ if not env_repo:
25
+ continue
26
+ candidate = Path(env_repo).expanduser().resolve()
27
+ if candidate not in candidates:
28
+ candidates.append(candidate)
25
29
 
26
30
  for parent in anchor.parents:
27
31
  # Primary dev layout: .../nold-ai/specfact-cli-worktrees/... and sibling specfact-cli-modules
@@ -1,5 +1,5 @@
1
1
  name: init
2
- version: 0.1.19
2
+ version: 0.1.21
3
3
  commands:
4
4
  - init
5
5
  category: core
@@ -17,5 +17,5 @@ publisher:
17
17
  description: Initialize SpecFact workspace and bootstrap local configuration.
18
18
  license: Apache-2.0
19
19
  integrity:
20
- checksum: sha256:a0ca0fb136f278a11a113be78047c3c7037de9a393c27f8e677a26c4ab2ba659
21
- signature: r3czsyG/tinaxMTd/lNkhjXQqRUU0ecLywXt1iDWPO0QuExVM+msp5tuAud03QPnuCsMXNdyBWWSDBovPeY+Aw==
20
+ checksum: sha256:925fd303b581441618597b5fa5d7f308cbc31405455ae7811243c072616974bf
21
+ signature: uMDekXAxcKEDb8V1rqEeL8X806bP4otT5rT5ShXFlUNjcJ06c90s7xg1KqTNYj/eVsuh07xKSGnWKo1BG6juAw==
@@ -13,7 +13,6 @@ from icontract import ensure, require
13
13
  from rich.console import Console
14
14
  from rich.panel import Panel
15
15
  from rich.rule import Rule
16
- from rich.table import Table
17
16
 
18
17
  from specfact_cli import __version__
19
18
  from specfact_cli.contracts.module_interface import ModuleIOContract
@@ -222,21 +221,6 @@ def _questionary_style() -> Any:
222
221
  )
223
222
 
224
223
 
225
- def _render_modules_table(modules_list: list[dict[str, Any]]) -> None:
226
- """Render discovered modules with effective enabled/disabled state."""
227
- table = Table(title="Installed Modules")
228
- table.add_column("Module", style="cyan")
229
- table.add_column("Version", style="magenta")
230
- table.add_column("State", style="green")
231
- for module in modules_list:
232
- module_id = str(module.get("id", ""))
233
- version = str(module.get("version", ""))
234
- enabled = bool(module.get("enabled", True))
235
- state = "enabled" if enabled else "disabled"
236
- table.add_row(module_id, version, state)
237
- console.print(table)
238
-
239
-
240
224
  def _module_checkbox_rows(candidates: list[dict[str, Any]]) -> tuple[dict[str, str], list[str]]:
241
225
  display_to_id: dict[str, str] = {}
242
226
  choices: list[str] = []
@@ -274,40 +258,6 @@ def _run_module_checkbox_prompt(
274
258
  return [display_to_id[s] for s in selected if s in display_to_id]
275
259
 
276
260
 
277
- def _select_module_ids_interactive(action: str, modules_list: list[dict[str, Any]]) -> list[str]:
278
- """Select one or more module IDs interactively via arrow-key checkbox menu."""
279
- try:
280
- import questionary # type: ignore[reportMissingImports]
281
- except ImportError as e:
282
- console.print(
283
- "[red]Interactive module selection requires 'questionary'. Install with: pip install questionary[/red]"
284
- )
285
- raise typer.Exit(1) from e
286
-
287
- target_enabled = action == "disable"
288
- candidates = [m for m in modules_list if bool(m.get("enabled", True)) is target_enabled]
289
- if not candidates:
290
- console.print(f"[yellow]No modules available to {action}.[/yellow]")
291
- return []
292
-
293
- action_title = "Enable" if action == "enable" else "Disable"
294
- current_state = "disabled" if action == "enable" else "enabled"
295
- console.print()
296
- console.print(
297
- Panel(
298
- f"[bold cyan]{action_title} Modules[/bold cyan]\n"
299
- f"Choose one or more currently [bold]{current_state}[/bold] modules.",
300
- border_style="cyan",
301
- )
302
- )
303
- console.print(
304
- "[dim]Controls: ↑↓ navigate • Space toggle • Enter confirm • Type to search/filter • Ctrl+C cancel[/dim]"
305
- )
306
-
307
- display_to_id, choices = _module_checkbox_rows(candidates)
308
- return _run_module_checkbox_prompt(action, display_to_id, choices, questionary)
309
-
310
-
311
261
  def _resolve_templates_dir(repo_path: Path) -> Path | None:
312
262
  """Resolve a representative templates directory from installed modules or a dev repo checkout."""
313
263
  prompt_files = discover_prompt_template_files(repo_path, include_package_fallback=True)
@@ -17,10 +17,6 @@ def _import_source_exists(source: Path) -> bool:
17
17
  return source.exists()
18
18
 
19
19
 
20
- def _export_target_exists(target: Path) -> bool:
21
- return target.exists()
22
-
23
-
24
20
  def _external_source_nonempty(external_source: str) -> bool:
25
21
  return len(external_source.strip()) > 0
26
22
 
@@ -41,7 +41,7 @@ def _get_category_grouping_enabled() -> bool:
41
41
  return val
42
42
  if isinstance(val, str):
43
43
  return val.strip().lower() in ("1", "true", "yes")
44
- except Exception:
44
+ except (OSError, ValueError):
45
45
  pass
46
46
  return True
47
47
 
@@ -742,25 +742,6 @@ def _check_protocol_compliance(module_class: Any) -> list[str]:
742
742
  return operations
743
743
 
744
744
 
745
- @beartype
746
- @require(lambda package_name: cast(str, package_name).strip() != "", "Package name must not be empty")
747
- @ensure(lambda result: result is not None, "Protocol inspection target must be resolved")
748
- def _resolve_protocol_target(module_obj: Any, package_name: str) -> Any:
749
- """Resolve runtime interface used for protocol inspection."""
750
- runtime_interface = getattr(module_obj, "runtime_interface", None)
751
- if runtime_interface is not None:
752
- return runtime_interface
753
- commands_interface = getattr(module_obj, "commands", None)
754
- if commands_interface is not None:
755
- return commands_interface
756
- # Module app entrypoints often only expose `app`; load module-local commands for protocol detection.
757
- try:
758
- return importlib.import_module(f"specfact_cli.modules.{package_name}.src.commands")
759
- except Exception:
760
- pass
761
- return module_obj
762
-
763
-
764
745
  def _resolve_protocol_source_paths(
765
746
  package_dir: Path,
766
747
  package_name: str,
@@ -67,7 +67,7 @@ def _code_repo_from_cwd(repo_name: str) -> Path | None:
67
67
  )
68
68
  if result.returncode == 0 and repo_name in result.stdout:
69
69
  return cwd
70
- except Exception:
70
+ except (OSError, ValueError):
71
71
  pass
72
72
  return None
73
73
 
@@ -79,7 +79,7 @@ def _code_repo_from_parent(repo_name: str) -> Path | None:
79
79
  repo_path = cwd.parent / repo_name
80
80
  if repo_path.exists() and (repo_path / ".git").exists():
81
81
  return repo_path
82
- except Exception:
82
+ except (OSError, ValueError):
83
83
  pass
84
84
  return None
85
85
 
@@ -94,7 +94,7 @@ def _code_repo_from_grandparent_siblings(repo_name: str) -> Path | None:
94
94
  for sibling in grandparent.iterdir():
95
95
  if sibling.is_dir() and sibling.name == repo_name and (sibling / ".git").exists():
96
96
  return sibling
97
- except Exception:
97
+ except (OSError, ValueError):
98
98
  pass
99
99
  return None
100
100
 
@@ -1498,7 +1498,7 @@ class BridgeSync:
1498
1498
  parsed_hostname: str | None = cast(str | None, parsed.hostname)
1499
1499
  if parsed_hostname and parsed_hostname.lower() == "dev.azure.com":
1500
1500
  pass
1501
- except Exception:
1501
+ except ValueError:
1502
1502
  pass
1503
1503
 
1504
1504
  def _collect_source_tracking_entries_from_proposal_text(self, proposal_content: str) -> list[dict[str, Any]]:
@@ -220,7 +220,7 @@ class SpecToCodeSync:
220
220
  data = cast(dict[str, Any], _tomli.load(f))
221
221
  if "project" in data and "dependencies" in data["project"]:
222
222
  dependencies.extend(data["project"]["dependencies"])
223
- except Exception:
223
+ except (ImportError, OSError, ValueError):
224
224
  pass # Ignore parsing errors
225
225
 
226
226
  return dependencies
@@ -208,7 +208,7 @@ def _detect_python_framework(repo_path: Path, context: ProjectContext) -> None:
208
208
  context.framework = "flask"
209
209
  elif "fastapi" in content:
210
210
  context.framework = "fastapi"
211
- except Exception:
211
+ except (OSError, UnicodeDecodeError):
212
212
  pass
213
213
 
214
214
 
@@ -225,7 +225,7 @@ def _detect_js_framework(repo_path: Path, context: ProjectContext) -> None:
225
225
  context.framework = "react"
226
226
  elif "vue" in deps:
227
227
  context.framework = "vue"
228
- except Exception:
228
+ except (OSError, json.JSONDecodeError):
229
229
  pass
230
230
 
231
231
 
@@ -45,7 +45,7 @@ def _safe_progress_display(display_console: Console) -> bool:
45
45
  # Rich stores active Live displays in Console._live
46
46
  if hasattr(display_console, "_live") and display_console._live is not None:
47
47
  return False
48
- except Exception:
48
+ except AttributeError:
49
49
  pass
50
50
 
51
51
  return True
@@ -149,7 +149,7 @@ def load_bundle_with_progress(
149
149
  # Brief pause to show completion
150
150
  time.sleep(0.1)
151
151
  return bundle
152
- except Exception:
152
+ except (RuntimeError, OSError):
153
153
  # If Progress creation fails (e.g., LiveError), fall back to direct load
154
154
  pass
155
155
 
@@ -222,7 +222,7 @@ def save_bundle_with_progress(
222
222
  # Brief pause to show completion
223
223
  time.sleep(0.1)
224
224
  return
225
- except Exception:
225
+ except (RuntimeError, OSError):
226
226
  # If Progress creation fails (e.g., LiveError), fall back to direct save
227
227
  pass
228
228
 
@@ -82,22 +82,6 @@ def intercept_help_advanced() -> None:
82
82
  sys.argv[:] = normalized_args
83
83
 
84
84
 
85
- @beartype
86
- def _is_help_context(ctx: ClickContext | None) -> bool:
87
- """Check if this context is for showing help."""
88
- if ctx is None:
89
- return False
90
- # Check if help was requested by looking at params or info_name
91
- if hasattr(ctx, "params") and ctx.params:
92
- # Check if any help option is in params
93
- for param in ctx.params.values() if isinstance(ctx.params, dict) else []:
94
- param_name = getattr(param, "name", None)
95
- if param_name and param_name in ("--help", "-h", "--help-advanced", "-ha"):
96
- return True
97
- # Check info_name for help indicators
98
- return bool(hasattr(ctx, "info_name") and ctx.info_name and "help" in str(ctx.info_name).lower())
99
-
100
-
101
85
  @beartype
102
86
  def _is_advanced_help_context(ctx: ClickContext | None) -> bool:
103
87
  """Check if this context is for showing advanced help."""
@@ -512,7 +512,7 @@ class SourceArtifactScanner:
512
512
  source_tracking = SourceTracking()
513
513
  source_tracking.update_hash(file_path)
514
514
  file_hashes_cache[rel_path] = source_tracking.file_hashes.get(rel_path, "")
515
- except Exception:
515
+ except (OSError, ValueError):
516
516
  pass
517
517
 
518
518
  def _index_test_file_for_link_cache(
@@ -552,7 +552,7 @@ class SourceArtifactScanner:
552
552
  source_tracking = SourceTracking()
553
553
  source_tracking.update_hash(file_path)
554
554
  file_hashes_cache[rel_path] = source_tracking.file_hashes.get(rel_path, "")
555
- except Exception:
555
+ except (OSError, ValueError):
556
556
  pass
557
557
 
558
558
  def _run_parallel_feature_linking(
@@ -252,7 +252,7 @@ class SpecFactStructure:
252
252
  bundle_dir = base_path / cls.PROJECTS / active_bundle
253
253
  if bundle_dir.exists() and (bundle_dir / "bundle.manifest.yaml").exists():
254
254
  return bundle_dir
255
- except Exception:
255
+ except (OSError, ValueError):
256
256
  # Fallback if config read fails
257
257
  pass
258
258
 
@@ -302,7 +302,7 @@ class SpecFactStructure:
302
302
  active_bundle = config.get(cls.ACTIVE_BUNDLE_CONFIG_KEY)
303
303
  if active_bundle:
304
304
  return active_bundle
305
- except Exception:
305
+ except (OSError, ValueError):
306
306
  # Fallback if config read fails
307
307
  pass
308
308
 
@@ -55,7 +55,7 @@ def create_sidecar_venv(venv_path: Path, repo_path: Path) -> bool:
55
55
  if result.returncode == 0:
56
56
  # Venv exists and works, skip recreation
57
57
  return True
58
- except Exception:
58
+ except (OSError, subprocess.SubprocessError):
59
59
  # Venv exists but Python can't run (e.g., libpython issue)
60
60
  # Delete and recreate
61
61
  pass
@@ -51,7 +51,7 @@ def _should_use_progress(console: Console) -> bool:
51
51
  try:
52
52
  if hasattr(console, "_live") and console._live is not None:
53
53
  return False
54
- except Exception:
54
+ except AttributeError:
55
55
  pass
56
56
  return True
57
57
 
File without changes
File without changes
File without changes