From 321bd49ce6903a97b7ae30e983a42a1a50c4fb2f Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Sat, 11 Jul 2026 17:30:26 +0000 Subject: [PATCH] chore: auto-commit from dashboard --- config.json | 2 +- cron/jobs.json | 8 +- scripts/ralph/.last-branch | 1 + scripts/ralph/prompt.md | 124 ++++++++++++ scripts/ralph/ralph.sh | 387 +++++++++++++++++++++++++++++++++++++ scripts/ralph/usage.jsonl | 15 ++ tasks/prd-echo-core.md | 104 ++++++++++ 7 files changed, 636 insertions(+), 5 deletions(-) create mode 100644 scripts/ralph/.last-branch create mode 100644 scripts/ralph/prompt.md create mode 100755 scripts/ralph/ralph.sh create mode 100644 scripts/ralph/usage.jsonl create mode 100644 tasks/prd-echo-core.md diff --git a/config.json b/config.json index 26c17d3..5e22d9a 100644 --- a/config.json +++ b/config.json @@ -104,7 +104,7 @@ "949388626146517022" ], "user_name": "Marius", - "default_voice": "M1", + "default_voice": "Marius 3", "auto_leave_minutes": 5, "stt_model": "/home/moltbot/echo-core/models/whisper-small-ro-cv11-int8" }, diff --git a/cron/jobs.json b/cron/jobs.json index a8a92df..06a7bd9 100644 --- a/cron/jobs.json +++ b/cron/jobs.json @@ -11,9 +11,9 @@ "report_on": "changes", "timeout": 120, "enabled": true, - "last_run": "2026-07-10T16:00:00.002193+00:00", + "last_run": "2026-07-11T16:00:00.001582+00:00", "last_status": "ok", - "next_run": "2026-07-11T10:00:00+00:00" + "next_run": "2026-07-14T10:00:00+00:00" }, { "name": "security-audit-daily", @@ -243,9 +243,9 @@ "prompt": "Heartbeat check. Rulează src/heartbeat.py printr-un scurt raport de status.\nDacă nu e nimic de raportat (email=0, calendar nu are evenimente <2h, kb ok), răspunde doar cu HEARTBEAT_OK și oprește-te — nu trimite mesaj.\nDacă e ceva: raport scurt pe Discord #echo-work.", "allowed_tools": [], "enabled": true, - "last_run": "2026-07-11T06:00:00.002630+00:00", + "last_run": "2026-07-11T14:00:00.001368+00:00", "last_status": "ok", - "next_run": "2026-07-11T10:00:00+00:00" + "next_run": "2026-07-11T18:00:00+00:00" }, { "name": "night-execute", diff --git a/scripts/ralph/.last-branch b/scripts/ralph/.last-branch new file mode 100644 index 0000000..f803065 --- /dev/null +++ b/scripts/ralph/.last-branch @@ -0,0 +1 @@ +ralph/echo-improve diff --git a/scripts/ralph/prompt.md b/scripts/ralph/prompt.md new file mode 100644 index 0000000..57419af --- /dev/null +++ b/scripts/ralph/prompt.md @@ -0,0 +1,124 @@ +# Ralph - Instrucțiuni pentru Iterație (smart gates) + +Ești un agent autonom care implementează user stories dintr-un PRD. Aceasta este O SINGURĂ iterație — implementezi UN singur story, validezi prin gate-urile relevante, apoi te oprești. + +## Workflow per iterație (4 faze, gates condiționale pe `story.tags`) + +### Faza 0: Citește contextul + +- PRD-ul (`prd.json`) și `progress.txt` sunt furnizate în context. +- Identifică următorul story candidate: + - `passes != true` ȘI `failed != true` ȘI `blocked != true` + - DAG: toate ID-urile din `dependsOn[]` au `passes == true` (altfel sare la următorul independent) + - Cea mai mică `priority` printre cele eligibile. +- Notează `techStack.commands` (lint, typecheck, test, start) și `techStack.port`. +- Notează `story.tags[]` — alegerea Faza 3 depinde de ele. + +### Faza 1: IMPLEMENTARE (mereu) + +1.1. **Branch management** — verifică să fii pe `branchName` din PRD; checkout/create dacă lipsește. +1.2. **Citește acceptance criteria** — fiecare criteriu e un test mental concret de trecut. +1.3. **Implementează cod minimal** — DOAR ce cere story-ul. Urmează patterns existente. Fără over-engineering, fără side features. +1.4. **Update `notes`** în `prd.json` cu fișierele atinse (pentru audit ulterior). + +### Faza 2: QUALITY BASE (mereu, înainte de gates) + +Folosește `techStack.commands`: + +```bash +{techStack.commands.typecheck} # ex: npm run typecheck / mypy . +{techStack.commands.lint} # ex: npm run lint / ruff check . +{techStack.commands.test} # ex: npm test / pytest +``` + +**Loop intern**: dacă vreuna eșuează → repară și repetă, max 3 retries în această fază. Dacă încă fail după 3, ieși cu sumar de erori în `progress.txt` (ralph.sh va decide retry-ul iterației). + +### Faza 3: SMART GATES (dispatcher pe `story.tags`) + +Tags posibile: `ui`, `db`, `vercel`, `refactor`, `docs`, `backend`, `infra`. + +Aplică DOAR gate-urile potrivite — **nu rulează toate**: + +| Tag | Gate | +|-------------|---------------------------------------------------------------------------------------| +| `refactor` | `/workflow:simplify` pe diff (reduce complexity fără behavior change) | +| `ui` | `/qa` Playwright/agent-browser snapshot pe `localhost:{techStack.port}` + screenshot | +| `ui` + `requiresDesignReview` | `/plan-design-review` pe screenshot capturat | +| `vercel` | push branch + `gh pr checks --watch` (timeout 5 min); fail dacă PR checks eșuează | +| `db` | verify schema diff (alembic / prisma migrate diff / `psql \\d+ tablename`) | +| `docs` | doar typecheck base (Faza 2 e suficient); skip gate dedicat | +| `backend` | `/review` pe diff (intern — second pass review pe API contracts, error handling) | +| `infra` | `/review` pe diff + manual smoke test al modificărilor (CI config, Dockerfile, etc.) | +| _(tags vide)_ | **run-all-gates fallback** — `/review` + `/qa` + `/workflow:simplify` (safe default) | + +**Mecanism**: skill-urile gstack se invocă prin text mention în prompt — Claude (subprocess `claude -p`) le vede ca tool-uri disponibile via `~/.claude/skills/gstack/`. + +**Multi-tag**: rulează gate-uri pentru fiecare tag (ex: `["ui", "backend"]` → atât `/qa` cât și `/review`). + +**Important**: dacă vreun gate eșuează, NU marca `passes=true`. Repară (max 3 fix-uri în iterație) sau lasă pentru iterația următoare (ralph.sh se ocupă de retry counter). + +### Faza 4: COMMIT + MARK + +4.1. **Commit** cu mesaj descriptiv: +``` +feat: [Story ID] - [Story Title] + +- ce ai schimbat (1-3 bullets) +- gates rulate: typecheck PASS, lint PASS, /qa PASS +``` + +4.2. **Update `prd.json`**: +- `passes: true` DOAR DACĂ toate gate-urile relevante au pasat +- `notes` populat cu rezultate gate (ex: "qa: ok, design-review: 8/10") + +4.3. **Append `progress.txt`**: +```markdown +## Iterație: [timestamp] +### Story implementat: [ID] - [Title] (tags: [ui, backend]) +### Status: Complete / Partial / Failed + +### Gates rulate: +- Typecheck: PASS +- Lint: PASS +- Tests: PASS/SKIP +- /qa (ui): PASS — screenshot la scripts/ralph/screenshots/... +- /review (backend): PASS + +### Learnings: +- [Patterns descoperite, gotchas] + +### Next: +- [Stories eligibile pentru iterația următoare] +--- +``` + +## Reguli importante + +1. **UN SINGUR STORY PE ITERAȚIE** — nu implementa mai mult de un story. +2. **DAG STRICT** — nu sări peste `dependsOn` neîmplinite. +3. **GATES PE TAGS** — rulează doar ce e relevant; tags vide = run-all-gates fallback. +4. **NU MARCA `passes=true` cu gate failed** — altfel ralph.sh nu va relua story-ul. +5. **FII CONCIS** — fără over-engineering, fără docs auto-generate dacă story-ul nu cere. + +## Comenzi agent-browser (referință rapidă pentru gate `ui`) + +```bash +agent-browser navigate "http://localhost:{techStack.port}" +agent-browser snapshot # listă elemente compactă (@e1, @e2...) +agent-browser click @e5 +agent-browser fill @e3 "value" +agent-browser screenshot ./scripts/ralph/screenshots/US-{id}-$(date +%Y%m%d-%H%M%S).png +agent-browser console # erori JS +agent-browser wait-for "Loading complete" +``` + +## Condiție de terminare + +Dacă TOATE story-urile au `passes: true` (sau combinat cu `failed: true` / `blocked: true` astfel că nimic nu mai e eligibil): + +``` +COMPLETE +``` + +--- +ÎNCEPE IMPLEMENTAREA ACUM. diff --git a/scripts/ralph/ralph.sh b/scripts/ralph/ralph.sh new file mode 100755 index 0000000..08b2d28 --- /dev/null +++ b/scripts/ralph/ralph.sh @@ -0,0 +1,387 @@ +#!/bin/bash +# Ralph pentru Claude Code - Loop autonom de agent AI (W3: smart gates + DAG + rate limit) +# Adaptat din Ralph original (snarktank/ralph) pentru Claude Code CLI +# Usage: ./ralph.sh [max_iterations] [project_dir] +# +# Env vars (opționale): +# RALPH_MAX_TURNS — --max-turns per iter (default 30) +# RALPH_RATE_LIMIT_SLEEP — sleep după rate limit detection (default 1800 = 30min) +# RALPH_DAG_HELPER — path la tools/ralph_dag.py (auto-detect default) +# RALPH_PYTHON — interpreter Python pentru DAG helper (default python3) + +set -e + +MAX_ITERATIONS=${1:-10} +PROJECT_DIR=${2:-$(pwd)} +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PRD_FILE="$SCRIPT_DIR/prd.json" +PROGRESS_FILE="$SCRIPT_DIR/progress.txt" +ARCHIVE_DIR="$SCRIPT_DIR/archive" +SCREENSHOTS_DIR="$SCRIPT_DIR/screenshots" +LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch" +PROMPT_FILE="$SCRIPT_DIR/prompt.md" + +# W3 config +MAX_TURNS=${RALPH_MAX_TURNS:-30} +RATE_LIMIT_SLEEP=${RALPH_RATE_LIMIT_SLEEP:-1800} +RALPH_PYTHON=${RALPH_PYTHON:-python3} + +# DAG helper auto-detect: prefer co-located cu echo-core; fallback la $SCRIPT_DIR +if [ -n "$RALPH_DAG_HELPER" ] && [ -f "$RALPH_DAG_HELPER" ]; then + DAG_HELPER="$RALPH_DAG_HELPER" +elif [ -f "/home/moltbot/echo-core/tools/ralph_dag.py" ]; then + DAG_HELPER="/home/moltbot/echo-core/tools/ralph_dag.py" +elif [ -f "/home/moltbot/echo-core-qc/tools/ralph_dag.py" ]; then + DAG_HELPER="/home/moltbot/echo-core-qc/tools/ralph_dag.py" +elif [ -f "$SCRIPT_DIR/ralph_dag.py" ]; then + DAG_HELPER="$SCRIPT_DIR/ralph_dag.py" +else + DAG_HELPER="" +fi + +# Usage helper auto-detect (rate limit budget tracking — best effort, niciodată +# blochează rularea Ralph dacă lipsește) +if [ -n "$RALPH_USAGE_HELPER" ] && [ -f "$RALPH_USAGE_HELPER" ]; then + USAGE_HELPER="$RALPH_USAGE_HELPER" +elif [ -f "/home/moltbot/echo-core/tools/ralph_usage.py" ]; then + USAGE_HELPER="/home/moltbot/echo-core/tools/ralph_usage.py" +elif [ -f "/home/moltbot/echo-core-instr/tools/ralph_usage.py" ]; then + USAGE_HELPER="/home/moltbot/echo-core-instr/tools/ralph_usage.py" +elif [ -f "$SCRIPT_DIR/ralph_usage.py" ]; then + USAGE_HELPER="$SCRIPT_DIR/ralph_usage.py" +else + USAGE_HELPER="" +fi +USAGE_FILE="$SCRIPT_DIR/usage.jsonl" + +# Verifică că jq este instalat +if ! command -v jq &> /dev/null; then + echo "Eroare: jq nu este instalat. Rulează: apt install jq" + exit 1 +fi + +# Verifică că claude este instalat +if ! command -v claude &> /dev/null; then + echo "Eroare: Claude Code CLI nu este instalat." + echo "Instalează cu: npm install -g @anthropic-ai/claude-code" + exit 1 +fi + +# Verifică agent-browser (opțional, pentru verificări UI) +if ! command -v agent-browser &> /dev/null; then + echo "Notă: agent-browser nu este instalat." + echo "Pentru verificări vizuale UI, instalează cu: npm install -g agent-browser && agent-browser install" + echo "Continuăm fără verificări browser..." + echo "" +fi + +# Verifică existența fișierelor necesare +if [ ! -f "$PRD_FILE" ]; then + echo "Eroare: prd.json nu există în $SCRIPT_DIR" + echo "Generează mai întâi un PRD folosind skill-ul /prd și apoi /ralph" + exit 1 +fi + +if [ ! -f "$PROMPT_FILE" ]; then + echo "Eroare: prompt.md nu există în $SCRIPT_DIR" + exit 1 +fi + +# Arhivare rulare anterioară dacă branch-ul s-a schimbat +if [ -f "$PRD_FILE" ] && [ -f "$LAST_BRANCH_FILE" ]; then + CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") + LAST_BRANCH=$(cat "$LAST_BRANCH_FILE" 2>/dev/null || echo "") + + if [ -n "$CURRENT_BRANCH" ] && [ -n "$LAST_BRANCH" ] && [ "$CURRENT_BRANCH" != "$LAST_BRANCH" ]; then + DATE=$(date +%Y-%m-%d) + FOLDER_NAME=$(echo "$LAST_BRANCH" | sed 's|^ralph/||') + ARCHIVE_FOLDER="$ARCHIVE_DIR/$DATE-$FOLDER_NAME" + + echo "Arhivare rulare anterioară: $LAST_BRANCH" + mkdir -p "$ARCHIVE_FOLDER" + [ -f "$PRD_FILE" ] && cp "$PRD_FILE" "$ARCHIVE_FOLDER/" + [ -f "$PROGRESS_FILE" ] && cp "$PROGRESS_FILE" "$ARCHIVE_FOLDER/" + echo " Arhivat în: $ARCHIVE_FOLDER" + + # Reset progress file + echo "# Ralph Progress Log" > "$PROGRESS_FILE" + echo "Started: $(date)" >> "$PROGRESS_FILE" + echo "Branch: $CURRENT_BRANCH" >> "$PROGRESS_FILE" + echo "---" >> "$PROGRESS_FILE" + fi +fi + +# Salvează branch-ul curent +if [ -f "$PRD_FILE" ]; then + CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") + if [ -n "$CURRENT_BRANCH" ]; then + echo "$CURRENT_BRANCH" > "$LAST_BRANCH_FILE" + fi +fi + +# Creează directoare necesare +mkdir -p "$SCRIPT_DIR/logs" "$SCRIPT_DIR/archive" "$SCRIPT_DIR/screenshots" + +# Creează .gitignore dacă nu există +if [ ! -f "$PROJECT_DIR/.gitignore" ]; then + cat > "$PROJECT_DIR/.gitignore" << 'GITIGNORE' +# Python +__pycache__/ +*.py[cod] +*.pyo +*.egg-info/ +dist/ +build/ +.coverage +htmlcov/ +.pytest_cache/ + +# Virtual environment +venv/ +.venv/ + +# Ralph runtime +scripts/ralph/.ralph.pid +scripts/ralph/.last-branch +scripts/ralph/logs/ +scripts/ralph/screenshots/ +scripts/ralph/archive/ + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db +GITIGNORE + echo "Created .gitignore" +fi + +# Inițializare progress file dacă nu există +if [ ! -f "$PROGRESS_FILE" ]; then + echo "# Ralph Progress Log" > "$PROGRESS_FILE" + echo "Started: $(date)" >> "$PROGRESS_FILE" + echo "---" >> "$PROGRESS_FILE" +fi + +# Funcție pentru a verifica dacă toate story-urile sunt complete +check_all_complete() { + local incomplete=$(jq '[.userStories[] | select(.passes != true)] | length' "$PRD_FILE" 2>/dev/null || echo "999") + [ "$incomplete" -eq 0 ] +} + +# W3: nimic eligibil = toate sunt fie passes, fie failed, fie blocked +check_no_eligible() { + local n=$(jq '[.userStories[] | select(.passes != true and .failed != true and .blocked != true)] | length' "$PRD_FILE" 2>/dev/null || echo "999") + [ "$n" -eq 0 ] +} + +# W3: alege next eligible story via DAG helper. Print story ID sau "" dacă nimic. +dag_next_story() { + if [ -n "$DAG_HELPER" ]; then + "$RALPH_PYTHON" "$DAG_HELPER" next-story "$PRD_FILE" 2>/dev/null || echo "" + else + # Fallback simplu (fără DAG): primul story cu passes!=true && failed!=true && blocked!=true, priority asc + jq -r '[.userStories[] | select(.passes != true and .failed != true and .blocked != true)] | sort_by(.priority) | .[0].id // ""' "$PRD_FILE" + fi +} + +dag_incr_retry() { + local sid="$1" + if [ -n "$DAG_HELPER" ]; then + "$RALPH_PYTHON" "$DAG_HELPER" incr-retry "$PRD_FILE" "$sid" 2>/dev/null || echo "0" + else + echo "0" + fi +} + +dag_mark_failed() { + local sid="$1" reason="$2" + if [ -n "$DAG_HELPER" ]; then + "$RALPH_PYTHON" "$DAG_HELPER" mark-failed "$PRD_FILE" "$sid" "$reason" 2>/dev/null || true + fi +} + +dag_force_tags() { + local sid="$1" + if [ -n "$DAG_HELPER" ]; then + "$RALPH_PYTHON" "$DAG_HELPER" force-tags "$PRD_FILE" "$sid" "$PROJECT_DIR" 2>/dev/null || true + fi +} + +# W3: detectează rate limit în output Claude (heuristic — Anthropic nu are exit code dedicat) +is_rate_limited() { + local output="$1" + echo "$output" | grep -qiE "rate limit|rate_limit_exceeded|429|too many requests" +} + +# Afișare status inițial +echo "" +echo "=======================================================================" +echo " RALPH pentru Claude Code - Agent Autonom " +echo "=======================================================================" +PROJECT_NAME=$(jq -r '.projectName // "Unknown"' "$PRD_FILE") +BRANCH_NAME=$(jq -r '.branchName // "N/A"' "$PRD_FILE") +TOTAL_STORIES=$(jq '.userStories | length' "$PRD_FILE") +COMPLETE_STORIES=$(jq '[.userStories[] | select(.passes == true)] | length' "$PRD_FILE") +echo " Proiect: $PROJECT_NAME" +echo " Branch: $BRANCH_NAME" +echo " Stories: $COMPLETE_STORIES / $TOTAL_STORIES complete" +echo " Max iterații: $MAX_ITERATIONS" +echo " Screenshots: $SCREENSHOTS_DIR" +echo "=======================================================================" +echo "" + +# Verificare rapidă - poate toate sunt deja complete? +if check_all_complete; then + echo "Toate story-urile sunt deja complete!" + exit 0 +fi + +# Tracker pentru rate limit retry (max 1 retry de iterație-rate-limit per rulare) +RATE_LIMIT_RETRY_USED=0 + +# Loop principal +for i in $(seq 1 $MAX_ITERATIONS); do + echo "" + echo "===================================================================" + echo " Ralph Iterația $i din $MAX_ITERATIONS" + echo "===================================================================" + + # W3: alege next story via DAG (propagă blocked dacă vreun dep a eșuat) + CURRENT_STORY=$(dag_next_story) + if [ -z "$CURRENT_STORY" ]; then + echo "" + echo "===================================================================" + if check_all_complete; then + echo " TOATE STORY-URILE DIN PRD SUNT COMPLETE!" + exit 0 + else + echo " NICIUN STORY ELIGIBIL (toate fie complete, fie failed, fie blocked)" + echo " Stories incomplete:" + jq -r '.userStories[] | select(.passes != true) | " - \(.id): \(.title) [failed=\(.failed // false) blocked=\(.blocked // false) retries=\(.retries // 0)]"' "$PRD_FILE" + exit 0 + fi + fi + + # Status curent + COMPLETE_NOW=$(jq '[.userStories[] | select(.passes == true)] | length' "$PRD_FILE") + NEXT_TITLE=$(jq -r --arg id "$CURRENT_STORY" '.userStories[] | select(.id == $id) | "\(.id): \(.title)"' "$PRD_FILE") + STORY_TAGS=$(jq -r --arg id "$CURRENT_STORY" '.userStories[] | select(.id == $id) | (.tags // []) | join(",")' "$PRD_FILE") + STORY_RETRIES=$(jq -r --arg id "$CURRENT_STORY" '.userStories[] | select(.id == $id) | (.retries // 0)' "$PRD_FILE") + echo " Progress: $COMPLETE_NOW / $TOTAL_STORIES stories complete" + echo " Next: $NEXT_TITLE [tags: ${STORY_TAGS:-}, retries: $STORY_RETRIES]" + echo "" + + # Pregătește prompt-ul cu context + FULL_PROMPT=$(cat <}) + +## PRD (prd.json): +$(cat "$PRD_FILE") + +## Progress până acum (progress.txt): +$(cat "$PROGRESS_FILE") + +## Instrucțiuni pentru această iterație: +$(cat "$PROMPT_FILE") +EOF +) + + # Execută Claude Code în modul non-interactiv + LOG_FILE="$SCRIPT_DIR/logs/iteration-$i-$(date +%Y%m%d-%H%M%S).log" + mkdir -p "$SCRIPT_DIR/logs" + + # --output-format json + --max-turns pentru control runtime + set +e + echo "$FULL_PROMPT" | claude -p \ + --dangerously-skip-permissions \ + --output-format json \ + --max-turns "$MAX_TURNS" \ + 2>&1 | tee "$LOG_FILE" + CLAUDE_EXIT=${PIPESTATUS[1]} + set -e + OUTPUT=$(cat "$LOG_FILE") + + # Rate limit budget tracking (best-effort, never blocks Ralph) + if [ -n "$USAGE_HELPER" ]; then + "$RALPH_PYTHON" "$USAGE_HELPER" append \ + "$USAGE_FILE" "$LOG_FILE" \ + --slug "$PROJECT_NAME" \ + --story-id "$CURRENT_STORY" \ + --iter "$i" 2>/dev/null || true + fi + + # W3: rate limit detection (max 1 retry per rulare) + if is_rate_limited "$OUTPUT" || [ "$CLAUDE_EXIT" = "29" ]; then + if [ "$RATE_LIMIT_RETRY_USED" = "0" ]; then + echo "" + echo " ⏸️ Rate limit detectat. Sleep ${RATE_LIMIT_SLEEP}s, apoi retry o dată." + RATE_LIMIT_RETRY_USED=1 + echo "## Rate limit la iter $i — sleep $RATE_LIMIT_SLEEP" >> "$PROGRESS_FILE" + sleep "$RATE_LIMIT_SLEEP" + continue # retry aceeași iterație + else + echo " ❌ Rate limit din nou — abort run, mark $CURRENT_STORY rate_limited" + dag_mark_failed "$CURRENT_STORY" "rate_limited" + echo "## Rate limit final la iter $i — abort" >> "$PROGRESS_FILE" + exit 2 + fi + fi + + # Verifică dacă toate task-urile sunt complete + if echo "$OUTPUT" | grep -q "COMPLETE"; then + echo "" + echo "===================================================================" + echo " RALPH A TERMINAT TOATE TASK-URILE!" + echo " Completat la iterația $i din $MAX_ITERATIONS" + echo "===================================================================" + exit 0 + fi + + # Verifică și prin prd.json + if check_all_complete; then + echo "" + echo "===================================================================" + echo " TOATE STORY-URILE DIN PRD SUNT COMPLETE!" + echo "===================================================================" + exit 0 + fi + + # W3: tag validation post-iter — chiar dacă Opus a marcat docs, dacă diff atinge .vue/.tsx, force ui + dag_force_tags "$CURRENT_STORY" >/dev/null 2>&1 || true + + # W3: dacă story-ul curent ÎNCĂ nu trece (passes==false), incrementăm retries + STILL_INCOMPLETE=$(jq -r --arg id "$CURRENT_STORY" '.userStories[] | select(.id == $id) | (.passes == true)' "$PRD_FILE") + if [ "$STILL_INCOMPLETE" != "true" ]; then + NEW_RETRY=$(dag_incr_retry "$CURRENT_STORY") + echo " Story $CURRENT_STORY încă incomplet. Retries: $NEW_RETRY/3" + if [ "$NEW_RETRY" -ge 3 ] 2>/dev/null; then + echo " ❌ $CURRENT_STORY failed: max_retries — sare la următorul" + # mark-failed e deja făcut de incr-retry când >=3, dar idempotent o re-aplicăm + dag_mark_failed "$CURRENT_STORY" "max_retries" + fi + else + echo " ✅ Story $CURRENT_STORY marcat passes=true în iterația asta." + fi + + echo " Iterația $i completă. Continuăm..." + sleep 2 +done + +echo "" +echo "===================================================================" +echo " Ralph a atins limita de iterații ($MAX_ITERATIONS)" +echo " Verifică progress.txt pentru status." +echo "===================================================================" +echo "" + +# Afișează stories incomplete +echo "Stories incomplete:" +jq -r '.userStories[] | select(.passes != true) | " - \(.id): \(.title)"' "$PRD_FILE" + +exit 1 diff --git a/scripts/ralph/usage.jsonl b/scripts/ralph/usage.jsonl new file mode 100644 index 0000000..2f03c32 --- /dev/null +++ b/scripts/ralph/usage.jsonl @@ -0,0 +1,15 @@ +{"ts": "2026-07-11T09:59:58+00:00", "slug": "echo-core", "story_id": "US-001", "iter": 1, "total_cost_usd": 1.1788641000000002, "input_tokens": 6801, "output_tokens": 10662, "cache_read": 2148867, "model": null, "duration_ms": 220891} +{"ts": "2026-07-11T10:03:08+00:00", "slug": "echo-core", "story_id": "US-001", "iter": 2, "total_cost_usd": 1.5010484999999998, "input_tokens": 6500, "output_tokens": 11928, "cache_read": 2264505, "model": null, "duration_ms": 186645} +{"ts": "2026-07-11T10:05:11+00:00", "slug": "echo-core", "story_id": "US-002", "iter": 3, "total_cost_usd": 1.1340510999999998, "input_tokens": 6635, "output_tokens": 5361, "cache_read": 1580897, "model": null, "duration_ms": 119118} +{"ts": "2026-07-11T10:08:05+00:00", "slug": "echo-core", "story_id": "US-003", "iter": 4, "total_cost_usd": 1.4051268999999997, "input_tokens": 6788, "output_tokens": 12175, "cache_read": 2484183, "model": null, "duration_ms": 170071} +{"ts": "2026-07-11T10:12:32+00:00", "slug": "echo-core", "story_id": "US-004", "iter": 5, "total_cost_usd": 1.6546155, "input_tokens": 6800, "output_tokens": 14493, "cache_read": 2492325, "model": null, "duration_ms": 263624} +{"ts": "2026-07-11T10:15:29+00:00", "slug": "echo-core", "story_id": "US-004", "iter": 6, "total_cost_usd": 1.0671055, "input_tokens": 6631, "output_tokens": 11521, "cache_read": 1651815, "model": null, "duration_ms": 172588} +{"ts": "2026-07-11T10:17:28+00:00", "slug": "echo-core", "story_id": "US-005", "iter": 7, "total_cost_usd": 1.3640780000000001, "input_tokens": 6646, "output_tokens": 6338, "cache_read": 2280720, "model": null, "duration_ms": 115308} +{"ts": "2026-07-11T10:23:30+00:00", "slug": "echo-core", "story_id": "US-006", "iter": 8, "total_cost_usd": 2.7279519999999997, "input_tokens": 6788, "output_tokens": 27979, "cache_read": 2733777, "model": null, "duration_ms": 358414} +{"ts": "2026-07-11T10:28:15+00:00", "slug": "echo-core", "story_id": "US-006", "iter": 9, "total_cost_usd": 2.57715855, "input_tokens": 679, "output_tokens": 7970, "cache_read": 1385564, "model": null, "duration_ms": 122619} +{"ts": "2026-07-11T10:31:41+00:00", "slug": "echo-core", "story_id": "US-007", "iter": 10, "total_cost_usd": 1.4841890000000002, "input_tokens": 6801, "output_tokens": 14697, "cache_read": 2548080, "model": null, "duration_ms": 201899} +{"ts": "2026-07-11T10:36:11+00:00", "slug": "echo-core", "story_id": "US-008", "iter": 11, "total_cost_usd": 1.6913165, "input_tokens": 10857, "output_tokens": 20527, "cache_read": 2717765, "model": null, "duration_ms": 266234} +{"ts": "2026-07-11T10:38:19+00:00", "slug": "echo-core", "story_id": "US-008", "iter": 12, "total_cost_usd": 0.9906942, "input_tokens": 16171, "output_tokens": 7730, "cache_read": 1350904, "model": null, "duration_ms": 123527} +{"ts": "2026-07-11T10:42:30+00:00", "slug": "echo-core", "story_id": "US-009", "iter": 13, "total_cost_usd": 1.7101233999999998, "input_tokens": 7439, "output_tokens": 19964, "cache_read": 2799168, "model": null, "duration_ms": 247394} +{"ts": "2026-07-11T10:44:39+00:00", "slug": "echo-core", "story_id": "US-009", "iter": 14, "total_cost_usd": 1.0942976, "input_tokens": 6648, "output_tokens": 7613, "cache_read": 1931572, "model": null, "duration_ms": 125381} +{"ts": "2026-07-11T11:16:45+00:00", "slug": "echo-core", "story_id": "US-010", "iter": 15, "total_cost_usd": 1.1445886, "input_tokens": 6795, "output_tokens": 8082, "cache_read": 2054902, "model": null, "duration_ms": 124204} diff --git a/tasks/prd-echo-core.md b/tasks/prd-echo-core.md new file mode 100644 index 0000000..b800281 --- /dev/null +++ b/tasks/prd-echo-core.md @@ -0,0 +1,104 @@ +# PRD: Echo Core + +## 1. Introducere + +Integrare pocket-tts (Kyutai) ca engine TTS nou in Echo Core. + +**Data:** 2026-07-11 +**Status:** Draft +**Mode:** FEATURE + +## 2. Context Tehnic + +**Proiect existent detectat:** +- Stack: python-legacy +- Config: requirements.txt +- Scripts: + +## 3. Obiective + +### Obiectiv Principal +Integrare pocket-tts (Kyutai) ca engine TTS nou in Echo Core + +### Obiective Secundare +- Integrare pocket-tts (Kyutai) ca engine TTS nou in Echo Core + +### Metrici de Succes +- Toate funcționalitățile implementate conform spec +- Tests passing (coverage > 80%) +- Code quality: lint + typecheck pass + +## 4. User Stories + +### US-001: Integrare pocket-tts (Kyutai) ca engine TTS nou in Echo Core +**Ca** utilizator +**Vreau** integrare pocket-tts (kyutai) ca engine tts nou in echo core +**Pentru că** pot folosi aplicația eficient + +**Acceptance Criteria:** +- [ ] Funcționalitatea implementată conform descrierii +- [ ] Input validation în loc +- [ ] Error handling pentru cazuri edge +- [ ] Tests cu pytest (coverage > 80%) +- [ ] Code quality: lint + typecheck pass + +**Priority:** 10 + +### US-002: Tests și Documentație +**Ca** developer +**Vreau** teste comprehensive și documentație +**Pentru că** asigur calitatea codului + +**Acceptance Criteria:** +- [ ] Unit tests pentru toate funcțiile (coverage > 80%) +- [ ] Integration tests pentru flow-uri principale +- [ ] README cu instrucțiuni de utilizare +- [ ] Docstrings pentru funcții publice +- [ ] pytest rulează fără erori + +**Priority:** 20 + +## 5. Cerințe Funcționale + +1. [REQ-001] Integrare pocket-tts (Kyutai) ca engine TTS nou in Echo Core + +## 6. Non-Goals (Ce NU facem) + +- Interfață grafică (GUI) - doar CLI/API +- Suport multiple limbaje - doar Python +- Deployment infrastructure - doar cod functional + +## 7. Considerații Tehnice + +### Stack/Tehnologii +- Limbaj: Python +- Testing: pytest +- Linting: pylint / eslint (depinde de stack) +- Type checking: mypy / typescript + +### Patterns de Urmat +- Clean code principles +- SOLID principles unde aplicabil +- Error handling consistent +- Input validation strict + +### Riscuri Tehnice +- Edge cases la input validation +- Performance pentru volume mari de date (dacă aplicabil) + +## 8. Considerații Security + +- Input validation pentru toate datele externe +- Error messages fără info sensibilă +- Principle of least privilege + +## 9. Open Questions + +- [ ] Performance requirements specifice? +- [ ] Limite pe input sizes? +- [ ] Specific error handling patterns preferați? + +--- + +**Generated by:** Echo (Ralph PRD Generator) +**Date:** 2026-07-11 09:54