feat(ralph): smart gates + DAG + dashboard live (W3)

Restructurare Ralph QC loop pe smart gate dispatcher tag-driven (în loc de
5 faze fixe), DAG dependsOn cu propagare blocked, retry guard 3-strike, rate
limit detection, plus dashboard live cu polling 5s.

Changes:
- tools/ralph_prd_generator.py: parametru optional final_plan_path; când e
  furnizat, invocă Claude Opus pe final-plan.md pentru extragere user stories
  cu schema extinsă (tags, dependsOn, acceptanceCriteria 3-5). Backward compat
  păstrat — fără final_plan_path, fallback la heuristic-ul vechi.
- tools/ralph/prd-template.json: schema W3 (tags[], dependsOn[], retries,
  failed, blocked, failureReason, requiresDesignReview).
- tools/ralph/prompt.md: 4 faze (impl, base quality, smart gates, commit) +
  dispatcher pe story.tags. Tags vide → run-all-gates fallback (safe default).
- tools/ralph_dag.py (nou): tag validation heuristic anti-silent-regression
  (force ui dacă diff atinge .vue/.tsx/.html/.css/.scss; force db pentru
  migrations sau .sql; force vercel dacă există vercel.json) + topological
  sort cu blocked propagation + atomic prd.json updates.
- tools/ralph/ralph.sh: --max-turns 30, DAG-aware story selection, retry
  counter cu auto-fail la 3, rate limit detection (sleep 30min + 1 retry),
  CLI subcommands prin tools/ralph_dag.py helper.
- dashboard/handlers/ralph.py (nou): /api/ralph/status + /<slug>/log + /prd
  + /stop. Defensive vs corrupt prd.json. Sandbox-ed PID kill.
- dashboard/ralph.html (nou): live cards 3/2/1 col responsive, polling 5s,
  drawer pentru log/PRD viewer, status colors (--status-running/blocked/
  failed/complete declarate inline), Lucide icons cu aria-labels.
- dashboard/api.py: mount /api/ralph/* (GET status/log/prd, POST stop).
- tests/: 72 teste noi (smart gates, DAG, retry, dashboard endpoint).

Note arhitecturale:
- Polling 5s ales peste SSE/WebSocket (suficient pentru iter Ralph 8-15min)
- Tag validation rulează POST-iter pe diff git pentru anti-silent-regression
- Rate limit retry: 1 dată per rulare, apoi mark failed=rate_limited

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-26 18:36:35 +00:00
parent e06a79d98c
commit 655ed3ae09
11 changed files with 2282 additions and 189 deletions

View File

@@ -1,203 +1,120 @@
# Ralph - Instrucțiuni pentru Iterație
# 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 și apoi te oprești.
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 pentru această iterație
## Workflow per iterație (4 faze, gates condiționale pe `story.tags`)
### 1. Citește contextul
- PRD-ul și progress.txt sunt furnizate în context
- Înțelege ce stories sunt deja complete (`passes: true`)
- Identifică următorul story de implementat (prioritate cea mai mică dintre cele incomplete)
- Notează `techStack.commands` din PRD pentru comenzile corecte
### Faza 0: Citește contextul
### 2. Management branch
- Verifică dacă ești pe branch-ul corect (specificat în `branchName` din PRD)
- Dacă nu, creează și checkout branch-ul:
```bash
git checkout -b <branchName>
```
- Dacă branch-ul există deja, doar checkout:
```bash
git checkout <branchName>
```
- 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.
### 3. Selectează story-ul
- Alege story-ul cu cea mai mică prioritate care are `passes: false`
- Citește atent acceptance criteria
- Verifică câmpul `requiresBrowserCheck` - dacă e `true`, trebuie verificare vizuală
### Faza 1: IMPLEMENTARE (mereu)
### 4. Implementare
- Implementează DOAR acest story
- Urmează patterns existente în codebase
- Fii minimal și focusat - nu adăuga funcționalități extra
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).
### 5. Quality Checks
Rulează TOATE verificările înainte de commit. Folosește comenzile din `techStack.commands`:
### Faza 2: QUALITY BASE (mereu, înainte de gates)
Folosește `techStack.commands`:
```bash
# Folosește comenzile din prd.json techStack.commands:
{techStack.commands.typecheck} # Type checking
{techStack.commands.lint} # Linting
{techStack.commands.test} # Tests (dacă există)
{techStack.commands.typecheck} # ex: npm run typecheck / mypy .
{techStack.commands.lint} # ex: npm run lint / ruff check .
{techStack.commands.test} # ex: npm test / pytest
```
**Comenzi standard per stack:**
**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).
| Stack | Typecheck | Lint | Test |
|-------|-----------|------|------|
| Next.js/TS | npm run typecheck | npm run lint | npm test |
| Node.js | npm run typecheck | npm run lint | npm test |
| Python | mypy . | ruff check . | python -m pytest |
| Go | - | golangci-lint run | go test ./... |
### Faza 3: SMART GATES (dispatcher pe `story.tags`)
**IMPORTANT**: Nu face commit dacă verificările eșuează. Repară mai întâi.
Tags posibile: `ui`, `db`, `vercel`, `refactor`, `docs`, `backend`, `infra`.
### 6. Verificare Browser (pentru UI stories)
Aplică DOAR gate-urile potrivite — **nu rulează toate**:
**DACĂ story-ul are `requiresBrowserCheck: true` sau implică UI:**
| 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) |
Folosește **agent-browser CLI** pentru verificare vizuală. Agent-browser e optimizat pentru agenți AI cu referințe compacte (@e1, @e2) care consumă minim tokeni.
**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/`.
#### 6.1 Pornește dev server-ul
```bash
# Folosește comanda din techStack.commands.start
{techStack.commands.start}
# Exemplu: npm run dev
```
**Multi-tag**: rulează gate-uri pentru fiecare tag (ex: `["ui", "backend"]` → atât `/qa` cât și `/review`).
Așteaptă să pornească (verifică output-ul pentru "ready" sau similar).
**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).
#### 6.2 Navighează la pagină
```bash
agent-browser navigate "http://localhost:{techStack.port}"
# Exemplu: agent-browser navigate "http://localhost:3000"
```
### Faza 4: COMMIT + MARK
#### 6.3 Ia snapshot pentru verificare
```bash
agent-browser snapshot
```
Snapshot-ul returnează o listă de elemente cu referințe compacte:
```
@e1: heading "Welcome"
@e2: button "Login"
@e3: textbox "Email"
@e4: textbox "Password"
@e5: button "Submit"
```
**Verifică în snapshot:**
- Elementele cheie din acceptance criteria există
- Textul e corect
- Structura paginii e corectă
#### 6.4 Testează interacțiunile (dacă e cazul)
```bash
# Click pe un element
agent-browser click @e2
# Fill un input
agent-browser fill @e3 "test@example.com"
# Așteaptă o schimbare
agent-browser snapshot # verifică noua stare
```
#### 6.5 Salvează screenshot ca dovadă
```bash
agent-browser screenshot ./scripts/ralph/screenshots/US-{id}-$(date +%Y%m%d-%H%M%S).png
# Exemplu: agent-browser screenshot ./scripts/ralph/screenshots/US-001-20240115-143022.png
```
#### 6.6 Verifică erori
```bash
# Verifică console pentru erori
agent-browser console
```
**IMPORTANT**:
- NU marca story-ul complete dacă verificarea vizuală eșuează!
- Dacă găsești erori în browser, repară-le înainte de commit
- Screenshots sunt salvate în `scripts/ralph/screenshots/` pentru referință
### 7. Documentare (dacă ai descoperit ceva util)
Dacă ai descoperit patterns sau gotchas, actualizează `AGENTS.md` în directorul relevant:
- API patterns
- Dependențe non-evidente
- Convenții de cod
- Cum să testezi anumite funcționalități
### 8. Commit
Format commit message:
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
```
### 9. Marchează story-ul ca complet
**CRITIC**: Actualizează `scripts/ralph/prd.json`:
- Setează `passes: true` pentru story-ul implementat
- Adaugă note relevante în câmpul `notes`
### 10. Actualizează progress.txt
Adaugă la sfârșitul fișierului `scripts/ralph/progress.txt`:
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]
### Status: Complete
### Story implementat: [ID] - [Title] (tags: [ui, backend])
### Status: Complete / Partial / Failed
### Verificări:
### Gates rulate:
- Typecheck: PASS
- Lint: PASS
- Tests: PASS/SKIP
- Browser check: PASS/N/A
- /qa (ui): PASS — screenshot la scripts/ralph/screenshots/...
- /review (backend): PASS
### Learnings:
- [Ce ai învățat]
- [Patterns descoperite]
- [Patterns descoperite, gotchas]
### Next steps:
- [Ce rămâne de făcut]
### 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. **TOATE CHECKS TREBUIE SĂ TREACĂ** - Nu face commit cu erori
3. **VERIFICARE BROWSER PENTRU UI** - Obligatorie dacă `requiresBrowserCheck: true`
4. **ACTUALIZEAZĂ prd.json** - Altfel iterația următoare va repeta munca
5. **FII CONCIS** - Nu over-engineer
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ă)
## Comenzi agent-browser (referință rapidă pentru gate `ui`)
```bash
# Navigare
agent-browser navigate "http://localhost:3000/page"
# Snapshot (vedere compactă a paginii)
agent-browser snapshot
# Click pe element (folosind ref din snapshot)
agent-browser navigate "http://localhost:{techStack.port}"
agent-browser snapshot # listă elemente compactă (@e1, @e2...)
agent-browser click @e5
# Fill input
agent-browser fill @e3 "value"
# Screenshot
agent-browser screenshot ./path/to/file.png
# Console logs
agent-browser console
# Așteaptă text
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 stories au `passes: true`, răspunde cu:
Dacă TOATE story-urile au `passes: true` (sau combinat cu `failed: true` / `blocked: true` astfel că nimic nu mai e eligibil):
```
<promise>COMPLETE</promise>