Question
A profiler periodically records the active call stack. Convert these snapshots into the minimal sequence of call-start and call-end events. ```python def convert_samples_to_events(samples: list[dict]) -> list[dict]: ... ``` Each sample has an integer timestamp and a stack ordered from outermost to innermost. Each output event contains the sample timestamp, an event type (`start` or `end`), and a frame name. ## Rules - Compare each stack with the previous stack using the longest common prefix. - End removed frames from innermost to outermost. - Start added frames from outermost to innermost. - Adjacent identical stacks produce no events. - Equal names at different depths represent different invocations. - Do not invent end events for calls still active in the last sample. - An empty stack is valid and ends all previously active frames. ## Example If `[main, parse, read]` becomes `[main, write]`, emit `end read`, `end parse`, and `start write` at the second sample's timestamp. ## Staged follow-ups 1. Confirm a new stack only after `N` consecutive identical observations. 2. Use the first or confirming timestamp consistently and explain the choice. 3. Support an iterator input with memory proportional only to the active and candidate stacks. 4. Discuss reconstruction when observations contain only the final `m` frames.