Spot the Bug in AI Code
An assistant wrote this history-trimmer to fit a chat inside the context window. It looks right, the types check, it passes the obvious case — and it silently drops the system prompt the moment the conversation gets long. Reviewing AI code means catching exactly this: confident, plausible, and wrong on the case that matters. Find the bug and fix it.
The problem
The starter code is an AI-written clip_history(history, max_turns). history[0] is the system message and must always survive; the rest are conversation turns, of which only the most recent max_turns should be kept. The current code returns history[-max_turns:] — which counts the system message as a turn and drops it entirely once the history is longer than the budget. Fix it so the system message is always first, followed by at most the last max_turns non-system messages. Do not mutate the input.
history=[sys, u1, u2], max_turns=5[sys, u1, u2]history=[sys, u1, u2, u3, u4, u5], max_turns=2[sys, u4, u5]history=[sys, u1, u2], max_turns=0[sys]- The system message (
history[0]) is always the first element of the result, regardless ofmax_turns. - Keep at most the last
max_turnsof the non-system messages (history[1:]);max_turns=0keeps none. - If the whole history already fits (
max_turns >= len(history) - 1), return it unchanged. - Do not mutate the input
history— build and return a fresh list.
Your turn — write it
Edit the stub, hit Run (or ⌘/Ctrl + Enter), and watch the hidden tests. Stuck? the hints are right above and Reveal solution is one click away.
The AI-written clip_history below drops the system prompt on long conversations. Find the one-line bug and fix it so the system message always survives and only the last max_turns turns are kept.
- Run it first: try max_turns=2 on a history of 6 — watch the system message vanish. That is the bug.
- The system message must not be counted against the turn budget. Separate it out: system = history[0], rest = history[1:].
- Slice the REST, not the whole history: rest[-max_turns:] keeps the last max_turns turns.
- Guard max_turns == 0 — an empty slice, so the result is just [system].
Approach, complexity & discussion — open after you solve
The approach
The bug is that history[-max_turns:] counts the system message (index 0) as one of the turns, so once the history is longer than the budget the slice slides past it and drops it. Separate the system message out first, then slice only the rest: system = history[0], kept = history[1:][-max_turns:] (and [] when max_turns == 0), and return [system] + kept.
Complexity
Time and space O(max_turns) for the kept slice — the history itself is not copied beyond the tail.
Common mistakes
- Slicing the whole
historyinstead ofhistory[1:], so the system message competes for the turn budget. - Forgetting the
max_turns == 0case —x[-0:]is the whole list, not empty, a classic Python trap. - Mutating the input list instead of building a fresh one.
- Fixing the symptom (“keep it under N”) without asking whether the system prompt must always survive — it must.
Where this shows up
Dropping the system prompt on long conversations is a real, shipped bug pattern in AI apps — the assistant silently “forgets” its instructions mid-chat. More broadly this is what reviewing AI-generated code is: the code looks right, passes the obvious case, and fails on the case that matters. Catching it means reading for the edge (long history) the demo never exercised — the core skill of shipping with AI.
Explore the topic
See this challenge alongside everything else on the same subject — handbooks, system designs, algorithms and tools, in one place.