# Model Grouping by Stem with Format Selection > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Combine model files with the same stem (e.g., `best.pt`, `best.onnx`, `best.engine`) into a single selectable model entry with a format dropdown (`.pt` / `.onnx` / `.engine`), reducing UI clutter while preserving format choice. **Current State:** 17 model files displayed as 17 separate checkboxes (e.g., `best.pt`, `best.onnx`, `best.engine` as three separate entries). Each has its own filter dropdown. **Desired State:** 6 model entries (one per stem: `best`, `model_karung_truk`, `truck-detector`, `v4-best`, `yolo11n-bbox-100ep-sack+box-20260909-best`, `karung-dimuat-detection-di-feedmill-yolo26n-seg-200e`). Each entry has: - One checkbox to enable the model - A format dropdown showing available formats (e.g., `.pt`, `.onnx`, `.engine`) - One filter dropdown (shared across formats, since classes are the same per stem) **Architecture:** 1. Modify `scan_models()` to return grouped models (one per stem) with format options 2. Update `ModelConfig` dataclass to include `formats: list[str]` and `format_paths: dict[str, str]` 3. Update `/` route to pass grouped models 4. Update upload endpoint to handle the new format 5. Rewrite template to render grouped cards with format dropdown 6. Update JavaScript to handle grouped model selection **Tech Stack:** Python, Flask, vanilla JS --- ## Global Constraints - Python >= 3.10 - No new Python dependencies - Keep backward compatibility where reasonable - Flat Design CSS with teal primary, orange accent - Accessible: semantic HTML, ARIA, keyboard navigation - Responsive: mobile-first --- ### Task 1: Update Model Registry — Group by Stem **Files:** - Modify: `src/model_registry.py` **Requirements:** 1. New dataclass `ModelGroup`: - `stem: str` — the model stem (e.g., "best") - `formats: list[str]` — available formats (e.g., [".pt", ".onnx", ".engine"]) - `format_paths: dict[str, str]` — format -> full path mapping - `known_classes: list[str]` — from KNOWN_MODEL_CLASSES - `default_format: str` — preferred format order: .engine > .pt > .onnx 2. New function `scan_model_groups(models_dir: str) -> list[ModelGroup]`: - Scan all files with MODEL_EXTENSIONS - Group by stem - Sort formats by preference (.engine first) - Return list of ModelGroup 3. Keep `scan_models()` for backward compatibility (API endpoint, tests) **Interfaces:** - Produces: `ModelGroup` with fields above - Consumes: `KNOWN_MODEL_CLASSES`, `MODEL_EXTENSIONS` **Tests:** Add tests for grouping logic --- ### Task 2: Update Flask Routes — Use Grouped Models **Files:** - Modify: `app.py` **Requirements:** 1. `index()` route: call `scan_model_groups()` instead of `scan_models()`, pass `model_groups` to template 2. `upload()` route: - Accept `model_stem` and `model_format` from form (e.g., `model_stem=best`, `model_format=.engine`) - Look up group by stem, then get path from `format_paths[format]` - Build `model_configs` with single selected format per group - Keep class filter logic (per stem, not per file) 3. `api_models()` endpoint: return grouped format (include formats + paths) **Backward Compatibility:** - If `models` (filenames) still sent, support legacy path - But prefer new `model_stem` + `model_format` approach --- ### Task 3: Update Template — Grouped Model Cards **Files:** - Modify: `templates/index.html` **Requirements:** 1. Iterate over `model_groups` instead of `models` 2. Each card: - Checkbox with `value="{{ group.stem }}"` and `data-format="{{ group.default_format }}"` - Format dropdown (`