--- description: Procesează toate screenshot-urile din screenshots/inbox/ paralel (5 agenți). Append serial cu partial-failure semantics. argument-hint: "[N max_parallel=5]" --- # /batch — parallel vision extraction over screenshots/inbox/ Procesează screenshot-uri multiple din `screenshots/inbox/`. Lansează până la **5 subagenți `m2d-extractor` în paralel** (cap rigid — context window + rate limits). După ce toți revin, append-ezi rezultatele **serial** (`append_row` citește/scrie CSV — paralelism la write = ID collision garantat). ## Workflow ### Fază 1 — Colectează lista 1. Listează `screenshots/inbox/*.png` (sortat alfabetic). 2. Dacă lista e goală → afișează `Inbox gol. Adaugă PNG-uri în screenshots/inbox/.` și oprește. 3. Dacă `$ARGUMENTS` conține un număr `N`, folosește-l ca `max_parallel` în loc de 5 (dar nu depăși niciodată 5 — hard cap). ### Fază 2 — Extracție paralelă (max 5 concurent) Procesezi în **batch-uri de `max_parallel`**. Pentru fiecare batch: - Lansezi câte un Task tool call cu `subagent_type: "m2d-extractor"` pentru fiecare screenshot, ÎN ACELAȘI MESAJ (tool calls paralele). Prompt per agent: ``` Extrage trade din ``. Scrie JSON la `data/extractions/.json` și log la `data/extractions/.log`. screenshot_path: screenshot_file: ``` - Aștepți să se întoarcă toți. Treci la următorul batch. **De ce max 5**: peste 5 sub-agenți paraleli începi să saturezi context window-ul orchestratorului cu output-urile lor și rate limits-urile API-ului. Cap rigid. ### Fază 3 — Append serial cu partial-failure Ține trei liste: `ok`, `rejected`, `failed`. Pentru fiecare PNG din lista originală, **în ordine alfabetică**: 1. **Verifică existența JSON-ului** `data/extractions/.json`: - Lipsește sau e corupt → mută PNG la `screenshots/needs_review/`, adaugă la `failed` cu motiv `missing/invalid JSON`, continuă. 2. **Apelează append** (source = `vision` — `/batch` nu suportă calibration, pentru asta folosește `/backtest --calibration` individual): ```bash python -c "from pathlib import Path; from scripts.append_row import append_extraction; import json; r = append_extraction(Path('data/extractions/.json'), source='vision'); print(json.dumps(r, default=str))" ``` 3. **Reacționezi**: - `status == "ok"` → mută PNG la `screenshots/processed/`, adaugă la `ok` cu `id`, `set`, `outcome_path`. - `status == "rejected"` → mută PNG la `screenshots/needs_review/`, mută JSON la `data/extractions/rejected/.json` (creează folderul dacă lipsește), adaugă la `rejected` cu `reason`. 4. **NU oprești batch-ul la primul fail**. Continuă până la capăt. ### Fază 4 — Regenerează MD o singură dată ```bash python -m scripts.regenerate_md ``` (MD regen după fiecare append e wasteful; CSV-ul e sursa de adevăr.) ### Fază 5 — Scrie summary la `data/extractions/_batch_.md` `` format ISO compact (ex: `2026-05-13T15-45-21Z`). Conținut: ```markdown # Batch run Total: | OK: | REJECTED: | FAILED: ## OK - .png → id=, set=, outcome_path= - ... ## REJECTED - .png — reason: - ... ## FAILED - .png — - ... ``` Secțiuni goale se omit (dacă REJECTED e gol, nu scrii secțiunea). ### Fază 6 — Afișează summary user-ului Format scurt în terminal: ``` /batch terminat. Total screenshot-uri. OK: (trade-uri #, #, ...) REJECTED: (mutate la screenshots/needs_review/) FAILED: (mutate la screenshots/needs_review/, JSON lipsă) Regenerat data/jurnal.md. Summary scris la data/extractions/_batch_.md. ``` ## Reguli - **Hard cap concurrency la 5**. Chiar dacă `max_parallel` argumentat e mai mare, clamp la 5. - **Append serial obligatoriu**. `append_extraction` citește CSV, computează `next_id`, scrie atomic; rulat paralel = ID-uri duplicate sau pierderi. - **Partial failure = continuă**. Un screenshot prost nu blochează restul batch-ului. - **MD regen o singură dată** la final. - **Path discipline pentru subagent neschimbată**: agentul scrie doar la `data/extractions/`. Tu (orchestrator) muți screenshot-uri și rejected JSON-uri. - `/batch` folosește mereu `source=vision`. Pentru calibration, rulează `/backtest --calibration` individual pe fiecare screenshot.