ara-cli 0.1.9.69__tar.gz → 0.1.9.70__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.

Potentially problematic release.


This version of ara-cli might be problematic. Click here for more details.

Files changed (166) hide show
  1. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/PKG-INFO +1 -1
  2. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/ara_command_action.py +6 -2
  3. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/ara_config.py +21 -7
  4. ara_cli-0.1.9.70/ara_cli/artefact_autofix.py +446 -0
  5. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_fuzzy_search.py +9 -4
  6. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/feature_artefact_model.py +72 -18
  7. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_reader.py +4 -3
  8. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_scan.py +27 -2
  9. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/file_classifier.py +2 -2
  10. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/prompt_handler.py +9 -10
  11. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/version.py +1 -1
  12. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/PKG-INFO +1 -1
  13. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/SOURCES.txt +1 -1
  14. ara_cli-0.1.9.69/tests/test_ara_autofix.py → ara_cli-0.1.9.70/tests/test_artefact_autofix.py +163 -29
  15. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_scan.py +50 -17
  16. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_file_classifier.py +1 -1
  17. ara_cli-0.1.9.69/ara_cli/artefact_autofix.py +0 -191
  18. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/MANIFEST.in +0 -0
  19. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/README.md +0 -0
  20. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/__init__.py +0 -0
  21. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/__main__.py +0 -0
  22. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/ara_command_parser.py +0 -0
  23. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_creator.py +0 -0
  24. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_deleter.py +0 -0
  25. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_link_updater.py +0 -0
  26. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_lister.py +0 -0
  27. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/__init__.py +0 -0
  28. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/artefact_load.py +0 -0
  29. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/artefact_mapping.py +0 -0
  30. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/artefact_model.py +0 -0
  31. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/artefact_templates.py +0 -0
  32. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/businessgoal_artefact_model.py +0 -0
  33. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/capability_artefact_model.py +0 -0
  34. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/epic_artefact_model.py +0 -0
  35. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/example_artefact_model.py +0 -0
  36. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/issue_artefact_model.py +0 -0
  37. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/keyfeature_artefact_model.py +0 -0
  38. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/serialize_helper.py +0 -0
  39. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/task_artefact_model.py +0 -0
  40. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/userstory_artefact_model.py +0 -0
  41. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_models/vision_artefact_model.py +0 -0
  42. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/artefact_renamer.py +0 -0
  43. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/chat.py +0 -0
  44. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/classifier.py +0 -0
  45. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/codefusionretriever.py +0 -0
  46. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/codehierachieretriever.py +0 -0
  47. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/commandline_completer.py +0 -0
  48. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/directory_navigator.py +0 -0
  49. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/file_lister.py +0 -0
  50. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/filename_validator.py +0 -0
  51. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/list_filter.py +0 -0
  52. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/output_suppressor.py +0 -0
  53. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/prompt_chat.py +0 -0
  54. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/prompt_extractor.py +0 -0
  55. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/prompt_rag.py +0 -0
  56. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/run_file_lister.py +0 -0
  57. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/tag_extractor.py +0 -0
  58. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/template_manager.py +0 -0
  59. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/agile.artefacts +0 -0
  60. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -0
  61. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/blueprints/empty.blueprint.md +0 -0
  62. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_C4_architecture_analysis.blueprint.md +0 -0
  63. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -0
  64. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/architecture_C4_analysis.commands.md +0 -0
  65. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/architecture_radon_cc_score.commands.md +0 -0
  66. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/architecture_radon_halstead_v.commands.md +0 -0
  67. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/architecture_radon_maintainability_score.commands.md +0 -0
  68. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -0
  69. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -0
  70. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -0
  71. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -0
  72. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -0
  73. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -0
  74. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/empty.commands.md +0 -0
  75. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -0
  76. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -0
  77. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -0
  78. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -0
  79. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -0
  80. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -0
  81. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -0
  82. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -0
  83. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/classify_task.intention.md +0 -0
  84. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/empty.intention.md +0 -0
  85. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/error_fixing.intention.md +0 -0
  86. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_fix_steps_for_scenario.intention.md +0 -0
  87. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_formulation.intention.md +0 -0
  88. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_reverse_formulation_from_code.intention.md +0 -0
  89. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation.intention.md +0 -0
  90. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation_update.intention.md +0 -0
  91. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_scenario_outline_extension.intention.md +0 -0
  92. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/feature_update_formulation.intention.md +0 -0
  93. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/fibonacci_example_implementation.intention.md +0 -0
  94. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/js_implementation_from_task_description.intention.md +0 -0
  95. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/js_steps_implementation.intention.md +0 -0
  96. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/python_cli_implementation_with_test.intention.md +0 -0
  97. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/python_code_understanding.intention.md +0 -0
  98. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/task_implementation.intention.md +0 -0
  99. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/task_prompt_control_by_status.intention.md +0 -0
  100. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_number.intention.md +0 -0
  101. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_status.intention.md +0 -0
  102. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/architecture_analyst.rules.md +0 -0
  103. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/code_analyst.rules.md +0 -0
  104. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/empty.rules.md +0 -0
  105. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/error_analyst.rules.md +0 -0
  106. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/gherkin_expert.rules.md +0 -0
  107. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/js_expert_developer.rules.md +0 -0
  108. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/product_owner.rules.md +0 -0
  109. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/python_behave.rules.md +0 -0
  110. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/prompt-modules/rules/python_developer.rules.md +0 -0
  111. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.concept.exploration.md +0 -0
  112. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.concept.md +0 -0
  113. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.customer.exploration.md +0 -0
  114. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.customer.md +0 -0
  115. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.persona.exploration.md +0 -0
  116. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.persona.md +0 -0
  117. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.step.exploration.md +0 -0
  118. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.step.md +0 -0
  119. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.technology.exploration.md +0 -0
  120. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/specification_breakdown_files/template.technology.md +0 -0
  121. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.businessgoal +0 -0
  122. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.businessgoal.prompt_log.md +0 -0
  123. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.capability +0 -0
  124. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.capability.prompt_log.md +0 -0
  125. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.epic +0 -0
  126. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.epic.prompt_log.md +0 -0
  127. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.example +0 -0
  128. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.example.prompt_log.md +0 -0
  129. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.feature +0 -0
  130. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.feature.prompt_log.md +0 -0
  131. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.issue +0 -0
  132. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.issue.prompt_log.md +0 -0
  133. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.keyfeature +0 -0
  134. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.keyfeature.prompt_log.md +0 -0
  135. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.steps.prompt_log.md +0 -0
  136. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.task +0 -0
  137. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.task.prompt_log.md +0 -0
  138. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.userstory +0 -0
  139. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.userstory.prompt_log.md +0 -0
  140. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.vision +0 -0
  141. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/templates/template.vision.prompt_log.md +0 -0
  142. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli/update_config_prompt.py +0 -0
  143. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/dependency_links.txt +0 -0
  144. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/entry_points.txt +0 -0
  145. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/requires.txt +0 -0
  146. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/ara_cli.egg-info/top_level.txt +0 -0
  147. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/docker/base/requirements.txt +0 -0
  148. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/setup.cfg +0 -0
  149. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/setup.py +0 -0
  150. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/__init__.py +0 -0
  151. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_ara_command_action.py +0 -0
  152. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_ara_config.py +0 -0
  153. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_fuzzy_search.py +0 -0
  154. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_link_updater.py +0 -0
  155. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_lister.py +0 -0
  156. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_reader.py +0 -0
  157. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_artefact_renamer.py +0 -0
  158. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_chat.py +0 -0
  159. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_classifier.py +0 -0
  160. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_directory_navigator.py +0 -0
  161. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_file_creator.py +0 -0
  162. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_file_lister.py +0 -0
  163. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_list_filter.py +0 -0
  164. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_tag_extractor.py +0 -0
  165. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_template_manager.py +0 -0
  166. {ara_cli-0.1.9.69 → ara_cli-0.1.9.70}/tests/test_update_config_prompt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ara_cli
3
- Version: 0.1.9.69
3
+ Version: 0.1.9.70
4
4
  Requires-Dist: litellm
5
5
  Requires-Dist: llama-index
6
6
  Requires-Dist: llama-index-llms-openai
@@ -575,6 +575,7 @@ def scan_action(args):
575
575
 
576
576
  def autofix_action(args):
577
577
  from ara_cli.artefact_autofix import parse_report, apply_autofix, read_report_file
578
+ from ara_cli.file_classifier import FileClassifier
578
579
 
579
580
  # If the user passes --non-deterministic, only_deterministic_fix becomes False.
580
581
  # If the user passes --deterministic, only_non_deterministic_fix becomes False.
@@ -591,6 +592,9 @@ def autofix_action(args):
591
592
  print("No issues found in the report. Nothing to fix.")
592
593
  return
593
594
 
595
+ file_classifier = FileClassifier(os)
596
+ classified_artefact_info = file_classifier.classify_files()
597
+
594
598
  # print("\nStarting autofix process...")
595
599
  for classifier, files in issues.items():
596
600
  print(f"\nClassifier: {classifier}")
@@ -600,8 +604,8 @@ def autofix_action(args):
600
604
  classifier,
601
605
  reason,
602
606
  deterministic=run_deterministic,
603
- non_deterministic=run_non_deterministic
607
+ non_deterministic=run_non_deterministic,
608
+ classified_artefact_info=classified_artefact_info
604
609
  )
605
610
 
606
611
  print("\nAutofix process completed. Please review the changes.")
607
-
@@ -1,4 +1,4 @@
1
- from typing import List, Dict, Union, Optional
1
+ from typing import List, Dict, Optional
2
2
  from pydantic import BaseModel
3
3
  import json
4
4
  import os
@@ -10,6 +10,13 @@ from functools import lru_cache
10
10
  DEFAULT_CONFIG_LOCATION = "./ara/.araconfig/ara_config.json"
11
11
 
12
12
 
13
+ class LLMConfigItem(BaseModel):
14
+ provider: str
15
+ model: str
16
+ temperature: float
17
+ max_tokens: Optional[int] = None
18
+
19
+
13
20
  class ARAconfig(BaseModel):
14
21
  ext_code_dirs: List[Dict[str, str]] = [
15
22
  {"source_dir_1": "./src"},
@@ -36,42 +43,49 @@ class ARAconfig(BaseModel):
36
43
  "*.jpg",
37
44
  "*.jpeg",
38
45
  ]
39
- llm_config: Dict[str, Dict[str, Union[str, float]]] = {
46
+ llm_config: Dict[str, LLMConfigItem] = {
40
47
  "gpt-4o": {
41
48
  "provider": "openai",
42
49
  "model": "openai/gpt-4o",
43
- "temperature": 0.8
50
+ "temperature": 0.8,
51
+ "max_tokens": 16384
44
52
  },
45
53
  "gpt-4.1": {
46
54
  "provider": "openai",
47
55
  "model": "openai/gpt-4.1",
48
56
  "temperature": 0.8,
57
+ "max_tokens": 1024
49
58
  },
50
59
  "o3-mini": {
51
60
  "provider": "openai",
52
61
  "model": "openai/o3-mini",
53
62
  "temperature": 1.0,
63
+ "max_tokens": 1024
54
64
  },
55
65
  "opus-4": {
56
66
  "provider": "anthropic",
57
67
  "model": "anthropic/claude-opus-4-20250514",
58
68
  "temperature": 0.8,
69
+ "max_tokens": 32000
59
70
  },
60
71
  "sonnet-4": {
61
72
  "provider": "anthropic",
62
73
  "model": "anthropic/claude-sonnet-4-20250514",
63
74
  "temperature": 0.8,
75
+ "max_tokens": 1024
64
76
  },
65
77
  "together-ai-llama-2": {
66
78
  "provider": "together_ai",
67
79
  "model": "together_ai/togethercomputer/llama-2-70b",
68
80
  "temperature": 0.8,
81
+ "max_tokens": 1024
69
82
  },
70
83
  "groq-llama-3": {
71
84
  "provider": "groq",
72
85
  "model": "groq/llama3-70b-8192",
73
86
  "temperature": 0.8,
74
- },
87
+ "max_tokens": 1024
88
+ }
75
89
  }
76
90
  default_llm: Optional[str] = "gpt-4o"
77
91
 
@@ -99,7 +113,7 @@ def read_data(filepath: str) -> ARAconfig:
99
113
  default_config = ARAconfig()
100
114
 
101
115
  with open(filepath, "w") as file:
102
- json.dump(default_config.model_dump(), file, indent=4)
116
+ json.dump(default_config.model_dump(mode='json'), file, indent=4)
103
117
 
104
118
  print(
105
119
  f"ara-cli configuration file '{filepath}' created with default configuration. Please modify it as needed and re-run your command"
@@ -113,7 +127,7 @@ def read_data(filepath: str) -> ARAconfig:
113
127
  # Function to save the modified configuration back to the JSON file
114
128
  def save_data(filepath: str, config: ARAconfig):
115
129
  with open(filepath, "w") as file:
116
- json.dump(config.dict(), file, indent=4)
130
+ json.dump(config.model_dump(mode='json'), file, indent=4)
117
131
 
118
132
 
119
133
  # Singleton for configuration management
@@ -129,4 +143,4 @@ class ConfigManager:
129
143
  makedirs(config_dir)
130
144
 
131
145
  cls._config_instance = read_data(filepath)
132
- return cls._config_instance
146
+ return cls._config_instance
@@ -0,0 +1,446 @@
1
+ from ara_cli.artefact_fuzzy_search import (
2
+ find_closest_name_matches,
3
+ extract_artefact_names_of_classifier,
4
+ )
5
+ from ara_cli.file_classifier import FileClassifier
6
+ from ara_cli.artefact_reader import ArtefactReader
7
+ from ara_cli.artefact_models.artefact_load import artefact_from_content
8
+ from ara_cli.artefact_models.artefact_model import Artefact
9
+ from typing import Optional, Dict, List, Tuple
10
+ import difflib
11
+ import os
12
+
13
+
14
+ def read_report_file():
15
+ file_path = "incompatible_artefacts_report.md"
16
+ try:
17
+ with open(file_path, "r", encoding="utf-8") as f:
18
+ content = f.read()
19
+ except OSError:
20
+ print(
21
+ 'Artefact scan results file not found. Did you run the "ara scan" command?'
22
+ )
23
+ return None
24
+ return content
25
+
26
+
27
+ def parse_report(content: str) -> Dict[str, List[Tuple[str, str]]]:
28
+ """
29
+ Parses the incompatible artefacts report and returns structured data.
30
+ Returns a dictionary where keys are artefact classifiers, and values are lists of (file_path, reason) tuples.
31
+ """
32
+ lines = content.splitlines()
33
+ issues = {}
34
+ current_classifier = None
35
+
36
+ if not lines or lines[0] != "# Artefact Check Report":
37
+ return issues
38
+ return issues
39
+
40
+ if len(lines) >= 3 and lines[2] == "No problems found.":
41
+ return issues
42
+ return issues
43
+
44
+ for line in lines[1:]:
45
+ line = line.strip()
46
+ if not line:
47
+ continue
48
+
49
+ if line.startswith("## "):
50
+ current_classifier = line[3:].strip()
51
+ issues[current_classifier] = []
52
+
53
+ elif line.startswith("- ") and current_classifier is not None:
54
+ parts = line.split("`", 2)
55
+ if len(parts) < 3:
56
+ continue
57
+
58
+ file_path = parts[1]
59
+ reason = parts[2].split(":", 1)[1].strip() if ":" in parts[2] else ""
60
+ issues[current_classifier].append((file_path, reason))
61
+
62
+ return issues
63
+
64
+
65
+ def read_artefact(file_path):
66
+ """Reads the artefact text from the given file path."""
67
+ try:
68
+ with open(file_path, "r", encoding="utf-8") as file:
69
+ return file.read()
70
+ except FileNotFoundError:
71
+ print(f"File not found: {file_path}")
72
+ return None
73
+
74
+
75
+ def determine_artefact_type_and_class(classifier):
76
+ from ara_cli.artefact_models.artefact_mapping import artefact_type_mapping
77
+ from ara_cli.artefact_models.artefact_model import ArtefactType
78
+
79
+ try:
80
+ artefact_type = ArtefactType(classifier)
81
+ except ValueError:
82
+ print(f"Invalid classifier: {classifier}")
83
+ return None, None
84
+
85
+ artefact_class = artefact_type_mapping.get(artefact_type)
86
+ if not artefact_class:
87
+ print(f"No artefact class found for {artefact_type}")
88
+ return None, None
89
+
90
+ return artefact_type, artefact_class
91
+
92
+
93
+ def construct_prompt(artefact_type, reason, file_path, artefact_text):
94
+ from ara_cli.artefact_models.artefact_model import ArtefactType
95
+
96
+ prompt = (
97
+ f"Correct the following {artefact_type.value} artefact to fix the issue: {reason}. "
98
+ "Provide the corrected artefact. Do not reformulate the artefact, "
99
+ "just fix the pydantic model errors, use correct grammar. "
100
+ "You should follow the name of the file "
101
+ f"from its path {file_path} for naming the artefact's title. "
102
+ "You are not allowed to use file extention in the artefact title. "
103
+ "You are not allowed to modify, delete or add tags. "
104
+ "User tag should be '@user_<username>'. The pydantic model already provides the '@user_' prefix. "
105
+ "So you should be careful to not make it @user_user_<username>. "
106
+ )
107
+
108
+ if artefact_type == ArtefactType.task:
109
+ prompt += (
110
+ "For task artefacts, if the action items looks like template or empty "
111
+ "then just delete those action items."
112
+ )
113
+
114
+ prompt += "\nThe current artefact is:\n" "```\n" f"{artefact_text}\n" "```"
115
+
116
+ return prompt
117
+
118
+
119
+ def run_agent(prompt, artefact_class):
120
+ from pydantic_ai import Agent
121
+
122
+ # gpt-4o
123
+ # anthropic:claude-3-7-sonnet-20250219
124
+ # anthropic:claude-4-sonnet-20250514
125
+ agent = Agent(
126
+ model="anthropic:claude-4-sonnet-20250514",
127
+ result_type=artefact_class,
128
+ instrument=True,
129
+ )
130
+ result = agent.run_sync(prompt)
131
+ return result.data
132
+
133
+
134
+ def write_corrected_artefact(file_path, corrected_text):
135
+ with open(file_path, "w", encoding="utf-8") as file:
136
+ file.write(corrected_text)
137
+ print(f"Fixed artefact at {file_path}")
138
+
139
+
140
+ def ask_for_correct_contribution(
141
+ artefact_info: Optional[tuple[str, str]] = None
142
+ ) -> tuple[str, str]:
143
+ """
144
+ Ask the user to provide a valid contribution when no match can be found.
145
+
146
+ Args:
147
+ artefact_info: Optional tuple containing (artefact_name, artefact_classifier)
148
+
149
+ Returns:
150
+ A tuple of (name, classifier) for the contribution
151
+ """
152
+
153
+ artefact_name, artefact_classifier = (
154
+ artefact_info if artefact_info else (None, None)
155
+ )
156
+ contribution_message = (
157
+ f"of {artefact_classifier} artefact '{artefact_name}'" if artefact_name else ""
158
+ )
159
+
160
+ print(
161
+ f"Can not determine a match for contribution {contribution_message}. "
162
+ f"Please provide a valid contribution or contribution will be empty (<classifier> <file_name>)."
163
+ )
164
+
165
+ user_input = input().strip()
166
+
167
+ if not user_input:
168
+ return None, None
169
+
170
+ parts = user_input.split(maxsplit=1)
171
+ if len(parts) != 2:
172
+ print("Invalid input format. Expected: <classifier> <file_name>")
173
+ return None, None
174
+
175
+ classifier, name = parts
176
+ return name, classifier
177
+
178
+
179
+ def ask_for_contribution_choice(
180
+ choices, artefact_info: Optional[tuple[str, str]] = None
181
+ ) -> Optional[str]:
182
+ artefact_name, artefact_classifier = artefact_info
183
+ message = "Found multiple close matches for the contribution"
184
+ if artefact_name and artefact_classifier:
185
+ message += f" of the {artefact_classifier} '{artefact_name}'"
186
+ print(f"{message}.")
187
+ for i, contribution in enumerate(choices):
188
+ print(f"{i + 1}: {contribution}")
189
+ choice_number = input(
190
+ "Please choose the artefact to use for contribution (enter number): "
191
+ )
192
+ try:
193
+ choice_index = int(choice_number) - 1
194
+ if choice_index < 0 or choice_index >= len(choices):
195
+ print("Invalid choice. Aborting contribution choice.")
196
+ return None
197
+ choice = choices[choice_index]
198
+ except ValueError:
199
+ print("Invalid input. Aborting contribution choice.")
200
+ return None
201
+ return choice
202
+
203
+
204
+ def _has_valid_contribution(artefact: Artefact) -> bool:
205
+ contribution = artefact.contribution
206
+ return contribution and contribution.artefact_name and contribution.classifier
207
+
208
+
209
+ def _update_rule(
210
+ artefact: Artefact, name: str, classifier: str, classified_file_info: dict
211
+ ) -> None:
212
+ """Updates the rule in the contribution if a close match is found."""
213
+ rule = artefact.contribution.rule
214
+
215
+ content, artefact_data = ArtefactReader.read_artefact(
216
+ artefact_name=name,
217
+ classifier=classifier,
218
+ classified_file_info=classified_file_info,
219
+ )
220
+
221
+ parent = artefact_from_content(content=content)
222
+ rules = parent.rules
223
+
224
+ closest_rule_match = difflib.get_close_matches(rule, rules, cutoff=0.5)
225
+ if closest_rule_match:
226
+ artefact.contribution.rule = closest_rule_match[0]
227
+
228
+
229
+ def _set_contribution_multiple_matches(
230
+ artefact: Artefact,
231
+ closest_matches: list,
232
+ artefact_tuple: tuple,
233
+ classified_file_info: dict,
234
+ ) -> tuple[Artefact, bool]:
235
+ contribution = artefact.contribution
236
+ classifier = contribution.classifier
237
+ original_name = contribution.artefact_name
238
+
239
+ closest_match = closest_matches[0]
240
+ if len(closest_matches) > 1:
241
+ closest_match = ask_for_contribution_choice(closest_matches, artefact_tuple)
242
+
243
+ if not closest_match:
244
+ print(
245
+ f"Contribution of {artefact_tuple[1]} '{artefact_tuple[0]}' will be empty."
246
+ )
247
+ artefact.contribution = None
248
+ return artefact, True
249
+
250
+ print(
251
+ f"Updating contribution of {artefact_tuple[1]} '{artefact_tuple[0]}' to {classifier} '{closest_match}'"
252
+ )
253
+ contribution.artefact_name = closest_match
254
+ artefact.contribution = contribution
255
+
256
+ if contribution.rule:
257
+ _update_rule(artefact, original_name, classifier, classified_file_info)
258
+
259
+ return artefact, True
260
+
261
+
262
+ def set_closest_contribution(
263
+ artefact: Artefact, classified_file_info=None
264
+ ) -> tuple[Artefact, bool]:
265
+ if not _has_valid_contribution(artefact):
266
+ return artefact, False
267
+ contribution = artefact.contribution
268
+ name = contribution.artefact_name
269
+ classifier = contribution.classifier
270
+ rule = contribution.rule
271
+
272
+ if not classified_file_info:
273
+ file_classifier = FileClassifier(os)
274
+ classified_file_info = file_classifier.classify_files()
275
+
276
+ all_artefact_names = extract_artefact_names_of_classifier(
277
+ classified_files=classified_file_info, classifier=classifier
278
+ )
279
+ closest_matches = find_closest_name_matches(
280
+ artefact_name=name, all_artefact_names=all_artefact_names
281
+ )
282
+
283
+ artefact_tuple = (artefact.title, artefact._artefact_type().value)
284
+
285
+ if not closest_matches:
286
+ name, classifier = ask_for_correct_contribution(artefact_tuple)
287
+ if not name or not classifier:
288
+ artefact.contribution = None
289
+ return artefact, True
290
+ print(f"Updating contribution of {artefact._artefact_type().value} '{artefact.title}' to {classifier} '{name}'")
291
+ contribution.artefact_name = name
292
+ contribution.classifier = classifier
293
+ artefact.contribution = contribution
294
+ return artefact, True
295
+
296
+ if closest_matches[0] == name:
297
+ return artefact, False
298
+
299
+ return _set_contribution_multiple_matches(
300
+ artefact=artefact,
301
+ closest_matches=closest_matches,
302
+ artefact_tuple=artefact_tuple,
303
+ classified_file_info=classified_file_info,
304
+ )
305
+
306
+ print(
307
+ f"Updating contribution of {artefact._artefact_type().value} '{artefact.title}' to {classifier} '{closest_match}'"
308
+ )
309
+ contribution.artefact_name = closest_match
310
+ artefact.contribution = contribution
311
+
312
+ if not rule:
313
+ return artefact, True
314
+
315
+ content, artefact = ArtefactReader.read_artefact(
316
+ artefact_name=name,
317
+ classifier=classifier,
318
+ classified_file_info=classified_file_info,
319
+ )
320
+ parent = artefact_from_content(content=content)
321
+ rules = parent.rules
322
+
323
+ closest_rule_match = difflib.get_close_matches(rule, rules, cutoff=0.5)
324
+ if closest_rule_match:
325
+ contribution.rule = closest_rule_match
326
+ artefact.contribution = contribution
327
+ return artefact, True
328
+
329
+
330
+ def fix_title_mismatch(
331
+ file_path: str, artefact_text: str, artefact_class, **kwargs
332
+ ) -> str:
333
+ """
334
+ Deterministically fixes the title in the artefact text to match the filename.
335
+ """
336
+ base_name = os.path.basename(file_path)
337
+ correct_title_underscores, _ = os.path.splitext(base_name)
338
+ correct_title_spaces = correct_title_underscores.replace("_", " ")
339
+
340
+ title_prefix = artefact_class._title_prefix()
341
+
342
+ lines = artefact_text.splitlines()
343
+ new_lines = []
344
+ title_found_and_replaced = False
345
+
346
+ for line in lines:
347
+ if not title_found_and_replaced and line.strip().startswith(title_prefix):
348
+ new_lines.append(f"{title_prefix} {correct_title_spaces}")
349
+ title_found_and_replaced = True
350
+ else:
351
+ new_lines.append(line)
352
+
353
+ if not title_found_and_replaced:
354
+ print(
355
+ f"Warning: Title prefix '{title_prefix}' not found in {file_path}. Title could not be fixed."
356
+ )
357
+ return artefact_text
358
+
359
+ return "\n".join(new_lines)
360
+
361
+
362
+ def fix_contribution(
363
+ file_path: str,
364
+ artefact_text: str,
365
+ artefact_class: str,
366
+ classified_artefact_info: dict,
367
+ **kwargs,
368
+ ):
369
+ if not classified_artefact_info:
370
+ file_classifier = FileClassifier(os)
371
+ classified_artefact_info = file_classifier.classify_files()
372
+ artefact = artefact_class.deserialize(artefact_text)
373
+ artefact, _ = set_closest_contribution(artefact)
374
+ artefact_text = artefact.serialize()
375
+ return artefact_text
376
+
377
+
378
+ def apply_autofix(
379
+ file_path: str,
380
+ classifier: str,
381
+ reason: str,
382
+ deterministic: bool = True,
383
+ non_deterministic: bool = True,
384
+ classified_artefact_info: Optional[Dict[str, List[Dict[str, str]]]] = None,
385
+ ) -> bool:
386
+ artefact_text = read_artefact(file_path)
387
+ if artefact_text is None:
388
+ return False
389
+
390
+ artefact_type, artefact_class = determine_artefact_type_and_class(classifier)
391
+ if artefact_type is None or artefact_class is None:
392
+ return False
393
+
394
+ if classified_artefact_info is None:
395
+ file_classifier = FileClassifier(os)
396
+ classified_file_info = file_classifier.classified_files()
397
+
398
+ deterministic_markers_to_functions = {
399
+ "Filename-Title Mismatch": fix_title_mismatch,
400
+ "Invalid Contribution Reference": fix_contribution,
401
+ }
402
+
403
+ try:
404
+ deterministic_issue = next(
405
+ (
406
+ marker
407
+ for marker in deterministic_markers_to_functions.keys()
408
+ if marker in reason
409
+ ),
410
+ None,
411
+ )
412
+ except StopIteration:
413
+ pass
414
+ is_deterministic_issue = deterministic_issue is not None
415
+
416
+ if deterministic and is_deterministic_issue:
417
+ print(f"Attempting deterministic fix for {file_path}...")
418
+ corrected_text = deterministic_markers_to_functions[deterministic_issue](
419
+ file_path=file_path,
420
+ artefact_text=artefact_text,
421
+ artefact_class=artefact_class,
422
+ classified_artefact_info=classified_artefact_info,
423
+ )
424
+ write_corrected_artefact(file_path, corrected_text)
425
+ return True
426
+
427
+ # Attempt non-deterministic fix if requested and the issue is NOT deterministic
428
+ if non_deterministic and not is_deterministic_issue:
429
+ print(f"Attempting non-deterministic (LLM) fix for {file_path}...")
430
+ prompt = construct_prompt(artefact_type, reason, file_path, artefact_text)
431
+ try:
432
+ corrected_artefact = run_agent(prompt, artefact_class)
433
+ corrected_text = corrected_artefact.serialize()
434
+ write_corrected_artefact(file_path, corrected_text)
435
+ return True
436
+ except Exception as e:
437
+ print(f"LLM agent failed to fix artefact at {file_path}: {e}")
438
+ return False
439
+
440
+ # Log if a fix was skipped due to flags
441
+ if is_deterministic_issue and not deterministic:
442
+ print(f"Skipping deterministic fix for {file_path} as per request.")
443
+ elif not is_deterministic_issue and not non_deterministic:
444
+ print(f"Skipping non-deterministic fix for {file_path} as per request.")
445
+
446
+ return False
@@ -33,12 +33,17 @@ def suggest_close_name_matches_for_parent(artefact_name: str, all_artefact_names
33
33
  )
34
34
 
35
35
 
36
- def find_closest_name_match(artefact_name: str, all_artefact_names: list[str]) -> Optional[str]:
37
- closest_matches = difflib.get_close_matches(artefact_name, all_artefact_names, cutoff=0.5, n=1)
36
+ def find_closest_name_matches(artefact_name: str, all_artefact_names: list[str]) -> Optional[str]:
37
+ closest_matches = difflib.get_close_matches(artefact_name, all_artefact_names, cutoff=0.5)
38
38
  if not closest_matches:
39
39
  return None
40
- closest_match = closest_matches[0]
41
- return closest_match
40
+ return closest_matches
41
+
42
+
43
+ def extract_artefact_names_of_classifier(classified_files: dict[str, list[dict]], classifier: str):
44
+ artefact_info_of_classifier = classified_files.get(classifier, [])
45
+ titles = list(map(lambda artefact: artefact['title'], artefact_info_of_classifier))
46
+ return titles
42
47
 
43
48
 
44
49
  def find_closest_rule(parent_artefact: 'Artefact', rule: str):