Code › tail-villain

Study Sessions That Could Resume

Turning study mode from a one-off chat into a session with state, progress, and a report

When I opened study mode again, the conversation started from the beginning.

After choosing a topic and a coach, the AI explained the material and asked questions. The user could answer, and the AI could continue the conversation. But if the user left and came back, the product did not know how far that session had progressed, what the user had understood, or what was still missing.

Interview practice does not end with one question and one answer. Study mode is supposed to help the user understand a specific topic, so it has to remember prior answers, current level, and what should be checked next. Otherwise, the AI can keep generating friendly first questions while the product has no stable record of where the user actually is.


Conversation logs still had to exist. Users need to reread their past answers, and the AI needs recent context to continue, but logs alone could not represent learning progress. What was said and how far the learning progressed are different pieces of information.

Suppose a user answers a question about cache consistency. The conversation log stores the answer text. But the product still needs to know whether that answer showed basic understanding, covered trade-offs, or only used the right terms without a concrete example. If the product only keeps piling up chat messages, the AI may be able to reread them later, but the system cannot reliably track learning progress.

So study mode needed session state separate from the conversation itself. The session started storing fields such as learner level, milestone state, current milestone, running summary, next focus, progress, and confidence. The goal was simple: let the product remember where the user is and what should be checked in the next turn.


Once that state existed, the user had to return to the session that owned it. If the product created a new session on every entry, the saved state would not accumulate. A user coming back to the same topic with the same persona should return to the existing active study session instead of receiving a new opening. Otherwise, the learning flow keeps going back to a first-message pattern like, “Hello, today we will study this topic,” and the result of the previous conversation does not connect to the next turn.

I changed study session lookup to use topicId, ownerId, and personaKey. If the same user was already studying the same topic with the same coach, the route sent them back to that existing session. Empty failed-opening sessions were not treated as active sessions, because an AI opening failure could otherwise leave behind an empty shell that the user would return to later.

The same screen and button can create a very different product behavior depending on whether they start a new session or resume an existing one. New sessions make study mode a conversation generator. Resumed sessions make it a learning flow where state can accumulate.


Once the session could continue, the end of the session needed its own shape. A user should be able to finish after enough discussion, but a completed learning session should leave behind more than the fact that the conversation stopped. It should record what concepts were understood, what gaps remained, and what the user should look at next.

So the study report started storing fields such as summary, understood concepts, remaining gaps, recommended next steps, and interview readiness. I also added a completion endpoint. This was not meant to be a perfect evaluation system. The immediate need was a minimal structure that captured the state in which the learning session ended.

Progress and confidence were separated for the same reason. Understanding the user had already demonstrated should not disappear easily, but confidence can drop when an answer becomes weaker. If both are collapsed into one score, the AI can overturn the whole progress state based on one bad turn, and the user may read that as losing the learning they had just built up.


To update that state on every turn, the AI response shape also had to change. Asking the AI for a good explanation can produce a plausible reply, but study mode needed structured state alongside the reply. The prompt changed so every turn returned not only the user-facing response, but also the state fields required to update the session.

There was a trade-off here. If state updates are handled too mechanically, the AI starts speaking in the same safe coaching pattern every time. Repeated lines like, “Good, you are doing well. Next question,” make the session feel like an auto-response rather than coaching. I adjusted the prompt to reduce repeated phrasing and make the next move depend on the user’s actual answer.

The frontend changed with that flow. Coach messages got persona avatars, user message labels were removed so the bubbles read more like normal chat, and the bubble width and padding were tightened. These were small changes, but study sessions are screens users stay in for a while. Small spacing and density problems compound over time.


After this work, generating one good AI answer was only the starting point for study mode. A learning product has to know where the user is, what needs review, and what remains after a session ends. Without that, the conversation remains, but the learning scatters.

The structure from that day was not final. Milestone names still needed refinement, and report quality would need real usage to tune properly. But one thing became clearer: study mode should not be a friendly chat window. It should be a learning session that lets the user come back and continue from a slightly better place than before.