1- import json
1+ """What the renderer remembers about conformance tests, and when.
2+
3+ Two artifacts, with different lifetimes:
4+
5+ * The **journal**, written mechanically as a functionality's fix loop runs, holding every attempt made against
6+ it. See :mod:`conformance_test_journal`. It is discarded once that functionality's tests pass.
7+
8+ * The **lessons**, extracted from the journal at that point and kept for the rest of the project. These are
9+ the memory files, and they are fed into every later prompt - which is why the set is capped and why a lesson
10+ has to be a transferable constraint rather than the story of one bug.
11+
12+ Consolidation runs once per functionality. It replaces an earlier arrangement that rebuilt a memory after
13+ every conformance test run and, being told not to duplicate itself, deleted the previous one each time - so a
14+ twenty round fix loop remembered only its most recent round.
15+ """
16+
217import os
318
419import file_utils
20+ from conformance_test_journal import ConformanceTestJournal
521from plain2code_console import console
6- from render_machine .implementation_code_helpers import ImplementationCodeHelpers
722from render_machine .render_context import RenderContext
823
924CONFORMANCE_TESTS_SUCCESS_EXIT_CODE = 0
@@ -27,106 +42,58 @@ def __init__(self, codeplain_api, memory_folder: str):
2742 self .codeplain_api = codeplain_api
2843 self .memory_folder = memory_folder
2944
30- def create_conformance_tests_memory (
31- self , render_context : RenderContext , exit_code : int , conformance_tests_issue : str
32- ):
45+ def consolidate_lessons (self , render_context : RenderContext ) -> None :
46+ """Extract what transfers to later functionalities, then discard the journal it came from.
3347
34- current_conformance_tests_issue_frid = render_context .conformance_tests_running_context .current_testing_frid
35- current_conformance_tests_issue_module = (
36- render_context .conformance_tests_running_context .current_testing_module_name
37- )
38- old_conformance_tests_issue_frid = (
39- render_context .conformance_tests_running_context .previous_conformance_tests_issue_frid
40- )
41- old_conformance_tests_issue_module = (
42- render_context .conformance_tests_running_context .previous_conformance_tests_issue_module
43- )
44-
45- old_conformance_tests_issue = (
46- render_context .conformance_tests_running_context .previous_conformance_tests_issue_old
47- )
48-
49- is_first_time_running_conformance_tests = (
50- old_conformance_tests_issue_frid is None
51- or old_conformance_tests_issue_frid == ""
52- or old_conformance_tests_issue_module != current_conformance_tests_issue_module
53- )
54- is_same_frid_as_previous_failing_test = (
55- current_conformance_tests_issue_frid == old_conformance_tests_issue_frid
56- and current_conformance_tests_issue_module == old_conformance_tests_issue_module
57- )
58- is_conformance_test_failed = exit_code != CONFORMANCE_TESTS_SUCCESS_EXIT_CODE
48+ Called when a functionality's own conformance tests pass. A functionality whose tests passed without
49+ any fixing has an empty journal and teaches nothing, so no call is made for it.
50+ """
51+ ctx = render_context .conformance_tests_running_context
52+ if ctx .current_testing_frid is None :
53+ return
5954
60- should_create_memory = not is_first_time_running_conformance_tests and (
61- is_same_frid_as_previous_failing_test or is_conformance_test_failed
55+ journal = ConformanceTestJournal . load (
56+ self . memory_folder , ctx . current_testing_module_name , ctx . current_testing_frid
6257 )
63- code_diff_files = render_context .conformance_tests_running_context .code_diff_files
64-
65- if not should_create_memory or code_diff_files is None :
66- console .debug (
67- "Skipping creation of conformance test memory because the conditions for creating memories are not met."
68- )
58+ previous_attempts = journal .render_for_prompt ()
59+ if not previous_attempts :
60+ console .debug ("No conformance test fixes were needed, so there are no lessons to consolidate." )
6961 return
7062
71- existing_files , existing_files_content = ImplementationCodeHelpers .fetch_existing_files (
72- render_context .build_folder
73- )
7463 memory_files , memory_files_content = MemoryManager .fetch_memory_files (self .memory_folder )
75-
76- conformance_tests_folder_name = (
77- render_context .conformance_tests_running_context .get_current_conformance_test_folder_name ()
78- )
79-
64+ conformance_tests_folder_name = ctx .get_current_conformance_test_folder_name ()
8065 (
8166 _ ,
82- existing_conformance_test_files_content ,
67+ conformance_tests_files_content ,
8368 ) = render_context .conformance_tests .fetch_existing_conformance_test_files (
8469 render_context .module_name ,
8570 render_context .required_modules ,
86- render_context . conformance_tests_running_context .current_testing_module_name ,
71+ ctx .current_testing_module_name ,
8772 conformance_tests_folder_name ,
8873 )
89- acceptance_tests = render_context .conformance_tests_running_context .get_current_acceptance_tests ()
9074
91- response_files = render_context .codeplain_api .create_conformance_test_memory (
75+ console .info (
76+ f"Consolidating what fixing the conformance tests for functionality { ctx .current_testing_frid } "
77+ f"in module { ctx .current_testing_module_name } has taught."
78+ )
79+
80+ response_files = render_context .codeplain_api .consolidate_conformance_test_lessons (
9281 render_context .frid_context .frid ,
9382 render_context .plain_source_tree ,
9483 render_context .frid_context .linked_resources ,
95- existing_files_content ,
9684 memory_files_content ,
9785 render_context .module_name ,
9886 render_context .get_required_modules_functionalities (),
99- code_diff_files ,
100- existing_conformance_test_files_content ,
101- acceptance_tests ,
102- conformance_tests_issue ,
87+ conformance_tests_files_content ,
88+ ctx .get_current_acceptance_tests (),
10389 conformance_tests_folder_name ,
104- old_conformance_tests_issue ,
90+ previous_attempts ,
10591 run_state = render_context .run_state ,
10692 )
107- if len (response_files ) > 0 :
93+
94+ if response_files :
10895 memory_folder_path = os .path .join (self .memory_folder , CONFORMANCE_TEST_MEMORY_SUBFOLDER )
10996 file_utils .store_response_files (memory_folder_path , response_files , memory_files )
11097
111- def delete_unresolved_memory_files (self ):
112- """Delete memory files whose resolution_status is not 'RESOLVED'."""
113- memory_path = os .path .join (self .memory_folder , CONFORMANCE_TEST_MEMORY_SUBFOLDER )
114- if not os .path .exists (memory_path ):
115- return
116-
117- memory_files = file_utils .list_all_text_files (memory_path )
118- for file_name in memory_files :
119- file_path = os .path .join (memory_path , file_name )
120- try :
121- with open (file_path , "r" ) as f :
122- content = json .load (f )
123- if content .get ("resolution_status" ) == "RESOLVED" :
124- continue
125- else :
126- os .remove (file_path )
127- except (json .JSONDecodeError , OSError ):
128- # Not a valid JSON file, unlikely to be a valid memory file, delete it
129- console .error (f"Memory file is not a valid JSON file: { file_name } . Deleting it." )
130- os .remove (file_path )
131-
132- console .debug (f"Deleted temporary memory file: { file_name } " )
98+ # The journal has served its purpose for this functionality; anything worth keeping is now a lesson.
99+ journal .delete (self .memory_folder )
0 commit comments