chore: auto-commit from dashboard

This commit is contained in:
2026-07-12 19:28:42 +00:00
parent 80eb8034b3
commit 4d2dbfb8a7
22 changed files with 582 additions and 520 deletions

165
CLAUDE.md
View File

@@ -6,15 +6,9 @@ Nu ești un tool de cod. Ești asistent — ajuți cu tot: tehnic, organizare, c
## Cum funcționează
Mesajele ajung la tine prin adaptoare (Discord, Telegram, WhatsApp) → `router.py``claude_session.py` → Claude CLI subprocess → răspuns trimis înapoi.
Mesajele ajung prin adaptoare (Discord, Telegram, WhatsApp) → `router.py``claude_session.py` → Claude CLI subprocess → răspuns înapoi.
Personalitatea ta se construiește din `personality/*.md`, concatenate în ordine:
- `IDENTITY.md` — cine ești
- `SOUL.md` — principii, ton, granițe
- `USER.md` — despre Marius
- `AGENTS.md` — reguli operaționale, model selection, securitate
- `HEARTBEAT.md` — verificări periodice
- `TOOLS.md` — unelte disponibile
Personalitatea se construiește din `personality/*.md`, concatenate în ordine: `IDENTITY.md` (cine ești) → `SOUL.md` (principii, ton, granițe) → `USER.md` (despre Marius) → `AGENTS.md` (reguli operaționale, model selection, securitate) → `HEARTBEAT.md` (verificări periodice) → `TOOLS.md` (unelte). `VOICE_MODE.md` se adaugă dinamic pe turnuri voice.
## Principii de Workflow
@@ -24,54 +18,27 @@ Personalitatea ta se construiește din `personality/*.md`, concatenate în ordin
Pentru orice task de cod cu **3+ pași sau decizii arhitecturale**, intră în plan mode înainte să atingi cod. Dacă lucrurile o iau razna mid-task (5+ erori în lanț, scope creep, premise false), **STOP** și re-planifică imediat.
Folosește skill-urile gstack pentru review:
- `/plan-eng-review` — arhitectură, edge cases, performance
- `/plan-ceo-review` — scope, ambiție, 10-star product
- `/plan-design-review` — UI/UX înainte de implementare
- `/autoplan` — toate trei automat, cu approval gate la final
Skill-uri gstack pentru review: `/plan-eng-review` (arhitectură, edge cases, performance), `/plan-ceo-review` (scope, ambiție, 10-star product), `/plan-design-review` (UI/UX înainte de implementare), `/autoplan` (toate trei automat, cu approval gate la final).
### 2. Strategie de subagenți
Folosește subagenți (`Agent` tool) liber pentru a păstra context window-ul curat. Offload research, exploration, parallel analysis. **Un singur task per subagent** — nu suprasolicita.
- `Explore` — căutări codebase
- `general-purpose` — research multi-step
- `Plan` — design de implementare
Folosește subagenți (`Agent` tool) liber pentru a păstra context window-ul curat. Offload research, exploration, parallel analysis. **Un singur task per subagent.** `Explore` — căutări codebase; `general-purpose` — research multi-step; `Plan` — design de implementare.
### 3. Self-Improvement Loop
După **ORICE** corectare de la Marius, actualizează `tasks/lessons.md` cu pattern-ul învățat. Scrie pentru tine viitor — ce a prevenit corectarea, regula, când se aplică.
La începutul oricărei sesiuni de cod (înainte de plan mode), **citește `tasks/lessons.md`** și aplică lecțiile relevante. Iterează pe ele neobosit pentru a evita rate drop-uri pe greșeli repetate.
Ralph va citi și el acest fișier între iterații (extensie viitoare — vezi `tools/ralph/prompt.md`).
După **ORICE** corectare de la Marius, actualizează `tasks/lessons.md` cu pattern-ul învățat (ce a prevenit corectarea, regula, când se aplică). La începutul oricărei sesiuni de cod (înainte de plan mode) **citește `tasks/lessons.md`** și aplică lecțiile relevante, ca să eviți rate drop-uri pe greșeli repetate. Ralph va citi și el acest fișier între iterații (extensie viitoare — vezi `tools/ralph/prompt.md`).
### 4. Verificare înainte de „done"
Nu marca un task complet fără să verifici că funcționează. Comportamentul diferit între `main` și branch-ul tău contează doar dacă e relevant pentru task. Întreabă-te mereu: **„Ar aproba un staff engineer asta?"**
Folosește din gstack:
- `/qa` — test + fix loop iterativ
- `/qa-only` — doar raport de bug-uri
- `/review` — pre-merge diff review
- `/devex-review` — DX live audit
- `/ship` — full pipeline (tests + CHANGELOG + PR)
Nu marca un task complet fără să verifici că funcționează. Diferența `main` vs branch contează doar dacă e relevantă pentru task. Întreabă-te: **„Ar aproba un staff engineer asta?"** Din gstack: `/qa` (test + fix loop), `/qa-only` (doar raport bug-uri), `/review` (pre-merge diff), `/devex-review` (DX live audit), `/ship` (full pipeline: tests + CHANGELOG + PR).
### 5. Cere eleganță (echilibrat)
Pentru schimbări non-triviale: pauză și întreabă **„e o cale mai elegantă?"** Dacă fix-ul se simte hacky, *„knowing everything I know now, implement the elegant solution"* — implementează soluția elegantă din capul locului.
**Skip pentru fixes simple, schimbări obvii** — nu over-engineer. Provoacă-ți munca înainte să o prezinți.
Folosește `/codex challenge` (mod adversarial care încearcă să spargă codul) sau `/codex review` pentru second opinion.
Pentru schimbări non-triviale: pauză și întreabă **„e o cale mai elegantă?"** Dacă fix-ul se simte hacky: *„knowing everything I know now, implement the elegant solution"*. **Skip pentru fixes simple/obvii** — nu over-engineer. Provoacă-ți munca înainte s-o prezinți. `/codex challenge` (adversarial) sau `/codex review` pentru second opinion.
### 6. Bug fixing autonom
Când Marius dă un bug report: **just fix it**. Fără hand-holding. Indică logs, errors, failing tests — apoi rezolvă-le. Zero context switching cerut de la user.
Folosește `/investigate` pentru debugging sistematic (4 faze: investigate → analyze → hypothesize → implement). **Iron Law: fără fix fără root cause.**
Ralph face exact asta noaptea, autonom, pe proiectele aprobate.
La bug report de la Marius: **just fix it**, fără hand-holding. Indică logs, errors, failing tests — apoi rezolvă-le. `/investigate` pentru debugging sistematic (4 faze: investigate → analyze → hypothesize → implement). **Iron Law: fără fix fără root cause.** Ralph face exact asta noaptea, autonom, pe proiectele aprobate.
## Task Management
@@ -86,7 +53,7 @@ Pentru work tracking folosește **Echo Task Board** (`dashboard/`), nu fișiere
## Core Principles
- **Simplicitate înainte de toate** — cele mai simple schimbări posibile. Impact minim, cod minimal.
- **Simplicitate înainte de toate** — cele mai simple schimbări posibile. Impact minim, cod minimal.
- **Zero lene** — root causes, nu temporary fixes. Standard de senior developer.
- **Impact minim** — atinge doar ce e necesar. Fără side effects la features noi.
@@ -121,39 +88,39 @@ source .venv/bin/activate && pip install -r requirements.txt
- **Telegram** (`src/adapters/telegram_bot.py`) — comenzi + inline keyboards, split la 4096 caractere
- **WhatsApp** (`src/adapters/whatsapp.py`) — polling Baileys bridge la `http://127.0.0.1:8098`, split la 4096 caractere
**Sesiuni** (`src/claude_session.py`): O sesiune persistentă per canal. `claude --resume <session_id>`. Mesajele externe sunt împachetate în markeri `[EXTERNAL CONTENT]`.
**Sesiuni** (`src/claude_session.py`): o sesiune persistentă per canal, `claude --resume <session_id>`. Mesajele externe împachetate în markeri `[EXTERNAL CONTENT]`.
**State:** `sessions/active.json` — channel ID → `{session_id, model, message_count, ...}`
**Credențiale** (`src/credential_store.py`): Keyring de sistem, serviciu `"echo-core"`. Niciodată secrete ca argumente CLI.
**Credențiale** (`src/credential_store.py`): keyring de sistem, serviciu `"echo-core"`. Niciodată secrete ca argumente CLI.
**Config** (`src/config.py`): `config.json` cu dot-notation. Namespaces: `channels`, `telegram_channels`, `whatsapp_channels`.
**Scheduler** (`src/scheduler.py`): APScheduler + `cron/jobs.json`, sesiuni izolate.
**Heartbeat** (`src/heartbeat.py`): Verificări email, calendar, KB, git. Ore tăcere 23-08.
**Heartbeat** (`src/heartbeat.py`): verificări email, calendar, KB, git. Ore tăcere 23-08.
**Ralph** (`tools/ralph/`): Sistem autonom de execuție. `ralph.sh` este un bash loop care cheamă `claude` CLI (subscription, nu API) per user story din `prd.json`. Generarea PRD se face cu `tools/ralph_prd_generator.py` (model Opus). Workspace-ul proiectelor e la `~/workspace/`.
**Ralph** (`tools/ralph/`): sistem autonom de execuție. `ralph.sh` e un bash loop care cheamă `claude` CLI (subscription, nu API) per user story din `prd.json`. PRD generat cu `tools/ralph_prd_generator.py` (Opus). Workspace la `~/workspace/`.
**Memory** (`memory/` în acest repo — sursa unică de adevăr). Retrieval **hibrid**, două căi:
1. **Navigare (întâi, pentru lookup pe subiect/parafrază):** citește `memory/kb/index.md` (router cu folderele), alege folderul relevant, apoi citește `memory/kb/<folder>/index.md` (titlu + tags + descriere 1 rând per notă) și deschide doar notele relevante. Ieftin și funcționează chiar dacă Ollama e picat. Generat de `tools/update_notes_index.py` (regenerat din heartbeat).
1. **Navigare (întâi, pentru lookup pe subiect/parafrază):** citește `memory/kb/index.md` (router cu folderele), alege folderul relevant, apoi `memory/kb/<folder>/index.md` (titlu + tags + descriere 1 rând per notă) și deschide doar notele relevante. Ieftin și funcționează chiar dacă Ollama e picat. Generat de `tools/update_notes_index.py` (regenerat din heartbeat).
2. **RAG semantic (pentru recall fuzzy):** `src/memory_search.py` — embeddings Ollama all-minilm (384 dim) + cosine pe SQLite. `search()` deduplică pe best-chunk-per-fișier și, dacă Ollama remote (`config.json → ollama.url`) e indisponibil, cade pe căutare keyword și marchează rezultatele cu `degraded: True` (semnalează userului că recall-ul semantic a lipsit).
*Notă istorică:* `memory/` era symlink la repo-ul legacy Clawdbot; consolidat în echo-core în migrația OpenClaw (2026-04).
**Dashboard** (`dashboard/`): Echo Task Board — HTTP API + UI static servit de `dashboard/api.py` pe portul 8088, de obicei în spatele unui reverse proxy la `/echo/`. Logica endpoint-urilor împărțită în mixin-uri `dashboard/handlers/*.py`; path-urile centralizate în `dashboard/constants.py`. Template systemd user unit la `dashboard/echo-taskboard.service`. `workspace.html` este hub-ul unificat de proiecte (fostul ralph.html + workspace.html); `/echo/ralph.html` → 302 redirect la `/echo/workspace.html`. Autentificare prin cookie httpOnly `dashboard=<token>`; `DASHBOARD_TOKEN` setat în `dashboard/.env`.
**Dashboard** (`dashboard/`): Echo Task Board — HTTP API + UI static servit de `dashboard/api.py` pe portul 8088, de obicei în spatele unui reverse proxy la `/echo/`. Logica endpoint-urilor în mixin-uri `dashboard/handlers/*.py`; path-uri centralizate în `dashboard/constants.py`. Template systemd user unit la `dashboard/echo-taskboard.service`. `workspace.html` e hub-ul unificat de proiecte (fostul ralph.html + workspace.html); `/echo/ralph.html` → 302 redirect la `/echo/workspace.html`. Autentificare prin cookie httpOnly `dashboard=<token>`; `DASHBOARD_TOKEN` în `dashboard/.env`.
## Dashboard — Note arhitecturale
**Cookie auth:** dashboard folosește httpOnly cookie `dashboard=...`; SameSite=Strict; Path=/echo/. EventSource SSE trimite cookie-ul automat. `DASHBOARD_TOKEN` din `dashboard/.env` — setează o dată, restart service. Resetare: schimbă valoarea din .env + restart.
**Cookie auth:** httpOnly cookie `dashboard=...`; SameSite=Strict; Path=/echo/. EventSource SSE trimite cookie-ul automat. `DASHBOARD_TOKEN` din `dashboard/.env` — setează o dată, restart service. Resetare: schimbă valoarea + restart.
**jsonlock helper (`src/jsonlock.py`):** folosește `read_locked(path)` / `write_locked(path, mutator)` pentru orice scriere la `approved-tasks.json`, `sessions/*.json`. Lock pe sidecar `<path>.lock` (inode stabil chiar și după os.replace). Ordine canonică lock-uri: alfabetic după filename. Re-entrant (threading.local refcount).
**jsonlock helper (`src/jsonlock.py`):** `read_locked(path)` / `write_locked(path, mutator)` pentru orice scriere la `approved-tasks.json`, `sessions/*.json`. Lock pe sidecar `<path>.lock` (inode stabil chiar și după os.replace). Ordine canonică lock-uri: alfabetic după filename. Re-entrant (threading.local refcount). Expune și `LockTimeoutError`.
**Slug convention:** slug-urile proiectelor validează cu regex `^[a-z0-9][a-z0-9\-_]{1,38}[a-z0-9]$` — permit hifene ȘI underscore. Validare centralizată în `dashboard/handlers/_validators.py`.
**Proxy timeout:** pentru nginx/caddy, setează `proxy_read_timeout >= 60s` și `proxy_buffering off` pentru `/echo/api/projects/stream` și `/echo/api/projects/<slug>/plan/*` (SSE + planning au răspunsuri lungi).
**Planning fragmentation (known limit):** sesiunile de planning pornite din Discord/Telegram nu se fuzionează cu cele din dashboard. Dashboard afișează sesiunea cea mai recentă per slug indiferent de adapter. P3 follow-up.
**Planning fragmentation (known limit):** sesiunile de planning din Discord/Telegram nu se fuzionează cu cele din dashboard. Dashboard afișează sesiunea cea mai recentă per slug indiferent de adapter. P3 follow-up.
## Ralph — Execuție autonomă de proiecte
@@ -171,7 +138,7 @@ Live dashboard → /echo/workspace.html — cards per proiect cu status
```
**Două căi de aprobare**:
- **Direct**: `/a <slug>` — pentru proiecte simple unde descrierea e suficientă
- **Direct**: `/a <slug>` — pentru proiecte simple unde descrierea e suficientă.
- **Conversational** (W2 — `/plan <slug>` SAU buton "Planifică" pe `/l`): Echo poartă o conversație multi-fază prin skills gstack (`/office-hours``/plan-ceo-review``/plan-eng-review` → opțional `/plan-design-review` dacă tags include "ui"), produce `~/workspace/<slug>/scripts/ralph/final-plan.md` și prezintă rezumat cu butonul "✅ Dau drumul tonight". `night-execute` îl folosește ca input pentru PRD generator (Opus extrage user stories cu acceptanceCriteria, tags, dependsOn).
**Comenzi** (funcționează pe toate adaptoarele — Discord, Telegram, WhatsApp):
@@ -188,16 +155,16 @@ Live dashboard → /echo/workspace.html — cards per proiect cu status
| `/k <slug>` | Trimite SIGTERM la ralph.sh PID |
**UX interactiv** (Discord/Telegram):
- `/l` deschide `RalphRootView` (Discord) / InlineKeyboardMarkup (Telegram) cu butoane per workspace project
- Click pe proiect → submeniu cu acțiuni: Propune feature (modal/ForceReply), 🧠 Planifică (W2), 👁 Vezi PRD, 📊 Status, ✅ Aprobă tonight, 🛑 Stop, 🔙 Înapoi
- La sfârșitul planning: butoane ✅ Dau drumul tonight / ✏️ Mai gândim / 🛑 Anulează
- State per `(adapter, channel)` în `sessions/ralph_flow.json` și `sessions/planning.json` (TTL 10min/60min)
- `/l` deschide `RalphRootView` (Discord) / InlineKeyboardMarkup (Telegram) cu butoane per workspace project.
- Click pe proiect → submeniu: Propune feature (modal/ForceReply), 🧠 Planifică (W2), 👁 Vezi PRD, 📊 Status, ✅ Aprobă tonight, 🛑 Stop, 🔙 Înapoi.
- La sfârșitul planning: butoane ✅ Dau drumul tonight / ✏️ Mai gândim / 🛑 Anulează.
- State per `(adapter, channel)` în `sessions/ralph_flow.json` și `sessions/planning.json` (TTL 10min/60min).
Pe **Discord**: slash commands native cu autocomplete dinamic: `/p <tab>` listează workspace, `/a <tab>` pending, `/k <tab>` running. Modal cu `TextInput` pentru descriere. Critical pattern: `await interaction.response.defer(ephemeral=True)` în orice button callback cu I/O (Discord 3s timeout).
Pe **Discord**: slash commands native cu autocomplete dinamic `/p <tab>` listează workspace, `/a <tab>` pending, `/k <tab>` running. Modal cu `TextInput` pentru descriere. Critical pattern: `await interaction.response.defer(ephemeral=True)` în orice button callback cu I/O (Discord 3s timeout).
Pe **Telegram**: `callback_ralph` cu pattern `^ralph:` rutează acțiuni; `ForceReply` pentru input text descriere.
Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keyword shortcuts**: `aprob <slug>``/a <slug>`, `stop <slug>``/k <slug>`, `stare`/`stare <slug>``/l`/`/l <slug>` (case-insensitive, doar pe WhatsApp; Discord/Telegram nu sunt afectate). `propose` intentionally NOT covered — descrierea fragilă.
Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keyword shortcuts**: `aprob <slug>``/a <slug>`, `stop <slug>``/k <slug>`, `stare`/`stare <slug>``/l`/`/l <slug>` (case-insensitive, doar pe WhatsApp; Discord/Telegram neafectate). `propose` intenționat NEacoperit — descrierea fragilă.
**Aliasuri legacy** (funcționează încă pentru backwards compat): `!propose`, `!approve`, `!status`, `!stop`.
**Aliasuri legacy** (backwards compat): `!propose`, `!approve`, `!status`, `!stop`.
**Fișiere cheie Ralph:**
@@ -205,14 +172,14 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor
|------|-----|
| `approved-tasks.json` | Coordonare între cron jobs + UX. Schema: `{name, description, status, planning_session_id, final_plan_path, repo, branch, base_branch, proposed_at, approved_at, started_at, pid}` |
| `prompts/planning_agent.md` | System prompt pentru `PlanningSession` (multi-fază conversational) |
| `src/planning_session.py` | Wrapper subprocess `claude -p` cu working dir = `~/workspace/<slug>/`, `--add-dir` skills gstack + project artifacts. `--max-turns=20` cu retry pe `error_max_turns` |
| `src/planning_orchestrator.py` | Coordonează fazele: fresh subprocess per skill phase; coordinează prin disk artifacts gstack convention; tag detection ui-scope |
| `sessions/planning.json` | State per `(adapter, channel)` planning session: session_id, current_phase, etc. — pentru re-resume la restart |
| `src/planning_session.py` | Wrapper subprocess `claude -p`, working dir = `~/workspace/<slug>/`, `--add-dir` skills gstack + project artifacts. `--max-turns=20` cu retry pe `error_max_turns` |
| `src/planning_orchestrator.py` | Coordonează fazele: fresh subprocess per skill phase; coordonare prin disk artifacts (convenție gstack); tag detection ui-scope |
| `sessions/planning.json` | State per `(adapter, channel)` planning session: session_id, current_phase etc. — pentru re-resume la restart |
| `tools/ralph/ralph.sh` | Bash loop DAG-aware: N iterații × `claude` CLI per story; folosește `tools/ralph_dag.py` pentru selecție topologică, retry guard (3 retries), rate-limit detection |
| `tools/ralph/prompt.md` | Smart gates dispatcher pe `story.tags` (Faza 3): refactor→/workflow:simplify, ui→/qa+screenshot, vercel→push+gh checks, db→schema diff, default→/review |
| `tools/ralph/prd-template.json` | Template prd.json: stories cu `acceptanceCriteria[]`, `tags[]`, `dependsOn[]`, `passes`, `retries` |
| `tools/ralph_prd_generator.py` | Generează prd.json. Cu `final_plan_path` (de la PlanningOrchestrator) → Opus extrage stories cu acceptance criteria. Fără → backwards-compat description-only |
| `tools/ralph_dag.py` | Pure functions Python (testabile): `infer_tags_from_paths`, `force_include_tags`, `topological_eligible`, `mark_failed`, blocked propagation iterativă. CLI subcommands chemate din ralph.sh (`infer-tags`, `next-story`, `mark-failed`, `incr-retry`) |
| `tools/ralph_dag.py` | Pure functions (testabile): `infer_tags_from_paths`, `force_include_tags`, `topological_eligible`, `mark_failed`, blocked propagation iterativă. CLI subcommands din ralph.sh (`infer-tags`, `next-story`, `mark-failed`, `incr-retry`) |
| `tools/ralph_usage.py` | Rate limit budget tracking: pure functions `extract_usage_entry`, `parse_usage_jsonl`, `aggregate_by_day`, `aggregate_by_project` + CLI append/summarize. Atomic write JSONL |
| `~/workspace/<name>/scripts/ralph/usage.jsonl` | Append-only log per `claude -p` call (cost, tokens, model, duration) — generat din ralph.sh, agregat de `/api/ralph/usage` |
| `~/workspace/<name>/scripts/ralph/final-plan.md` | Output planning agent — citit de PRD generator |
@@ -220,7 +187,7 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor
| `~/workspace/<name>/scripts/ralph/logs/` | Loguri ralph.sh per rulare |
| `dashboard/handlers/ralph.py` | Endpoints `/api/ralph/status`, `/<slug>/log`, `/<slug>/prd`, `/<slug>/stop`, `/<slug>/rollback`, `/usage[?days=N]`, `/stream` (SSE) |
| `dashboard/handlers/projects.py` | Endpoints unificate proiecte: `/api/projects`, `/propose`, `/approve`, `/unapprove`, `/cancel`, `/<slug>/plan/*`, `/stream` (SSE), `/signature` |
| `dashboard/workspace.html` | Hub unificat proiecte — cards status/iter/ETA, log, prd, stop/rollback. Realtime SSE cu fallback polling 5s. Înlocuiește ralph.html (care face 302 redirect aici) |
| `dashboard/workspace.html` | Hub unificat proiecte — cards status/iter/ETA, log, prd, stop/rollback. Realtime SSE cu fallback polling 5s. Înlocuiește ralph.html (302 redirect aici) |
| `dashboard/.env` | `GITEA_TOKEN` pentru clone HTTPS la `gitea.romfast.ro`; `DASHBOARD_TOKEN` pentru cookie auth |
**Status flow:** `pending` → (`planning` →) `approved``running``complete` / `failed` / `stopped` / `blocked` (DAG)
@@ -229,28 +196,27 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor
**Workspace proiecte** (`~/workspace/`): roa2web, gomag-vending, vending_data_intelligence_report, btgo-playwright, space-booking, romfast-website, game-library, wol, romfastsql
**Reguli importante:**
- Ralph NU modifică niciodată `src/router.py`, `src/claude_session.py` sau alte fișiere core din echo-core
- Self-improvement echo-core NUMAI pe branch `ralph/echo-improve`, niciodată pe master
- Ralph NU modifică niciodată `src/router.py`, `src/claude_session.py` sau alte fișiere core din echo-core.
- Self-improvement echo-core NUMAI pe branch `ralph/echo-improve`, niciodată pe master.
- Clone-urile folosesc `GITEA_TOKEN` din `dashboard/.env`: `https://moltbot:${TOKEN}@gitea.romfast.ro/romfast/<name>.git`
### Features pe repo-uri existente (worktree-aware)
Slug-ul proiectului nu trebuie să corespundă cu un repo Gitea. Pentru o feature pe un repo existent (ex: `roa2web-telegram-bonuri` ca feature pe `roa2web`), folosește câmpurile opționale `repo`, `branch`, `base_branch`:
Slug-ul proiectului nu trebuie să corespundă cu un repo Gitea. Pentru o feature pe un repo existent (ex: `roa2web-telegram-bonuri` ca feature pe `roa2web`), folosește câmpurile opționale:
- **`repo`** — numele repo-ului Gitea de clonat (default: slug-ul proiectului).
- **`branch`** — feature branch nou care va fi creat după clone (default: niciunul, ralph lucrează pe HEAD-ul default).
- **`base_branch`** — branch-ul de la care porneste `branch` (default: `main`).
- **`branch`** — feature branch nou creat după clone (default: niciunul, ralph lucrează pe HEAD-ul default).
- **`base_branch`** — branch-ul de la care pornește `branch` (default: `main`).
Cum le setezi:
- **CLI/chat:** `/p <slug> --repo <name> --branch <feature> [--base-branch <name>] <descriere>` (parser în `_ralph_propose` la `src/router.py`).
- **Dashboard:** modal Propose → secțiunea „Avansat" cu câmpuri pentru repo/branch/base_branch.
Night-execute (`cron/jobs.json`) detectează câmpurile și clonează `repo` în `~/workspace/<slug>/`, apoi `git checkout -b <branch> <base_branch>` dacă `branch` e setat. Dacă clone-ul eșuează (repo inexistent), proiectul e marcat `failed` fără să mai pornească ralph.
Night-execute (`cron/jobs.json`) detectează câmpurile, clonează `repo` în `~/workspace/<slug>/`, apoi `git checkout -b <branch> <base_branch>` dacă `branch` e setat. Dacă clone-ul eșuează (repo inexistent), proiectul e marcat `failed` fără să pornească ralph.
### Approval guard — protejare împotriva re-planning accidental
`/plan/start` (POST `/api/projects/<slug>/plan/start`) refuză cu 409 `already_committed` dacă proiectul e deja `approved`/`running`/`complete`. Pentru a re-iniția planning-ul intenționat:
`/plan/start` (POST `/api/projects/<slug>/plan/start`) refuză cu 409 `already_committed` dacă proiectul e deja `approved`/`running`/`complete`. Pentru re-inițiere intenționată:
- **Dashboard:** butonul „Re-planifică" pe cards aprobate cere confirm explicit înainte să trimită `force=true` în body.
- **API direct:** trimite `{"force": true, "description": "..."}` în body-ul de la `/plan/start`.
@@ -262,6 +228,8 @@ Import-uri absolute via `sys.path.insert(0, PROJECT_ROOT)`: `from src.config imp
## Fișiere cheie
Fișierele Ralph (planning_session, planning_orchestrator, ralph.sh, ralph_dag, ralph_prd_generator, planning_agent.md, prd.json etc.) sunt documentate în tabelul din § Ralph. Restul:
| Path | Rol |
|------|-----|
| `src/main.py` | Entry point — adaptoare + scheduler + heartbeat |
@@ -275,63 +243,22 @@ Import-uri absolute via `sys.path.insert(0, PROJECT_ROOT)`: `from src.config imp
| `memory/` | Knowledge base — embeddings + SQLite (în repo, nu symlink) |
| `dashboard/api.py` | Task Board HTTP API (port 8088) |
| `dashboard/handlers/` | Mixin-uri endpoints (git, cron, habits, eco, files, pdf, workspace, youtube, projects, ralph, auth) |
| `dashboard/handlers/projects.py` | Endpoints unificate proiecte: `/api/projects`, `/propose`, `/approve`, `/unapprove`, `/cancel`, `/<slug>/plan/*`, `/stream` (SSE) |
| `dashboard/handlers/projects.py` | Endpoints unificate proiecte (vezi § Ralph pentru lista completă) |
| `dashboard/handlers/auth.py` | Login/logout cu cookie httpOnly `dashboard=<token>`; `DASHBOARD_TOKEN` din `.env` |
| `dashboard/handlers/_validators.py` | Validatori slug/descriere partajați. Slug regex: `^[a-z0-9][a-z0-9\-_]{1,38}[a-z0-9]$` (permite hifene ȘI underscore) |
| `dashboard/static/tokens.css` | Design tokens CSS (`--color-*`, `--space-*`, etc.) — shared variables pentru toate paginile |
| `dashboard/handlers/_validators.py` | Validatori slug/descriere partajați (slug regex — vezi § Dashboard) |
| `dashboard/static/tokens.css` | Design tokens CSS (`--color-*`, `--space-*`, etc.) — shared pentru toate paginile |
| `dashboard/DESIGN.md` | Design system source-of-truth: tokens, componente, regula no-emoji |
| `dashboard/constants.py` | Path-uri centralizate + config Gitea pentru dashboard |
| `dashboard/echo-taskboard.service` | Template systemd user unit |
| `src/jsonlock.py` | Flock helper pentru scrieri concurente: `read_locked(path)`, `write_locked(path, mutator)`, `LockTimeoutError`. Sidecar `<path>.lock` (inode stabil). Re-entrant per thread. Ordine canonică: alfabetic |
| `src/jsonlock.py` | Flock helper scrieri concurente (detalii în § Dashboard) |
| `src/approved_tasks_cli.py` | CLI wrapper pentru shell scripts: scrie în `approved-tasks.json` prin jsonlock. Usage: `python3 -m src.approved_tasks_cli set-status --slug X --status Y` |
| `cron/jobs.json` | Job-uri APScheduler (schemă plată, Europe/Bucharest) |
| `approved-tasks.json` | Fișier coordonare Ralph — status proiecte autonome (extins cu `planning_session_id`, `final_plan_path`) |
| `approved-tasks.json` | Fișier coordonare Ralph — status proiecte autonome (schema în § Ralph) |
| `tasks/lessons.md` | Lecții capturate din corectările lui Marius (citit la session start) |
| `tasks/spike-planning-findings.md` | Validare empirică Spike Step 0 (subprocess `claude -p` + skills gstack + `--resume` round-trip) |
| `prompts/planning_agent.md` | System prompt pentru planning agent multi-fază (W2) |
| `src/ralph_flow.py` | State per `(adapter, chat, user)` pentru UX flow (TTL 10min) |
| `src/planning_session.py` | Wrapper Claude subprocess pentru planning agent |
| `src/planning_orchestrator.py` | Orchestrare faze gstack skills (W2) |
| `src/adapters/discord_views.py` | Discord Views/Modal pentru UX interactiv (W1) |
| `tools/ralph/ralph.sh` | Bash loop DAG-aware (W3): N iter × claude CLI per story |
| `tools/ralph_dag.py` | DAG helpers + CLI (W3) |
| `tools/ralph_prd_generator.py` | Generează PRD + prd.json cu Opus |
## gstack
Folosește skill-ul `/browse` din gstack pentru orice navigare web. Nu folosi tool-uri `mcp__claude-in-chrome__*`.
Skill-uri disponibile:
- `/office-hours`
- `/plan-ceo-review`
- `/plan-eng-review`
- `/plan-design-review`
- `/design-consultation`
- `/design-shotgun`
- `/design-html`
- `/review`
- `/ship`
- `/land-and-deploy`
- `/canary`
- `/benchmark`
- `/browse`
- `/connect-chrome`
- `/qa`
- `/qa-only`
- `/design-review`
- `/setup-browser-cookies`
- `/setup-deploy`
- `/retro`
- `/investigate`
- `/document-release`
- `/codex`
- `/cso`
- `/autoplan`
- `/plan-devex-review`
- `/devex-review`
- `/careful`
- `/freeze`
- `/guard`
- `/unfreeze`
- `/gstack-upgrade`
- `/learn`
Skills gstack + regula `/browse` (nu `mcp__claude-in-chrome__*`) sunt definite în CLAUDE.md-ul global al userului — vezi acolo lista completă de skill-uri.