feat: US-008 - Comandă Discord /voice addvoice

- /voice addvoice <nume> <sample:Attachment>: validează wav+durată min 3s,
  oprește pocket-tts.service, exportă vocea prin pocket_tts_add_voice.py
  în venv separat, repornește serviciul, răspunde cu numele final + preview audio
- gates rulate: tests PASS (1043 passed, 22 preexistente neschimbate), review backend manual PASS
This commit is contained in:
2026-07-11 10:38:15 +00:00
parent c7db236247
commit 3d5c2a4ace
3 changed files with 243 additions and 5 deletions

View File

@@ -125,3 +125,81 @@ Project: echo-core
- US-009 (ui+backend, autocomplete voci) — eligibil, dependsOn US-003+US-006 (ambele acum passes:true)
- US-011 (backend, teste TTS) — eligibil, dependsOn US-006 (acum passes:true)
---
## Iterație: 2026-07-11 (US-007)
### Story implementat: US-007 - Comandă Discord /voice engine (tags: ui, backend)
### Status: Complete
### Gates rulate:
- Typecheck: SKIP (mypy neinstalat în .venv)
- Lint: SKIP (ruff neinstalat în .venv)
- Tests: PASS — pytest tests/ aceleași 22 eșecuri preexistente, 1043 passed (neschimbat)
- Gate `ui`: agent-browser/Playwright nu se aplică — /voice engine e o comandă slash Discord, nu o pagină
web pe techStack.port. În loc de screenshot, am validat wiring-ul comenzii într-un CommandTree izolat
(register() apelat direct, fără bot live) — comanda 'engine' apare cu choices=[pockettts, supertonic].
Am evitat intenționat un restart al `echo-core.service` (bot-ul de producție Discord/Telegram/WhatsApp
folosit activ de Marius) pentru un smoke-test end-to-end real în Discord, ca să nu întrerup serviciul
mid-day fără motiv — rămâne recomandare de test manual după următorul restart/deploy normal.
- /review (backend, manual): PASS — diff mic, urmează exact pattern-ul `/voice setvoice` existent
(defer ephemeral, Config().set+save, try/except pe save failure), fără shell injection, fără secret
leakage, API contract nou (nu atinge alte comenzi).
### Learnings:
- Pentru comenzi Discord (tag `ui` fără server web real pe `techStack.port`), gate-ul `/qa` din instrucțiuni
(agent-browser pe localhost) nu are sens literal — echo-core e un bot, nu o aplicație web. Verificare
alternativă validă: instanțiere izolată a CommandTree + register() pentru confirmare structurală, plus
review manual al codului. Nu presupune că un web server rulează pe `techStack.port` doar pentru că PRD-ul
are un port generic definit.
- `echo-core.service` rulează live direct din acest working tree, pe branch-ul `ralph/echo-improve` — este
bot-ul de producție folosit activ de Marius (Discord/Telegram/WhatsApp), nu un serviciu de test izolat.
Restart-ul lui e o acțiune cu blast radius asupra unui sistem shared/live — nu-l restart fără motiv clar
sau aprobare explicită, chiar dacă ar oferi o verificare end-to-end mai completă a comenzilor Discord noi.
- `_default_voice_for_engine()` a fost adăugat ca helper mic separat de `_get_default_voice()` existent —
catalogul `tts_voices.json` nu are un flag explicit "default per engine", deci am folosit convenția deja
stabilită în US-003 (voce predefinită pocket-tts = 'alba') + config-ul existent `voice.default_voice`
pentru Supertonic, în loc să introduc un câmp nou de config nefolosit în altă parte.
### Next:
- US-008 (ui+backend, /voice addvoice) — eligibil, dependsOn US-004+US-006 (ambele passes:true)
- US-009 (ui+backend, autocomplete voci) — eligibil, dependsOn US-003+US-006 (ambele passes:true)
- US-010 (backend, /voice doctor + pocket-tts health) — eligibil, dependsOn US-001+US-002 (ambele passes:true)
- US-011 (backend, teste TTS) — eligibil, dependsOn US-006 (passes:true)
---
## Iterație: 2026-07-11 (US-008)
### Story implementat: US-008 - Comandă Discord /voice addvoice (tags: ui, backend)
### Status: Complete
### Gates rulate:
- Typecheck: SKIP (mypy neinstalat în .venv)
- Lint: SKIP (ruff neinstalat în .venv)
- Tests: PASS — pytest tests/ aceleași 22 eșecuri preexistente, 1043 passed (neschimbat)
- Gate `ui`: la fel ca US-007, /voice addvoice e o comandă slash Discord, nu o pagină web pe
techStack.port — agent-browser nu se aplică. Verificat wiring prin CommandTree izolat
(register() apelat direct, fără bot live): comanda 'addvoice' apare cu parametrii
nume:str și sample:Attachment. Nu am restart-uit echo-core.service (bot de producție live
folosit activ de Marius) pentru un test end-to-end real în Discord.
- /review (backend, manual): PASS — subprocess apelat cu argumente ca listă (fără shell=True),
deci fără risc de shell injection pe `--name` (nume introdus de utilizator); hf_token nu
apare niciodată în discord_voice.py (rămâne izolat în subprocesul pocket_tts_add_voice.py,
citit din keyring); systemctl start rulează în `finally` deci serviciul repornește chiar și
la timeout/eroare; fișierul temporar WAV e curățat în `finally` separat.
### Learnings:
- Codul pentru US-008 era deja scris (necommitat) dintr-o iterație anterioară care a atins
max_turns fără să apuce commit — a treia oară când se întâmplă acest pattern (după
US-003/US-004, US-006). Verifică mereu `git diff`/`git status` la începutul iterației
înainte să presupui reimplementare de la zero; aici codul era deja corect și complet,
a fost nevoie doar de verificare linie cu linie contra acceptance criteria, nu rescriere.
- Pattern-ul de gate `ui` pentru comenzi Discord (fără server web real) rămâne: verificare
structurală prin CommandTree izolat + review manual, stabilit deja la US-007 — reutilizat
aici fără modificări.
- `cron/jobs.json` are timestamp-uri live modificate de scheduler-ul care rulează concurent
cu acest proces Ralph — nu trebuie inclus în commit-ul de cod al story-ului (confirmă
learning-ul din iterația US-004).
### Next:
- US-009 (ui+backend, autocomplete voci) — eligibil, dependsOn US-003+US-006 (ambele passes:true)
- US-010 (backend, /voice doctor + pocket-tts health) — eligibil, dependsOn US-001+US-002 (ambele passes:true)
- US-011 (backend, teste TTS) — eligibil, dependsOn US-006 (passes:true)
---