ara-cli 0.1.9.69__py3-none-any.whl → 0.1.9.71__py3-none-any.whl

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 (39) hide show
  1. ara_cli/ara_command_action.py +16 -12
  2. ara_cli/ara_config.py +24 -10
  3. ara_cli/artefact_autofix.py +278 -23
  4. ara_cli/artefact_creator.py +3 -3
  5. ara_cli/artefact_fuzzy_search.py +9 -4
  6. ara_cli/artefact_link_updater.py +4 -4
  7. ara_cli/artefact_models/artefact_model.py +14 -7
  8. ara_cli/artefact_models/artefact_templates.py +1 -1
  9. ara_cli/artefact_models/feature_artefact_model.py +72 -18
  10. ara_cli/artefact_models/serialize_helper.py +1 -1
  11. ara_cli/artefact_reader.py +16 -38
  12. ara_cli/artefact_renamer.py +2 -2
  13. ara_cli/artefact_scan.py +28 -3
  14. ara_cli/chat.py +1 -1
  15. ara_cli/file_classifier.py +3 -3
  16. ara_cli/file_lister.py +1 -1
  17. ara_cli/list_filter.py +1 -1
  18. ara_cli/output_suppressor.py +1 -1
  19. ara_cli/prompt_extractor.py +3 -3
  20. ara_cli/prompt_handler.py +9 -10
  21. ara_cli/prompt_rag.py +2 -2
  22. ara_cli/template_manager.py +2 -2
  23. ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +1 -1
  24. ara_cli/update_config_prompt.py +2 -2
  25. ara_cli/version.py +1 -1
  26. {ara_cli-0.1.9.69.dist-info → ara_cli-0.1.9.71.dist-info}/METADATA +1 -1
  27. {ara_cli-0.1.9.69.dist-info → ara_cli-0.1.9.71.dist-info}/RECORD +39 -39
  28. tests/test_ara_command_action.py +7 -7
  29. tests/{test_ara_autofix.py → test_artefact_autofix.py} +163 -29
  30. tests/test_artefact_link_updater.py +3 -3
  31. tests/test_artefact_renamer.py +2 -2
  32. tests/test_artefact_scan.py +52 -19
  33. tests/test_file_classifier.py +1 -1
  34. tests/test_file_lister.py +1 -1
  35. tests/test_list_filter.py +2 -2
  36. tests/test_update_config_prompt.py +2 -2
  37. {ara_cli-0.1.9.69.dist-info → ara_cli-0.1.9.71.dist-info}/WHEEL +0 -0
  38. {ara_cli-0.1.9.69.dist-info → ara_cli-0.1.9.71.dist-info}/entry_points.txt +0 -0
  39. {ara_cli-0.1.9.69.dist-info → ara_cli-0.1.9.71.dist-info}/top_level.txt +0 -0
@@ -1,50 +1,50 @@
1
1
  ara_cli/__init__.py,sha256=0zl7IegxTid26EBGLav_fXZ4CCIV3H5TfAoFQiOHjvg,148
2
2
  ara_cli/__main__.py,sha256=Z6XYWRLceIoZPvfC-X9EXouSZdtFOOe84kKVWJGA4r4,1861
3
- ara_cli/ara_command_action.py,sha256=dD97IeH7x5udKC_APk5TbuVXPiyU2XSBV2uqy52nQ9A,21625
3
+ ara_cli/ara_command_action.py,sha256=dmv2xAUw3UXB1dMfeJ3ibFYJhGjBDbQdXrHRtx_whaM,21981
4
4
  ara_cli/ara_command_parser.py,sha256=v8LUdkBSI2771gI53PdrxtD8YVjhk-7E8vgTEsTGnRM,17952
5
- ara_cli/ara_config.py,sha256=gOeaFR5Bkxk1EbN7qvJuHeaLICgy7irCREOIQD6_98M,3832
6
- ara_cli/artefact_autofix.py,sha256=-7XHl7j5O1kwWeBeIybnA4CI8v6SlXRNkV1KQ9nSWLQ,6817
7
- ara_cli/artefact_creator.py,sha256=tUNCNvfFYMheyF_viyrQhm2-43AkbHFoQaHui9ntvws,6002
5
+ ara_cli/ara_config.py,sha256=xynwnCrlpBj20ozL7ra8siniNlfM4eh4OlOHi7fkDY8,4237
6
+ ara_cli/artefact_autofix.py,sha256=_xCAZFNZHJnIS95QCNxGPezrCBb9v8gIMn9_Ixjcj74,14876
7
+ ara_cli/artefact_creator.py,sha256=ysWtlYDbZf_k8ya7ZBXILP_PWZKIssAAJK8kak5mW-E,6056
8
8
  ara_cli/artefact_deleter.py,sha256=Co4wwCH3yW8H9NrOq7_2p5571EeHr0TsfE-H8KqoOfY,1900
9
- ara_cli/artefact_fuzzy_search.py,sha256=BBDe-IP75sWZjG6nTNFtVljjL01JlQUy5ccJBZ6Trow,2429
10
- ara_cli/artefact_link_updater.py,sha256=itMS_Z64jE8bBly9WA01z8PqkBeNW6ntTO7ryMeCTRg,3703
9
+ ara_cli/artefact_fuzzy_search.py,sha256=iBlDqjZf-_D3VUjFf7ZwkiQbpQDcwRndIU7aG_sRTgE,2668
10
+ ara_cli/artefact_link_updater.py,sha256=nKdxTpDKqWTOAMD8viKmUaklSFGWzJZ8S8E8xW_ADuM,3775
11
11
  ara_cli/artefact_lister.py,sha256=jhk4n4eqp7hDIq07q43QzS7-36BM3OfZ4EABxCeOGcw,4764
12
- ara_cli/artefact_reader.py,sha256=_RqBY1f1DWH2DThXETYuHeTB2ip0wgYuGvHYI_D6EJ4,8062
13
- ara_cli/artefact_renamer.py,sha256=loIn1DF9kVnjhH7wP1v5qUvt3s0uKeWXuQPrHXenQGE,4025
14
- ara_cli/artefact_scan.py,sha256=J3aCAOltVr1oS6Lwnv51gtZC_G8faORGTccFY3kkBX4,2368
15
- ara_cli/chat.py,sha256=7xTtPEDk052_wmIzoti7GavEJ1vpRxe5c084WQ1C7dg,28617
12
+ ara_cli/artefact_reader.py,sha256=E6DMBvbOYf1OoLf-OyLaiB6K2-gd7iHmjoQZU9Rsy6g,6965
13
+ ara_cli/artefact_renamer.py,sha256=Hnz_3zD9xxnBa1FHyUE6mIktLk_9ttP2rFRvQIkmz-o,4061
14
+ ara_cli/artefact_scan.py,sha256=yg1ozwavWmqsrO9lx4bY3ggCooiPJ_DYQuZuJlFJdqc,3617
15
+ ara_cli/chat.py,sha256=Vv4tfzP203hCISd2Q0W0ZZ7ua7dk0jJ1qdl9NiHI5gM,28635
16
16
  ara_cli/classifier.py,sha256=zWskj7rBYdqYBGjksBm46iTgVU5IIf2PZsJr4qeiwVU,1878
17
17
  ara_cli/codefusionretriever.py,sha256=fCHgXdIBRzkVAnapX-KI2NQ44XbrrF4tEQmn5J6clUI,1980
18
18
  ara_cli/codehierachieretriever.py,sha256=Xd3EgEWWhkSf1TmTWtf8X5_YvyE_4B66nRrqarwSiTU,1182
19
19
  ara_cli/commandline_completer.py,sha256=b00Dqb5n7SecpxYIDLxAfYhp8X6e3c8a5qYz6ko0i3E,1192
20
20
  ara_cli/directory_navigator.py,sha256=6QbSAjJrJ5a6Lutol9J4HFgVDMiAQ672ny9TATrh04U,3318
21
- ara_cli/file_classifier.py,sha256=JsY7Y_D8WL-fiWz57zwzttg6SEajxWVxpDkFG_149-Q,3967
22
- ara_cli/file_lister.py,sha256=VFpUmHU1d6sQvJWSeuFqkZZ0Ci3ZYCUtAUfvgWypaYU,2314
21
+ ara_cli/file_classifier.py,sha256=A7wilPtIFm81iMgvqD0PjkOVL_QMUc9TB2w2Z9UcPcM,4001
22
+ ara_cli/file_lister.py,sha256=0C-j8IzajXo5qlvnuy5WFfe43ALwJ-0JFh2K6Xx2ccw,2332
23
23
  ara_cli/filename_validator.py,sha256=Aw9PL8d5-Ymhp3EY6lDrUBk3cudaNqo1Uw5RzPpI1jA,118
24
- ara_cli/list_filter.py,sha256=Not17hIngI37gZsLtIKxopB-BmyWoOGlBzSqBwh-Zpc,5273
25
- ara_cli/output_suppressor.py,sha256=ZByUwLH2DxOb-eJ31KQbtIziBKdykoyxvwxZ0tSammA,371
24
+ ara_cli/list_filter.py,sha256=qKGwwQsrWe7L5FbdxEbBYD1bbbi8c-RMypjXqXvLbgs,5291
25
+ ara_cli/output_suppressor.py,sha256=nwiHaQLwabOjMoJOeUESBnZszGMxrQZfJ3N2OvahX7Y,389
26
26
  ara_cli/prompt_chat.py,sha256=kd_OINDQFit6jN04bb7mzgY259JBbRaTaNp9F-webkc,1346
27
- ara_cli/prompt_extractor.py,sha256=a8LwPj6U8sG_v3SqDXQyPvDZQds4kHnYSO8eGissYJA,7503
28
- ara_cli/prompt_handler.py,sha256=eUkiA4CnBlSBQPZRQ78i7HqllvIDYlJgrSqQmwQHtp8,17621
29
- ara_cli/prompt_rag.py,sha256=vmlt4-rSboWibwgO_KUF79TK99YXT5KXjmbD9FeWdZY,7449
27
+ ara_cli/prompt_extractor.py,sha256=6l1Or7wuFNUDqbMg-NDXpFX-WMi2XV7YGH6hGDvow2o,7557
28
+ ara_cli/prompt_handler.py,sha256=ukYWR_AMDd8nfGkeUKyYQ8PO_-PfO8x9tV1kNcNWOT4,17672
29
+ ara_cli/prompt_rag.py,sha256=ydlhe4CUqz0jdzlY7jBbpKaf_5fjMrAZKnriKea3ZAg,7485
30
30
  ara_cli/run_file_lister.py,sha256=XbrrDTJXp1LFGx9Lv91SNsEHZPP-PyEMBF_P4btjbDA,2360
31
31
  ara_cli/tag_extractor.py,sha256=4krQyvmLR2ffhe7N7lWC7QjaxXcb90HaQdmjnBiD8ak,2523
32
- ara_cli/template_manager.py,sha256=YXPj2jGNDb-diIHFEK_vGJ-ZucodnXSGAPofKTnOofI,6633
33
- ara_cli/update_config_prompt.py,sha256=PZgNIN3dTw6p80GyX8Sp5apkAhSoykwnkEbHo3IOkUo,4571
34
- ara_cli/version.py,sha256=47jiKD51bfE-X5CaysuEIPJuxXII3Vvv_DNLT7glr-I,146
32
+ ara_cli/template_manager.py,sha256=flMO3yXMUIgBxCgLdRtIhxezPDs5kfh3IASySSa1IKI,6669
33
+ ara_cli/update_config_prompt.py,sha256=Oy9vNTw6UhDohyTEfSKkqE5ifEMPlmWNYkKHgUrK_pY,4607
34
+ ara_cli/version.py,sha256=EyUSNmWg71ZqSwLCGsMkHZC9sx8se2ACVTOoCek_sn0,146
35
35
  ara_cli/artefact_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ara_cli/artefact_models/artefact_load.py,sha256=dNcwZDW2Dk0bts9YnPZ0ESmWD2NbsLIvl4Z-qQeGmTQ,401
37
37
  ara_cli/artefact_models/artefact_mapping.py,sha256=8aD0spBjkJ8toMAmFawc6UTUxB6-tEEViZXv2I-r88Q,1874
38
- ara_cli/artefact_models/artefact_model.py,sha256=nZZS6WyVuODblLnVTH6VZli--eFrDiwNMtjwHTs2KBI,14703
39
- ara_cli/artefact_models/artefact_templates.py,sha256=Vd7SwoRVKNGKZmxBKS6f9FE1ThUOCqZLScu0ClPfIu8,8321
38
+ ara_cli/artefact_models/artefact_model.py,sha256=FSn_DBaqvcCpybsq0jzaQOinkGPqTVJ6MOSHY6lZtTg,14979
39
+ ara_cli/artefact_models/artefact_templates.py,sha256=kEBmxFfySgO8ISgMRLDKhBl-n8o1mi7p49-Pf686YU0,8345
40
40
  ara_cli/artefact_models/businessgoal_artefact_model.py,sha256=jqYFMXjWle0YW9RvcFLDBAwy61bdT5VuDT_6lTOFzMw,4853
41
41
  ara_cli/artefact_models/capability_artefact_model.py,sha256=SZqHx4O2mj4urn77Stnj4_Jxtlq3-LgBBU9SMkByppI,3079
42
42
  ara_cli/artefact_models/epic_artefact_model.py,sha256=IadQWs6SWNcLgwvtOQWmYDyV9xLr3WwAsx-YMFan5fA,5765
43
43
  ara_cli/artefact_models/example_artefact_model.py,sha256=UXrKbaPotg1jwcrVSdCeo-XH4tTD_-U1e3giaBn5_xg,1384
44
- ara_cli/artefact_models/feature_artefact_model.py,sha256=BeLsq9ZinzIDwss8nurIbxJZQ2qPgyRKRHrRlrl-zHA,15583
44
+ ara_cli/artefact_models/feature_artefact_model.py,sha256=JvgBKsiI1Y5Cs_0Ygn6lttJIjCpEC9XyZieDExUnsvg,18386
45
45
  ara_cli/artefact_models/issue_artefact_model.py,sha256=v6CpKnkqiUh6Wch2kkEmyyW49c8ysdy1qz8l1Ft9uJA,2552
46
46
  ara_cli/artefact_models/keyfeature_artefact_model.py,sha256=a3MyAiePN9n_GTN6QkTvamdsaorwVUff6w-9CdRZSlo,4243
47
- ara_cli/artefact_models/serialize_helper.py,sha256=0XCruO70-fyfLfTn7pnt8NrSQe79eYNUAjuQaV8K6_8,586
47
+ ara_cli/artefact_models/serialize_helper.py,sha256=Wks30wy-UrwJURetydKykLgJkdGRgXFHkDT24vHe5tU,595
48
48
  ara_cli/artefact_models/task_artefact_model.py,sha256=kHMw_Tr-Ud3EeHWpRWy4jI0xFnPzGZ-FT52c5rSrT1k,3558
49
49
  ara_cli/artefact_models/userstory_artefact_model.py,sha256=u6G8wdeE2EpOsg1OPR-s8uShB4A77GfqN0vkSSuthFI,6582
50
50
  ara_cli/artefact_models/vision_artefact_model.py,sha256=KcNE3QQjyT29ZMMhCQo4pOcXKTkI6pXLvyfqoN2kuUQ,5920
@@ -70,7 +70,7 @@ ara_cli/templates/template.userstory,sha256=x6fouctaYl6I9gAyR8KXLVXec7oUT4uFm4Ec
70
70
  ara_cli/templates/template.userstory.prompt_log.md,sha256=Yp62iF7zDy2XNIwwJN35jKKSmezinK_JKbSvVuagtmA,205
71
71
  ara_cli/templates/template.vision,sha256=FZYcXUZtFOLvk0H1UEMhrJrDWZnS2CSmDv9feMkyYjU,594
72
72
  ara_cli/templates/template.vision.prompt_log.md,sha256=CAzBzj3O23CzrPIUq3xzpXGKn3_nAvyBLRUi-5Bnq_0,196
73
- ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md,sha256=LEK9cfOPCxqVNMRJhdyBqSpCsl9mD7H_1QkVyqIKlCY,613
73
+ ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md,sha256=DtZsdfVDNy9_cGE_Nn_TE2T3oRwr27kecZchOp5uIG0,672
74
74
  ara_cli/templates/prompt-modules/blueprints/empty.blueprint.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  ara_cli/templates/prompt-modules/blueprints/task_todo_list_C4_architecture_analysis.blueprint.md,sha256=jEZrZaVK_pkRhLp1SpTX3xR6BGXkox6NafXEjX_GDvM,3099
76
76
  ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md,sha256=EimfgzjhFIsZnJ0qMNbVlUQEU0vC9Sv1VupesLz7A1E,2088
@@ -132,27 +132,27 @@ ara_cli/templates/specification_breakdown_files/template.step.md,sha256=nzDRl9Xo
132
132
  ara_cli/templates/specification_breakdown_files/template.technology.exploration.md,sha256=zQyiJcmbUfXdte-5uZwZUpT6ey0zwfZ00P4VwI97jQk,2274
133
133
  ara_cli/templates/specification_breakdown_files/template.technology.md,sha256=bySiksz-8xtq0Nnj4svqe2MgUftWrVkbK9AcrDUE3KY,952
134
134
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
- tests/test_ara_autofix.py,sha256=EFVzhVTNPDRVxpoK0CY6OAM88EjZTRXh-uxFGS1AVWk,10695
136
- tests/test_ara_command_action.py,sha256=Y5MrG6VjXgebliKfdFaCaS8i3GoZCGSLpj3AWCbL5Lk,25695
135
+ tests/test_ara_command_action.py,sha256=JTLqXM9BSMlU33OQgrk_sZnoowFJZKZAx8q-st-wa34,25821
137
136
  tests/test_ara_config.py,sha256=1LWby_iSestTIIqK-1clggL8kmbGGbtlYfsxAHaMMF8,2232
137
+ tests/test_artefact_autofix.py,sha256=0Y6z5EXTEDUbZb-xxWNhaVUKnhxVVS3w2YZWTvyvoZs,12103
138
138
  tests/test_artefact_fuzzy_search.py,sha256=5Sh3_l9QK8-WHn6JpGPU1b6h4QEnl2JoMq1Tdp2cj1U,1261
139
- tests/test_artefact_link_updater.py,sha256=gN5KFF1uY7OoBh8Mr5jWpqXp02YCU5OSIpSU76Rm4Gs,2137
139
+ tests/test_artefact_link_updater.py,sha256=biqbEp2jCOz8giv72hu2P2hDfeJfJ9OrVGdAv5d9cK4,2191
140
140
  tests/test_artefact_lister.py,sha256=VCEOCgDgnAOeUUgIoGAbWgz60hf9UT-tdHg18LGfB34,22656
141
141
  tests/test_artefact_reader.py,sha256=660K-d8ed-j8hulsUB_7baPD2-hhbg9TffUR5yVc4Uo,927
142
- tests/test_artefact_renamer.py,sha256=N9JnnKBEJChTYEdltHoiDnn5UCNQUPj9H9YqOvLzbH0,3458
143
- tests/test_artefact_scan.py,sha256=7w4wqCj8VEwk676JiSqh0FCAOT-kFq624u2JDrhzpuw,5860
142
+ tests/test_artefact_renamer.py,sha256=lSnKCCfoFGgKhTdDZrEaeBq1xJAak1QoqH5aSeOe9Ro,3494
143
+ tests/test_artefact_scan.py,sha256=m1dws5d5m-dMnCn43BVhnNHHLU75zgVWaKIEK9y76fk,7512
144
144
  tests/test_chat.py,sha256=-00mni6Kik_RO8BGUpWqaL4S0wt2MbUBi5jD06dSHJM,47538
145
145
  tests/test_classifier.py,sha256=grYGPksydNdPsaEBQxYHZTuTdcJWz7VQtikCKA6BNaQ,1920
146
146
  tests/test_directory_navigator.py,sha256=7G0MVrBbtBvbrFUpL0zb_9EkEWi1dulWuHsrQxMJxDY,140
147
- tests/test_file_classifier.py,sha256=hbGp0-_A_LgQ0pGv1jWDEIyCgvDyfChcvvVfbxjNY2U,10938
147
+ tests/test_file_classifier.py,sha256=kLWPiePu3F5mkVuI_lK_2QlLh2kXD_Mt2K8KZZ1fAnA,10940
148
148
  tests/test_file_creator.py,sha256=D3G7MbgE0m8JmZihxnTryxLco6iZdbV--2CGc0L20FM,2109
149
- tests/test_file_lister.py,sha256=f6B_vIv-wAulKH2ZGgNg4SG79XqGGbfwoIvZlbEnYyM,4306
150
- tests/test_list_filter.py,sha256=gSRKirTtFuhRS3QlFHqWl89WvCvAdVEnFsCWTYmgB2o,7928
149
+ tests/test_file_lister.py,sha256=Q9HwhKKx540EPzTmfzOCnvtAgON0aMmpJE2eOe1J3EA,4324
150
+ tests/test_list_filter.py,sha256=fJA3d_SdaOAUkE7jn68MOVS0THXGghy1fye_64Zvo1U,7964
151
151
  tests/test_tag_extractor.py,sha256=nSiAYlTKZ7TLAOtcJpwK5zTWHhFYU0tI5xKnivLc1dU,2712
152
152
  tests/test_template_manager.py,sha256=q-LMHRG4rHkD6ON6YW4cpZxUx9hul6Or8wVVRC2kb-8,4099
153
- tests/test_update_config_prompt.py,sha256=vSsLvc18HZdVjVM93qXWVbJt752xTLL6VGjSVCrPufk,6729
154
- ara_cli-0.1.9.69.dist-info/METADATA,sha256=rInVDCWbgC4qvLyE2StAFpOXWahBfD7OBkfE5csu6SQ,415
155
- ara_cli-0.1.9.69.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
156
- ara_cli-0.1.9.69.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
157
- ara_cli-0.1.9.69.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
158
- ara_cli-0.1.9.69.dist-info/RECORD,,
153
+ tests/test_update_config_prompt.py,sha256=xsqj1WTn4BsG5Q2t-sNPfu7EoMURFcS-hfb5VSXUnJc,6765
154
+ ara_cli-0.1.9.71.dist-info/METADATA,sha256=EloNN_cqYAUedL2f6JFADIE1mBXJSXD8nknW5Ggc9Y8,415
155
+ ara_cli-0.1.9.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
156
+ ara_cli-0.1.9.71.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
157
+ ara_cli-0.1.9.71.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
158
+ ara_cli-0.1.9.71.dist-info/RECORD,,
@@ -439,7 +439,7 @@ def read_user_action(args):
439
439
  lambda x: x["title"] == artefact_name, artefact_info_dicts
440
440
  ))
441
441
 
442
- with open(artefact_info["file_path"], 'r') as file:
442
+ with open(artefact_info["file_path"], 'r', encoding='utf-8') as file:
443
443
  content = file.read()
444
444
  artefact = artefact_from_content(content)
445
445
 
@@ -514,8 +514,8 @@ def test_set_status_action(classifier, artefact_name, artefact_names, new_status
514
514
 
515
515
  # Verify the file was opened for reading and writing
516
516
  expected_file_path = next(info["file_path"] for info in artefact_info_dicts if info["title"] == artefact_name)
517
- mock_open.assert_any_call(expected_file_path, 'r')
518
- mock_open.assert_any_call(expected_file_path, 'w')
517
+ mock_open.assert_any_call(expected_file_path, 'r', encoding='utf-8')
518
+ mock_open.assert_any_call(expected_file_path, 'w', encoding='utf-8')
519
519
 
520
520
  # Verify the serialized content was written
521
521
  mock_file_handle.__enter__.return_value.write.assert_called_once_with("serialized_content")
@@ -593,14 +593,14 @@ def test_set_user_action(
593
593
  else:
594
594
  # Should open the file and read content
595
595
  expected_file_path = next(info["file_path"] for info in artefact_info_dicts if info["title"] == artefact_name)
596
- mock_open.assert_any_call(expected_file_path, 'r')
596
+ mock_open.assert_any_call(expected_file_path, 'r', encoding='utf-8')
597
597
  mock_artefact_from_content.assert_called_once_with(mock_file_content)
598
598
 
599
599
  # Should set the users attribute on the artefact
600
600
  assert mock_artefact.users == [new_user.lstrip('@') if new_user.startswith('@') else new_user]
601
601
 
602
602
  # Should write the serialized content back to the file
603
- mock_open.assert_any_call(expected_file_path, 'w')
603
+ mock_open.assert_any_call(expected_file_path, 'w', encoding='utf-8')
604
604
  mock_file_handle.__enter__.return_value.write.assert_called_once_with("serialized_content")
605
605
 
606
606
  # Should print a success message
@@ -655,7 +655,7 @@ def test_scan_action_with_issues(capsys):
655
655
  "\t\treason1\n"
656
656
  )
657
657
  assert captured.out == expected_output
658
- m.assert_called_once_with("incompatible_artefacts_report.md", "w")
658
+ m.assert_called_once_with("incompatible_artefacts_report.md", "w", encoding="utf-8")
659
659
  handle = m()
660
660
  expected_writes = [
661
661
  call("# Artefact Check Report\n\n"),
@@ -684,7 +684,7 @@ def test_scan_action_all_good(capsys):
684
684
 
685
685
  captured = capsys.readouterr()
686
686
  assert captured.out == "All files are good!\n"
687
- m.assert_called_once_with("incompatible_artefacts_report.md", "w")
687
+ m.assert_called_once_with("incompatible_artefacts_report.md", "w", encoding="utf-8")
688
688
  handle = m()
689
689
  handle.write.assert_has_calls([
690
690
  call("# Artefact Check Report\n\n"),
@@ -9,10 +9,11 @@ from ara_cli.artefact_autofix import (
9
9
  run_agent,
10
10
  write_corrected_artefact,
11
11
  construct_prompt,
12
- fix_title_mismatch
12
+ fix_title_mismatch,
13
13
  )
14
14
  from ara_cli.artefact_models.artefact_model import ArtefactType
15
15
 
16
+
16
17
  @pytest.fixture
17
18
  def mock_artefact_type():
18
19
  """Provides a mock for the ArtefactType enum member."""
@@ -20,6 +21,7 @@ def mock_artefact_type():
20
21
  mock_type.value = "feature"
21
22
  return mock_type
22
23
 
24
+
23
25
  @pytest.fixture
24
26
  def mock_artefact_class():
25
27
  """Provides a mock for the Artefact class."""
@@ -30,13 +32,22 @@ def mock_artefact_class():
30
32
  return mock_class
31
33
 
32
34
 
35
+ @pytest.fixture
36
+ def mock_classified_artefact_info():
37
+ """Provides a mock for the classified artefact info dictionary."""
38
+ return MagicMock()
39
+
40
+
33
41
  def test_read_report_file_success():
34
42
  """Tests successful reading of the report file."""
35
43
  mock_content = "# Artefact Check Report\n- `file.feature`: reason"
36
44
  with patch("builtins.open", mock_open(read_data=mock_content)) as m:
37
45
  content = read_report_file()
38
46
  assert content == mock_content
39
- m.assert_called_once_with("incompatible_artefacts_report.md", "r", encoding="utf-8")
47
+ m.assert_called_once_with(
48
+ "incompatible_artefacts_report.md", "r", encoding="utf-8"
49
+ )
50
+
40
51
 
41
52
  def test_read_report_file_not_found(capsys):
42
53
  with patch("builtins.open", side_effect=OSError("File not found")):
@@ -44,28 +55,36 @@ def test_read_report_file_not_found(capsys):
44
55
  assert content is None
45
56
  assert "Artefact scan results file not found" in capsys.readouterr().out
46
57
 
58
+
47
59
  def test_parse_report_with_issues():
48
- content = "# Artefact Check Report\n\n## feature\n- `path/to/file.feature`: A reason\n"
60
+ content = (
61
+ "# Artefact Check Report\n\n## feature\n- `path/to/file.feature`: A reason\n"
62
+ )
49
63
  expected = {"feature": [("path/to/file.feature", "A reason")]}
50
64
  assert parse_report(content) == expected
51
65
 
66
+
52
67
  def test_parse_report_no_issues():
53
68
  content = "# Artefact Check Report\n\nNo problems found.\n"
54
69
  assert parse_report(content) == {}
55
70
 
71
+
56
72
  def test_parse_report_invalid_format():
57
73
  assert parse_report("This is not a valid report") == {}
58
74
 
75
+
59
76
  def test_parse_report_invalid_line_format():
60
77
  content = "# Artefact Check Report\n\n## feature\n- an invalid line\n"
61
78
  assert parse_report(content) == {"feature": []}
62
79
 
80
+
63
81
  def test_read_artefact_success():
64
82
  mock_content = "Feature: My Feature"
65
83
  with patch("builtins.open", mock_open(read_data=mock_content)) as m:
66
84
  content = read_artefact("file.feature")
67
85
  assert content == mock_content
68
- m.assert_called_once_with("file.feature", 'r', encoding="utf-8")
86
+ m.assert_called_once_with("file.feature", "r", encoding="utf-8")
87
+
69
88
 
70
89
  def test_read_artefact_file_not_found(capsys):
71
90
  with patch("builtins.open", side_effect=FileNotFoundError):
@@ -73,6 +92,7 @@ def test_read_artefact_file_not_found(capsys):
73
92
  assert result is None
74
93
  assert "File not found: nonexistent.feature" in capsys.readouterr().out
75
94
 
95
+
76
96
  @patch("ara_cli.artefact_models.artefact_mapping.artefact_type_mapping")
77
97
  def test_determine_artefact_type_and_class_no_class_found(mock_mapping, capsys):
78
98
  mock_mapping.get.return_value = None
@@ -83,134 +103,248 @@ def test_determine_artefact_type_and_class_no_class_found(mock_mapping, capsys):
83
103
  # The print statement inside the function is called before returning, so this check is valid.
84
104
  assert "No artefact class found for" in capsys.readouterr().out
85
105
 
106
+
86
107
  @patch("ara_cli.artefact_models.artefact_model.ArtefactType", side_effect=ValueError)
87
108
  def test_determine_artefact_type_and_class_invalid(mock_artefact_type_enum, capsys):
88
- artefact_type, artefact_class = determine_artefact_type_and_class("invalid_classifier")
109
+ artefact_type, artefact_class = determine_artefact_type_and_class(
110
+ "invalid_classifier"
111
+ )
89
112
  assert artefact_type is None
90
113
  assert artefact_class is None
91
114
  assert "Invalid classifier: invalid_classifier" in capsys.readouterr().out
92
115
 
116
+
93
117
  def test_write_corrected_artefact():
94
118
  with patch("builtins.open", mock_open()) as m:
95
119
  write_corrected_artefact("file.feature", "corrected content")
96
- m.assert_called_once_with("file.feature", 'w', encoding="utf-8")
120
+ m.assert_called_once_with("file.feature", "w", encoding="utf-8")
97
121
  m().write.assert_called_once_with("corrected content")
98
122
 
123
+
99
124
  def test_construct_prompt_for_task():
100
125
  prompt = construct_prompt(ArtefactType.task, "some reason", "file.task", "text")
101
- assert "For task artefacts, if the action items looks like template or empty" in prompt
126
+ assert (
127
+ "For task artefacts, if the action items looks like template or empty" in prompt
128
+ )
129
+
102
130
 
103
131
  @patch("ara_cli.artefact_autofix.run_agent")
104
- @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class", return_value=(None, None))
132
+ @patch(
133
+ "ara_cli.artefact_autofix.determine_artefact_type_and_class",
134
+ return_value=(None, None),
135
+ )
105
136
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
106
- def test_apply_autofix_exits_when_classifier_is_invalid(mock_read, mock_determine, mock_run_agent):
137
+ def test_apply_autofix_exits_when_classifier_is_invalid(
138
+ mock_read, mock_determine, mock_run_agent, mock_classified_artefact_info
139
+ ):
107
140
  """Tests that apply_autofix exits early if the classifier is invalid."""
108
- result = apply_autofix("file.feature", "invalid", "reason", deterministic=True, non_deterministic=True)
141
+ result = apply_autofix(
142
+ "file.feature",
143
+ "invalid",
144
+ "reason",
145
+ deterministic=True,
146
+ non_deterministic=True,
147
+ classified_artefact_info=mock_classified_artefact_info,
148
+ )
109
149
  assert result is False
110
150
  mock_read.assert_called_once_with("file.feature")
111
151
  mock_determine.assert_called_once_with("invalid")
112
152
  mock_run_agent.assert_not_called()
113
153
 
154
+
114
155
  @patch("ara_cli.artefact_autofix.run_agent")
115
156
  @patch("ara_cli.artefact_autofix.write_corrected_artefact")
116
157
  @patch("ara_cli.artefact_autofix.fix_title_mismatch", return_value="fixed text")
117
158
  @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class")
118
159
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
119
- def test_apply_autofix_for_title_mismatch_with_deterministic_flag(mock_read, mock_determine, mock_fix_title, mock_write, mock_run_agent, mock_artefact_type, mock_artefact_class):
160
+ def test_apply_autofix_for_title_mismatch_with_deterministic_flag(
161
+ mock_read,
162
+ mock_determine,
163
+ mock_fix_title,
164
+ mock_write,
165
+ mock_run_agent,
166
+ mock_artefact_type,
167
+ mock_artefact_class,
168
+ mock_classified_artefact_info,
169
+ ):
120
170
  """Tests that a deterministic fix is applied when the flag is True."""
121
171
  mock_determine.return_value = (mock_artefact_type, mock_artefact_class)
122
172
  reason = "Filename-Title Mismatch: some details"
123
-
124
- result = apply_autofix("file.feature", "feature", reason, deterministic=True, non_deterministic=False)
173
+
174
+ result = apply_autofix(
175
+ "file.feature",
176
+ "feature",
177
+ reason,
178
+ deterministic=True,
179
+ non_deterministic=False,
180
+ classified_artefact_info=mock_classified_artefact_info,
181
+ )
125
182
 
126
183
  assert result is True
127
- mock_fix_title.assert_called_once_with("file.feature", "original text", mock_artefact_class)
184
+ mock_fix_title.assert_called_once_with(
185
+ file_path="file.feature",
186
+ artefact_text="original text",
187
+ artefact_class=mock_artefact_class,
188
+ classified_artefact_info=mock_classified_artefact_info,
189
+ )
128
190
  mock_write.assert_called_once_with("file.feature", "fixed text")
129
191
  mock_run_agent.assert_not_called()
130
192
 
193
+
131
194
  @patch("ara_cli.artefact_autofix.run_agent")
132
195
  @patch("ara_cli.artefact_autofix.write_corrected_artefact")
133
196
  @patch("ara_cli.artefact_autofix.fix_title_mismatch")
134
197
  @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class")
135
198
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
136
- def test_apply_autofix_skips_title_mismatch_without_deterministic_flag(mock_read, mock_determine, mock_fix_title, mock_write, mock_run_agent, mock_artefact_type, mock_artefact_class):
199
+ def test_apply_autofix_skips_title_mismatch_without_deterministic_flag(
200
+ mock_read,
201
+ mock_determine,
202
+ mock_fix_title,
203
+ mock_write,
204
+ mock_run_agent,
205
+ mock_artefact_type,
206
+ mock_artefact_class,
207
+ mock_classified_artefact_info,
208
+ ):
137
209
  """Tests that a deterministic fix is skipped when the flag is False."""
138
210
  mock_determine.return_value = (mock_artefact_type, mock_artefact_class)
139
211
  reason = "Filename-Title Mismatch: some details"
140
-
141
- result = apply_autofix("file.feature", "feature", reason, deterministic=False, non_deterministic=True)
212
+
213
+ result = apply_autofix(
214
+ "file.feature",
215
+ "feature",
216
+ reason,
217
+ deterministic=False,
218
+ non_deterministic=True,
219
+ classified_artefact_info=mock_classified_artefact_info,
220
+ )
142
221
 
143
222
  assert result is False
144
223
  mock_fix_title.assert_not_called()
145
224
  mock_write.assert_not_called()
146
225
  mock_run_agent.assert_not_called()
147
226
 
227
+
148
228
  @patch("ara_cli.artefact_autofix.write_corrected_artefact")
149
229
  @patch("ara_cli.artefact_autofix.run_agent")
150
230
  @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class")
151
231
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
152
- def test_apply_autofix_for_llm_fix_with_non_deterministic_flag(mock_read, mock_determine, mock_run_agent, mock_write, mock_artefact_type, mock_artefact_class):
232
+ def test_apply_autofix_for_llm_fix_with_non_deterministic_flag(
233
+ mock_read,
234
+ mock_determine,
235
+ mock_run_agent,
236
+ mock_write,
237
+ mock_artefact_type,
238
+ mock_artefact_class,
239
+ mock_classified_artefact_info,
240
+ ):
153
241
  """Tests that an LLM fix is applied when the non-deterministic flag is True."""
154
242
  mock_determine.return_value = (mock_artefact_type, mock_artefact_class)
155
243
  mock_run_agent.return_value = mock_artefact_class
156
244
  reason = "Pydantic validation error"
157
245
 
158
- result = apply_autofix("file.feature", "feature", reason, deterministic=False, non_deterministic=True)
246
+ result = apply_autofix(
247
+ "file.feature",
248
+ "feature",
249
+ reason,
250
+ deterministic=False,
251
+ non_deterministic=True,
252
+ classified_artefact_info=mock_classified_artefact_info,
253
+ )
159
254
 
160
255
  assert result is True
161
256
  mock_run_agent.assert_called_once()
162
257
  mock_write.assert_called_once_with("file.feature", "llm corrected content")
163
258
 
259
+
164
260
  @patch("ara_cli.artefact_autofix.write_corrected_artefact")
165
261
  @patch("ara_cli.artefact_autofix.run_agent")
166
262
  @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class")
167
263
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
168
- def test_apply_autofix_skips_llm_fix_without_non_deterministic_flag(mock_read, mock_determine, mock_run_agent, mock_write, mock_artefact_type, mock_artefact_class):
264
+ def test_apply_autofix_skips_llm_fix_without_non_deterministic_flag(
265
+ mock_read,
266
+ mock_determine,
267
+ mock_run_agent,
268
+ mock_write,
269
+ mock_artefact_type,
270
+ mock_artefact_class,
271
+ mock_classified_artefact_info,
272
+ ):
169
273
  """Tests that an LLM fix is skipped when the non-deterministic flag is False."""
170
274
  mock_determine.return_value = (mock_artefact_type, mock_artefact_class)
171
275
  reason = "Pydantic validation error"
172
276
 
173
- result = apply_autofix("file.feature", "feature", reason, deterministic=True, non_deterministic=False)
277
+ result = apply_autofix(
278
+ "file.feature",
279
+ "feature",
280
+ reason,
281
+ deterministic=True,
282
+ non_deterministic=False,
283
+ classified_artefact_info=mock_classified_artefact_info,
284
+ )
174
285
 
175
286
  assert result is False
176
287
  mock_run_agent.assert_not_called()
177
288
  mock_write.assert_not_called()
178
289
 
290
+
179
291
  @patch("ara_cli.artefact_autofix.run_agent", side_effect=Exception("LLM failed"))
180
292
  @patch("ara_cli.artefact_autofix.determine_artefact_type_and_class")
181
293
  @patch("ara_cli.artefact_autofix.read_artefact", return_value="original text")
182
- def test_apply_autofix_llm_exception(mock_read, mock_determine, mock_run_agent, capsys, mock_artefact_type, mock_artefact_class):
294
+ def test_apply_autofix_llm_exception(
295
+ mock_read,
296
+ mock_determine,
297
+ mock_run_agent,
298
+ capsys,
299
+ mock_artefact_type,
300
+ mock_artefact_class,
301
+ mock_classified_artefact_info,
302
+ ):
183
303
  """Tests that an exception during an LLM fix is handled gracefully."""
184
304
  mock_determine.return_value = (mock_artefact_type, mock_artefact_class)
185
305
  reason = "Pydantic validation error"
186
306
 
187
- result = apply_autofix("file.feature", "feature", reason, deterministic=False, non_deterministic=True)
307
+ result = apply_autofix(
308
+ "file.feature",
309
+ "feature",
310
+ reason,
311
+ deterministic=False,
312
+ non_deterministic=True,
313
+ classified_artefact_info=mock_classified_artefact_info,
314
+ )
188
315
 
189
316
  assert result is False
190
- assert "LLM agent failed to fix artefact at file.feature: LLM failed" in capsys.readouterr().out
317
+ assert (
318
+ "LLM agent failed to fix artefact at file.feature: LLM failed"
319
+ in capsys.readouterr().out
320
+ )
321
+
191
322
 
192
323
  # === Other Tests ===
193
324
 
325
+
194
326
  def test_fix_title_mismatch_success(mock_artefact_class):
195
327
  artefact_text = "Feature: wrong title\nSome other content"
196
328
  file_path = "path/to/correct_title.feature"
197
-
329
+
198
330
  expected_text = "Feature: correct title\nSome other content"
199
-
331
+
200
332
  result = fix_title_mismatch(file_path, artefact_text, mock_artefact_class)
201
-
333
+
202
334
  assert result == expected_text
203
335
  mock_artefact_class._title_prefix.assert_called_once()
204
336
 
337
+
205
338
  def test_fix_title_mismatch_prefix_not_found(capsys, mock_artefact_class):
206
339
  artefact_text = "No title prefix here"
207
340
  file_path = "path/to/correct_title.feature"
208
341
 
209
342
  result = fix_title_mismatch(file_path, artefact_text, mock_artefact_class)
210
-
211
- assert result == artefact_text # Should return original text
343
+
344
+ assert result == artefact_text # Should return original text
212
345
  assert "Warning: Title prefix 'Feature:' not found" in capsys.readouterr().out
213
346
 
347
+
214
348
  @patch("pydantic_ai.Agent")
215
349
  def test_run_agent_exception_handling(mock_agent_class):
216
350
  mock_agent_instance = mock_agent_class.return_value
@@ -25,7 +25,7 @@ def test_update_links_in_related_artefacts(mock_isfile, mock_listdir):
25
25
  mock_file_handles = {filename: mock_open(read_data=content).return_value
26
26
  for filename, content in file_contents.items()}
27
27
  mock_open_function = mock_open()
28
- mock_open_function.side_effect = lambda file_path, mode='r': mock_file_handles[os.path.basename(file_path)]
28
+ mock_open_function.side_effect = lambda file_path, mode='r', encoding='utf-8': mock_file_handles[os.path.basename(file_path)]
29
29
 
30
30
  with patch("builtins.open", mock_open_function):
31
31
  # Instantiate the ArtefactLinkUpdater with the mocked file system
@@ -38,8 +38,8 @@ def test_update_links_in_related_artefacts(mock_isfile, mock_listdir):
38
38
  # Verify that the open function was called correctly for each file
39
39
  for filename in file_contents.keys():
40
40
  expected_file_path = os.path.join(dir_path, filename)
41
- mock_open_function.assert_any_call(expected_file_path, 'r')
42
- mock_open_function.assert_any_call(expected_file_path, 'w')
41
+ mock_open_function.assert_any_call(expected_file_path, 'r', encoding='utf-8')
42
+ mock_open_function.assert_any_call(expected_file_path, 'w', encoding='utf-8')
43
43
 
44
44
  # Verify the content of the files was updated correctly
45
45
  for filename, content in file_contents.items():
@@ -53,9 +53,9 @@ def test_update_title_in_artefact(mock_file, classifier, artefact_name, read_dat
53
53
  ar._update_title_in_artefact(artefact_path, new_title, classifier)
54
54
 
55
55
  # Check that the file was opened for reading
56
- mock_file.assert_any_call(artefact_path, 'r')
56
+ mock_file.assert_any_call(artefact_path, 'r', encoding='utf-8')
57
57
  # Check that the file was opened for writing
58
- mock_file.assert_any_call(artefact_path, 'w')
58
+ mock_file.assert_any_call(artefact_path, 'w', encoding='utf-8')
59
59
  # Check that the file write was called with the correct new content
60
60
  expected_content = read_data.replace(f"{read_data_prefix}{old_title}", f"{read_data_prefix}{new_title}")
61
61
  mock_file().write.assert_called_with(expected_content)