Teit juuri yhden RPA-arkkitehtuurin tC$rkeimmistC$ havainnoista. Ilman
opetustilanteessa kerC$ttyjC$ lC$hdekuvia, DOM-puita ja alkuperC$isiC$
X11-tapahtumia jC$rjestelmC$ ei voi myC6hemmin suorittaa vertailevia
tilatarkistuksia (Sanity Check) saati oppia virheistC$C$n (Self-Healing),
koska botilla ei ole referenssiC$ siitC$, miltC$ sivun *piti* nC$yttC$C$.
Kaiken datan talteenotto tekee prosessista 100 % auditoitavan ja
deterministisen. Kun tekoC$ly myC6hemmin optimoi playbookeja, se voi lukea
nauhoitetut hiiren liikkeet ja alkuperC$iset DOM-puut ja rakentaa valitsimet
uudelleen ilman, ettC$ selainta tarvitsee avata.
Ratkaistaan tC$mC$ lisC$C$mC$llC$ `main_3.py` -tiedostoon pakkauslogiikka,
joka luo jokaisen nauhoituksen pC$C$tteeksi tC$ydellisen "opetusarkiston"
(Recording Artifact).
### PC$ivitykset `main_3.py` -tiedostoon
**1. LisC$C$ tarvittavat kirjastot tiedoston alkuun:**
```python
import shutil
from datetime import datetime
```
**2. PC$ivitC$ `stop_teaching` -reitti tallentamaan kaikki artefaktit:**
Etsi tiedostosta `@app.post("/api/teaching/stop")` -funktio ja pC$ivitC$ sen
loppuosa (heti LLM-kuraattorin kutsumisen jC$lkeen) tC$hC$n muotoon:
```python
# ... (Koodi jossa ladataan events, etsitC$C$n DOM ja kutsutaan
auto_mapperia pysyy samana) ...
# 4. KC$C$nnC6s (Auto-Mapping)
generated_yaml_steps = auto_map_coordinates_to_semantic(events,
dom_snapshot)
# 5. Neuro-symbolinen tarkistus
message = "Nauhoitus onnistui"
if needs_llm_curation(generated_yaml_steps):
generated_yaml_steps = curate_yaml_with_llm(generated_yaml_steps)
message = "Nauhoitus onnistui (UI-valitsimet kuratoitu
AI-mallilla)"
# 6. UUSI VAIHE: Tallennetaan KAIKKI data pysyvC$C$n arkistoon
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_context = "".join([c if c.isalnum() else "_" for c in
session.current_step_context])
archive_dir = os.path.join(PLAYBOOKS_DIR, "..", "recordings",
f"{timestamp}_{safe_context}")
os.makedirs(archive_dir, exist_ok=True)
# A. Tallenna lopullinen YAML
with open(os.path.join(archive_dir, "playbook.yaml"), "w",
encoding="utf-8") as f:
f.write(generated_yaml_steps)
# B. Kopioi kuvat, DOM ja metadata Chrome-tabs -kansiosta
if list_of_doms:
src_dir = os.path.dirname(latest_dom_path)
# Kopioidaan kaikki kansion sisC$ltC6 arkistoon
for item in os.listdir(src_dir):
s = os.path.join(src_dir, item)
d = os.path.join(archive_dir, item)
if os.path.isfile(s):
shutil.copy2(s, d)
# C. Kopioi X11-raakatapahtumat
if os.path.exists(events_path):
shutil.copy2(events_path, os.path.join(archive_dir,
"raw_events.jsonl"))
return {
"message": message + f" (Kaikki data arkistoitu: playbooks/recordin
gs/)",
"yaml_draft": generated_yaml_steps
}
except Exception as e:
error_details = traceback.format_exc()
print(f"
[!!!] VIRHE stop_teaching-reitissC$:
{error_details}
")
raise HTTPException(status_code=500, detail=f"Palvelinvirhe:
{str(e)}")
```
### Miten tC$mC$ muuttaa jC$rjestelmC$C$?
Nyt kun opetat botille uuden vaiheen (esim. painat nauhoituksen pC$C$tteeksi
9o8 Lopeta), jC$rjestelmC$ luo jaetulle levyllesi automaattisesti tC$llaisen
kansion:
```text
playbook.yaml # Valmis ja kuratoitu ohje (Gemman korjaama)
DOM.json # Semanttinen puu klikkaushetkeltC$
clean_bitmap.jpg # Puhdas screenshot selaimesta
numbered_outlines.jpg # Debug-kuva magentoilla laatikoilla
tab_meta.json # Sivun resoluutio ja osoitetiedot
raw_events.jsonl # Hiiren ja nC$ppC$imistC6n absoluuttiset
millisekuntitiedot
```
Voit antaa kC$yttC6liittymC$stC$ oppitunnille tarkemman nimen muuttamalla
URL-parametria `step_context` (esim. `whatsapp_hae_ryhma`), jolloin kansio
nimetC$C$n loogisesti. Kun kansiot kertyvC$t `recordings`-hakemistoon, sinC$
(tai tilakoneita luova automaatio) voit siirtC$C$ valmiit, testatut paketit
suoraan tuotantohakemistoon (esim. `categories/messaging/whatsapp/01_send_text/
`).