diff --git a/tests/test_frames_emit.py b/tests/test_frames_emit.py index 7c571b4..08e6b74 100644 --- a/tests/test_frames_emit.py +++ b/tests/test_frames_emit.py @@ -104,3 +104,70 @@ def test_pages_for_segment_revisit_then_dwell(): assert page_b.count == 1 +def _context_block_legacy(doc, *, max_frames: int = 40) -> str: + """Pre-optimization legacy implementation of context_block() for golden testing.""" + d = doc.to_dict(False) + cov = d["coverage"] + frames = d["frames"] + + if len(frames) > max_frames: + keep = sorted(frames, key=lambda f: -f["duration_min"])[:max_frames] + keep_ids = {f["id"] for f in keep} + dropped = len(frames) - len(keep) + frames = [f for f in frames if f["id"] in keep_ids] + else: + dropped = 0 + + day = d["window"].get("day", d["window"]["start_utc"][:10]) + lines = [ + f"USER ACTIVITY ({day}, local time; measured from screen capture, " + "no interpretation):", + f"coverage: {cov['first_activity']}-{cov['last_activity']}, " + f"{cov['active_minutes']} active min, {cov['distinct_apps']} apps", + ] + for g in cov.get("gaps", []): + lines.append(f"away: {g['start']}-{g['end']} ({g['minutes']}m)") + for f in frames: + where = f["app"] + (f"/{f['site']}" if f.get("site") else "") + bits = [] + for p in f.get("pages", [])[:4]: + b = p["kind"] + if p.get("entity"): + b += f":{p['entity']}" + if p.get("count"): + b += f" x{p['count']}" + bits.append(b) + if not bits and f.get("windows"): + bits = [f["windows"][0][:60]] + inp = f.get("input", {}) + if inp.get("keys", 0) > 50: + bits.append(f"typed ~{inp['keys']} chars") + lines.append( + f"- {f['start'][:5]}-{f['end'][:5]} {where} ({f['duration_min']}m): " + + ("; ".join(bits) if bits else "on screen") + ) + if dropped: + lines.append(f"(+{dropped} frames over the size budget omitted)") + omitted = d.get("omitted", {}).get("below_min_minutes", 0) + if omitted: + lines.append( + f"(+{omitted} brief frames under " + f"{d['omitted']['min_minutes']} min omitted)" + ) + return "\n".join(lines) + + +def test_context_block_golden_equivalence(fixture_db, day_window): + """Golden equivalence test: verify optimized context_block() matches legacy 1:1.""" + for max_frames in (1, 2, 5, 10, 40): + for min_minutes in (0.0, 1.0, 5.0): + for inc_text in (False, True): + doc = build_frames( + fixture_db, *day_window, min_minutes=min_minutes, include_text=inc_text + ) + actual = context_block(doc, max_frames=max_frames) + expected = _context_block_legacy(doc, max_frames=max_frames) + assert actual == expected, ( + f"Golden mismatch for max_frames={max_frames}, " + f"min_minutes={min_minutes}, include_text={inc_text}" + )