-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsession_state_diagnostic.py
More file actions
205 lines (163 loc) Β· 8.42 KB
/
session_state_diagnostic.py
File metadata and controls
205 lines (163 loc) Β· 8.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
"""
DIAGNOSTIC SCRIPT: Complete Session State Analysis
Run this to trace exactly why coaching objects are being recreated.
CRITICAL DISCOVERY: The issue is likely in how Streamlit handles session_state
keys during component reruns, causing the persistent keys to be lost.
"""
def trace_session_state_keys():
"""Trace which session state keys exist and their stability."""
print("π SESSION STATE KEY ANALYSIS")
print("=" * 50)
import streamlit as st
# Check all session state keys
all_keys = list(st.session_state.keys())
print(f"π Total session state keys: {len(all_keys)}")
# Group keys by category
coaching_keys = [k for k in all_keys if 'coaching' in k.lower()]
persistent_keys = [k for k in all_keys if 'persistent' in k.lower()]
session_keys = [k for k in all_keys if 'session' in k.lower()]
print(f"\nπ― Coaching-related keys: {coaching_keys}")
print(f"π Persistent keys: {persistent_keys}")
print(f"π Session keys: {session_keys}")
# Check for the specific problem keys
problem_indicators = []
if 'persistent_coaching_state' not in all_keys:
problem_indicators.append("β persistent_coaching_state MISSING")
else:
state_obj = st.session_state.persistent_coaching_state
problem_indicators.append(f"β
persistent_coaching_state EXISTS (ID: {id(state_obj)})")
if 'persistent_adaptive_coach' not in all_keys:
problem_indicators.append("β persistent_adaptive_coach MISSING")
else:
coach_obj = st.session_state.persistent_adaptive_coach
problem_indicators.append(f"β
persistent_adaptive_coach EXISTS (ID: {id(coach_obj)})")
# Check session coaching state consistency
if hasattr(st.session_state, 'session') and st.session_state.session:
session = st.session_state.session
if hasattr(session, 'coaching_state') and session.coaching_state:
session_state_id = id(session.coaching_state)
if 'persistent_coaching_state' in all_keys:
persistent_state_id = id(st.session_state.persistent_coaching_state)
if session_state_id == persistent_state_id:
problem_indicators.append("β
Session and persistent coaching states MATCH")
else:
problem_indicators.append(f"π¨ Session coaching state ({session_state_id}) != persistent ({persistent_state_id})")
else:
problem_indicators.append("π¨ Session has coaching state but no persistent state exists")
else:
problem_indicators.append("β οΈ Session exists but has no coaching_state")
else:
problem_indicators.append("β οΈ No session object found")
print(f"\nπ¨ PROBLEM ANALYSIS:")
for indicator in problem_indicators:
print(f" {indicator}")
return problem_indicators
def trace_coaching_integration_calls():
"""Trace calls to CoachingIntegration methods."""
print("\nπ§ COACHING INTEGRATION ANALYSIS")
print("=" * 50)
try:
from core.coaching_integration import CoachingIntegration
# Test the persistent system
print("π§ͺ Testing get_existing_coaching_system()...")
state1, coach1 = CoachingIntegration.get_existing_coaching_system()
state1_id, coach1_id = id(state1), id(coach1)
print(f" First call: State ID {state1_id}, Coach ID {coach1_id}")
# Call again to see if we get the same objects
state2, coach2 = CoachingIntegration.get_existing_coaching_system()
state2_id, coach2_id = id(state2), id(coach2)
print(f" Second call: State ID {state2_id}, Coach ID {coach2_id}")
# Check consistency
if state1_id == state2_id and coach1_id == coach2_id:
print(" β
CONSISTENT: Same objects returned")
else:
print(" π¨ INCONSISTENT: Different objects returned!")
print(" π¨ This confirms the coaching object recreation bug!")
return state1_id == state2_id and coach1_id == coach2_id
except Exception as e:
print(f" β Error testing coaching integration: {e}")
return False
def trace_streamlit_rerun_behavior():
"""Analyze how Streamlit reruns affect session state."""
print("\nπ STREAMLIT RERUN BEHAVIOR ANALYSIS")
print("=" * 50)
import streamlit as st
# Check if we're in a rerun
if 'rerun_counter' not in st.session_state:
st.session_state.rerun_counter = 0
st.session_state.rerun_counter += 1
current_run = st.session_state.rerun_counter
print(f"π Current run number: {current_run}")
# Track when persistent keys get lost
if 'persistent_key_history' not in st.session_state:
st.session_state.persistent_key_history = []
current_persistent_keys = [k for k in st.session_state.keys() if 'persistent' in k]
st.session_state.persistent_key_history.append({
'run': current_run,
'keys': current_persistent_keys.copy()
})
print(f"π Persistent keys this run: {current_persistent_keys}")
# Check for key loss across runs
if len(st.session_state.persistent_key_history) > 1:
previous_run = st.session_state.persistent_key_history[-2]
current_run_data = st.session_state.persistent_key_history[-1]
lost_keys = set(previous_run['keys']) - set(current_run_data['keys'])
gained_keys = set(current_run_data['keys']) - set(previous_run['keys'])
if lost_keys:
print(f" π¨ LOST persistent keys: {lost_keys}")
if gained_keys:
print(f" β
GAINED persistent keys: {gained_keys}")
if not lost_keys and not gained_keys:
print(f" β
Persistent keys stable across reruns")
def recommend_fix():
"""Provide specific fix recommendations based on analysis."""
print("\nπ‘ FIX RECOMMENDATIONS")
print("=" * 50)
print("Based on the analysis, the fix strategy should be:")
print()
print("1. π STRENGTHEN session state persistence")
print(" - Use more robust session state keys")
print(" - Add defensive key recreation")
print(" - Implement session state validation")
print()
print("2. π§ FIX coaching integration robustness")
print(" - Always check key existence before access")
print(" - Implement fallback recreation logic")
print(" - Add coaching state synchronization validation")
print()
print("3. π¨ CRITICAL: Add coaching object ID tracking")
print(" - Log coaching object IDs at creation and use")
print(" - Detect when different objects are being used")
print(" - Force session state refresh when inconsistency detected")
def main():
"""Run complete diagnostic analysis."""
print("π¨ CodeClimbAI MCQ Bug Diagnostic Analysis")
print("=" * 60)
print("This script analyzes why MCQ input is ignored for selenium code.")
print("=" * 60)
# Run all diagnostic checks
session_indicators = trace_session_state_keys()
integration_consistent = trace_coaching_integration_calls()
trace_streamlit_rerun_behavior()
recommend_fix()
print("\n" + "=" * 60)
print("π― DIAGNOSTIC SUMMARY")
print("=" * 60)
# Determine the most likely root cause
has_persistent_keys = any("persistent_coaching_state EXISTS" in ind for ind in session_indicators)
has_key_mismatch = any("!=" in ind for ind in session_indicators)
if not has_persistent_keys:
print("π¨ ROOT CAUSE: Persistent session state keys are not being created")
print("π§ FIX: Check CoachingIntegration.get_existing_coaching_system() implementation")
elif has_key_mismatch:
print("π¨ ROOT CAUSE: Session and persistent coaching states are out of sync")
print("π§ FIX: Add coaching state synchronization in session_manager.py")
elif not integration_consistent:
print("π¨ ROOT CAUSE: CoachingIntegration returns different objects on each call")
print("π§ FIX: Fix coaching_integration.py persistent object management")
else:
print("π€ ROOT CAUSE: Unknown - further investigation needed")
print("π§ NEXT: Add detailed logging to identify coaching object recreation points")
print("\nπ Copy this entire output and send to Claude for specific fix implementation!")
if __name__ == "__main__":
main()