{
  "analysis": "Excellent! Most frames only change 1 line. First frame has 901 non-space chars. This suggests a line-based strategy: for changed lines, decide whether to erase and rewrite or do partial updates.",
  "plan": "Analyze the cost of line-based encoding - for each changed line, compare cost of EL+rewrite vs partial updates. This will determine the optimal strategy.",
  "commands": [
    {
      "keystrokes": "python3 -c \"\nimport struct\n\nwith open('/app/frames.tza', 'rb') as f:\n    f.read(4)\n    w, h = struct.unpack('<HH', f.read(4))\n    n_frames, max_bytes = struct.unpack('<II', f.read(8))\n    \n    frames = []\n    for i in range(n_frames):\n        frames.append(f.read(w*h))\n\n# Analyze a changed line (frame 3->4, row 2)\nprev_row = frames[3][2*w:3*w]\ncurr_row = frames[4][2*w:3*w]\nchanges = sum(1 for j in range(w) if prev_row[j] != curr_row[j])\nprint(f'Row 2 changes: {changes} out of {w}')\n\n# Cost of EL + rewrite line\n# ESC[2K = 4 bytes, then write w chars\ncost_erase_rewrite = 4 + w\nprint(f'Cost EL+rewrite: {cost_erase_rewrite}')\n\n# Cost of cursor positioning + changes\n# ESC[r;cH = ~7 bytes per run\n# Find runs in this row\nruns = 0\nin_run = False\nfor c in range(w):\n    if prev_row[c] != curr_row[c]:\n        if not in_run:\n            in_run = True\n            runs += 1\n    else:\n        in_run = False\ncost_partial = runs * 7 + changes\nprint(f'Cost partial ({runs} runs): {cost_partial}')\n\n# Find all changed rows for frame 3->4\nchanged_rows = []\nfor r in range(h):\n    if frames[3][r*w:(r+1)*w] != frames[4][r*w:(r+1)*w]:\n        changed_rows.append(r)\nprint(f'Changed rows in frame 3->4: {changed_rows}')\n\"\n",
      "duration": 2.0
    }
  ]
}