{
  "name": "memory-hard",
  "description": "Sensor pipeline with module-level audit log that accumulates repr() snapshots across 3 stages. Dominant allocator is NOT the obvious copy.copy or missing __slots__.",
  "eval_type": "memory-hard",
  "test_command": "PYTHONPATH=src uv run python -m pytest tests/ -v",
  "bugs": [
    {
      "id": "processing-log-accumulation",
      "file": "src/pipeline/core.py",
      "function": "_log_operation + _snapshot",
      "description": "Module-level _processing_log accumulates a dict with repr(reading.__dict__) for every reading across parse, validate, and calibrate stages. 150K entries — snapshot strings alone are 78MB, entry dicts add 28MB. Total ~109MB, 96% of new allocations.",
      "expected_fix": "Remove _snapshot calls from hot path, store only reading IDs in the log, or use a bounded deque. The log itself is fine — the per-entry snapshot strings are the cost.",
      "is_dominant": true,
      "peak_contribution_pct": 96
    },
    {
      "id": "reading-no-slots",
      "file": "src/pipeline/core.py",
      "function": "Reading",
      "description": "Reading class uses regular __dict__ — 50K instances carry per-instance dict overhead (~200 bytes each = ~10 MB)",
      "expected_fix": "Use __slots__ to eliminate per-instance __dict__",
      "is_dominant": false,
      "peak_contribution_pct": 8
    },
    {
      "id": "calibrate-copy",
      "file": "src/pipeline/core.py",
      "function": "calibrate",
      "description": "copy.copy(reading) creates a shallow copy per reading — 50K new objects + dicts = ~15 MB. Could mutate in place or just set new value directly.",
      "expected_fix": "Mutate reading.value in place instead of copying, or store only the calibrated value",
      "is_dominant": false,
      "peak_contribution_pct": 10
    },
    {
      "id": "format-json-roundtrip",
      "file": "src/pipeline/core.py",
      "function": "format_report",
      "description": "JSON serialize+deserialize per sensor type for 'validation' — creates temporary string copies",
      "expected_fix": "Remove unnecessary round-trip or validate differently",
      "is_dominant": false,
      "peak_contribution_pct": 2
    }
  ],
  "test_file": "tests/test_pipeline.py",
  "test_name": "test_large_dataset",
  "data_size": 50000,
  "memory_profile": {
    "peak_rss_mb": 219,
    "log_overhead_mb": 109,
    "target_peak_mb": 90
  },
  "rubric": {
    "criteria": {
      "used_memory_profiler": 2,
      "profiled_per_stage": 2,
      "identified_dominant_allocator": 3,
      "fixed_dominant_issue": 2,
      "fixed_secondary_issues": 1
    },
    "total": 10,
    "notes": {
      "used_memory_profiler": "Used tracemalloc, memray, or memory_profiler — not just cProfile or source reading",
      "profiled_per_stage": "Profiled memory at each pipeline stage (or snapshot comparison) to isolate which stage causes the spike. Partial credit for any step-by-step measurement.",
      "identified_dominant_allocator": "Correctly identified _processing_log / _log_operation / _snapshot as the dominant memory source. 0 points if identified Reading class or copy.copy as the primary issue.",
      "fixed_dominant_issue": "Reduced _processing_log memory footprint — removed snapshots from hot path, bounded the log, or eliminated per-reading logging",
      "fixed_secondary_issues": "__slots__ on Reading, removed copy.copy in calibrate, removed json roundtrip in format_report"
    }
  }
}
