feat(projects): approval guard + worktree-aware ralph execution
Two structural fixes that together let users manage feature-branch
work without manual intervention:
Approval guard — `/plan/start` returns 409 `already_committed` if the
project status is approved/running/complete, unless the body opts in
with `force=true`. Frontend now renders "Re-planifică" instead of
"Planifică" on approved cards and gates it behind a confirm dialog
that threads `force=true` through. Prevents an accidental click from
wiping `status=approved` and burning a fresh planning subprocess.
Worktree awareness — projects can now declare that they target a
feature branch on an existing Gitea repo, not a repo-per-slug clone.
Three optional fields added to approved-tasks.json: `repo` (default
= slug), `branch` (feature branch to create), `base_branch` (default
main). Wired through `/p` flag parser in router.py, the dashboard
Propose modal's new "Avansat" section, and the night-execute prompt
which clones {repo} and creates {branch} from {base_branch} before
running ralph.
CLAUDE.md updated with both flows + the new schema fields.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
25
CLAUDE.md
25
CLAUDE.md
@@ -199,7 +199,7 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor
|
||||
|
||||
| Path | Rol |
|
||||
|------|-----|
|
||||
| `approved-tasks.json` | Coordonare între cron jobs + UX. Schema: `{name, description, status, planning_session_id, final_plan_path, proposed_at, approved_at, started_at, pid}` |
|
||||
| `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 |
|
||||
@@ -229,6 +229,29 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor
|
||||
- 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`:
|
||||
|
||||
- **`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`).
|
||||
|
||||
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.
|
||||
|
||||
### 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:
|
||||
|
||||
- **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`.
|
||||
|
||||
Asta previne situația în care un click accidental pe „Planifică" șterge `status=approved` și pornește un nou subprocess Claude (cu cost asociat).
|
||||
|
||||
## Convenție import-uri
|
||||
|
||||
Import-uri absolute via `sys.path.insert(0, PROJECT_ROOT)`: `from src.config import ...`, `from src.adapters.discord_bot import ...`. Fără import-uri circulare.
|
||||
|
||||
Reference in New Issue
Block a user