Commit Graph

15 Commits

Author SHA1 Message Date
1462f98ae9 chore: auto-commit from dashboard 2026-04-28 10:46:30 +00:00
5e930ade02 feat(dashboard): unified workspace hub — cookie auth, 9-state projects, planning chat
Merges workspace.html + ralph.html into a single unified project hub with:
- Cookie-based auth (DASHBOARD_TOKEN, HttpOnly, SameSite=Strict)
- 9-state project badge system (running-ralph/manual, planning, approved,
  pending, blocked, failed, complete, idle) with BUTTONS_FOR_STATE matrix
- SSE realtime + polling fallback, version-based optimistic concurrency (If-Match)
- Planning chat modal (phase stepper, markdown bubbles, 50s+ wait state, auto-resume)
- Propose modal (Variant B: inline Plan-with-Echo checkbox)
- 5-type toast taxonomy (success/info/warning/busy/error, 3px colored left-bar)
- Inter font self-hosted + shared tokens.css design system + DESIGN.md
- src/jsonlock.py (flock helper, sidecar .lock for stable inode)
- src/approved_tasks_cli.py (shell-safe wrapper for cron/ralph.sh)
- 55 new tests (T#1–T#30) + real jsonlock bug fix caught by T#16/T#28
- No emoji anywhere (enforced by test_dashboard_no_emoji.py)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 07:26:19 +00:00
03d875974b Merge branch 'ralph/dashboard-realtime' — SSE realtime + story rollback
Server-Sent Events (TODO P3):
- GET /api/ralph/stream — signature-based change detection (poll FS 2s, emit
  doar la diff), heartbeat 30s, X-Accel-Buffering:no
- HTTPServer → ThreadingHTTPServer (altfel SSE blochează toate endpoint-urile)
- ralph.html: EventSource cu fallback permanent la polling 5s când CLOSED.
  Badge: 🟢 Live / ⏱ Polling / Offline

Story rollback (TODO P3):
- POST /api/ralph/<slug>/rollback — git revert --no-edit HEAD; fallback
  git reset --hard HEAD~1 doar la conflict
- Decrementează passes pe ultima story complete; clears failed/blocked/retries
  (atomic temp+rename)
- Slug strict regex ^[A-Za-z0-9_-]{1,64}$ + reject path traversal explicit
- Buton ↩️ pe card-uri running; confirm dialog înainte de execuție
- Response: {success, message, reverted_commit, story_reverted, method}

Tests: 39/39 pe test_dashboard_ralph_endpoint (era 19; +20 cazuri noi).

# Conflicts:
#	dashboard/api.py
#	dashboard/handlers/ralph.py
2026-04-26 19:14:17 +00:00
84f304f7be Merge branch 'ralph/instrumentation' — rate limit budget + WhatsApp keywords
Rate limit budget tracking (TODO P2):
- tools/ralph_usage.py — pure functions extract/parse/aggregate; CLI subcomenzi
  append/summarize. Atomic write JSONL.
- tools/ralph/ralph.sh: după fiecare claude -p, append usage entry la
  workspace/<slug>/scripts/ralph/usage.jsonl (best-effort)
- dashboard/handlers/ralph.py: GET /api/ralph/usage[?days=N] cross-project
  aggregation cu today_cost, today_runs, by_project, by_day

WhatsApp text-keyword commands (TODO P3):
- src/router.py: helper _translate_whatsapp_text — `aprob <slug>` → `/a <slug>`,
  `stop <slug>` → `/k <slug>`, `stare`/`stare <slug>` → `/l`/`/l <slug>`. Aplicat
  DOAR pe adapter whatsapp în _try_ralph_dispatch (Discord/TG nu sunt afectate).
  Propose intentionally NOT covered (descrierea fragilă).

Tests: 53 noi (28 ralph_usage + 21 whatsapp_keywords + 4 dashboard endpoint extend)
+ 0 regressions pe modulele atinse.
2026-04-26 19:12:43 +00:00
6d56356ada feat(dashboard): integrate Ralph nav link + add e2e planning walkthrough test
dashboard/api.py: adaug link "Ralph" (lucide bot icon) în NAV_HTML între
Workspace și KB. Pagina ralph.html se injectează corect cu nav-ul (verificat
live via curl pe :8088/ralph.html).

tests/test_e2e_planning_walkthrough.py (nou): 4 teste integration care
simulează scripted exact ce face un user pe Discord:
- click Planifică pe game-library cu UI scope → 4 faze (incl design-review)
- /office-hours → ceo → eng → design → final-plan.md stub scris pe disk
- "Dau drumul" → status approved + final_plan_path în approved-tasks.json
- description fără UI keywords → 3 faze (skip design)
- /cancel mid-planning → status revert pending, state cleared
- mesaj fără planning state → cade pe Claude main chat (NU orchestrator)

Subprocess `claude -p` mock-uit; testează tot wire-up-ul router → orchestrator
→ session și schema approved-tasks.json. Nu consumă credite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:11:35 +00:00
ff9b9a0d1d feat(dashboard): SSE realtime + story rollback button
Replaces 5s polling on /echo/ralph.html with EventSource streaming and adds
a rollback control for the running Ralph cards.

Server (dashboard/handlers/ralph.py):
- /api/ralph/stream — Server-Sent Events. Emits `event: status` whenever a
  signature over the projects' state changes (poll filesystem at 2s); emits
  `event: heartbeat` every 30s to keep proxies happy. Disables proxy
  buffering via X-Accel-Buffering:no.
- /api/ralph/<slug>/rollback (POST) — runs `git revert --no-edit HEAD` in
  the project; falls back to `git reset --hard HEAD~1` only if revert
  reports conflict. After rolling back the commit, decrements `passes` on
  the last user story marked complete in prd.json (atomic temp+rename
  write, same pattern as ralph_dag.py). Returns
  `{success, message, reverted_commit, story_reverted, method}`.
- _ralph_validate_slug tightened to a strict regex (alphanum + dash +
  underscore, ≤64 chars) plus explicit ../, /, \ rejection. All previously
  accepted slugs still pass; URL-encoded traversal and shell metachars
  now blocked before the filesystem is touched.
- _ralph_collect_status / _ralph_signature factored out of
  handle_ralph_status so the SSE loop can reuse them and detect changes
  cheaply.

Server (dashboard/api.py):
- HTTPServer → ThreadingHTTPServer with daemon_threads=True. SSE is a
  long-lived response; without threading a single client would block all
  other dashboard endpoints.
- /api/ralph/stream (GET) and /api/ralph/<slug>/rollback (POST) wired
  into the dispatch.

Client (dashboard/ralph.html):
- EventSource('/api/ralph/stream') with permanent fallback to 5s polling
  when readyState=CLOSED (no server, CORS blocked, browser without SSE).
- Indicator badge: 🟢 Live (SSE), ⏱ Polling (fallback), Offline.
- Rollback button (undo-2 icon) on running cards; native confirm() with
  message: "Asta va da git revert HEAD pe <slug> și va decrementa ultima
  story trecută. Continui?"

Tests (tests/test_dashboard_ralph_endpoint.py, +20 cases):
- Strict slug validator: underscore allowed, >64 rejected, special chars
  / backslash / URL-encoded traversal rejected.
- _ralph_collect_status + _ralph_signature: stable when nothing changes,
  flips when project added or `passes` toggles.
- Rollback: invalid slug → 400, non-git project → 400, real two-commit
  repo revert succeeds and decrements last passing story (US-002 goes
  passes:false while US-001 stays passes:true), no-passing-stories case
  succeeds with story_reverted=None, response shape contract, atomic
  helper leaves no .tmp file behind.
- API routing smoke: confirms ThreadingHTTPServer + stream + rollback
  references present in dashboard/api.py.

39/39 tests pass on tests/test_dashboard_ralph_endpoint.py. Pre-existing
failures in test_dashboard_constants.py::test_base_dir_is_echo_core (the
worktree dir is `echo-core-realtime`, not `echo-core`) and
test_dashboard_unified_index.py::test_index_has_all_panels are unrelated
to this change and reproduced on master.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:07:13 +00:00
3e7818286b feat(ralph): rate limit budget tracking + whatsapp text-keywords
Task #1 — Rate limit budget tracking MVP:
- tools/ralph_usage.py: pure functions (extract_usage_entry, parse_usage_jsonl,
  aggregate_by_day/_project, filter_by_days, summarize) + CLI append/summarize
  subcommands. Atomic write via temp+rename.
- tools/ralph/ralph.sh: după fiecare claude -p, append usage entry
  derivat din JSON envelope la <project>/scripts/ralph/usage.jsonl. Best-effort,
  niciodată blochează rularea (|| true).
- dashboard/handlers/ralph.py: GET /api/ralph/usage[?days=N] aggregează cross-
  project și returnează {today_cost, today_runs, by_project, by_day, ...}.

Task #2 — WhatsApp text-keyword commands:
- src/router.py: helper _translate_whatsapp_text mapează "aprob"/"stop <slug>"/
  "stare [<slug>]" → /a, /k, /l. Apelat DOAR pe adapter whatsapp în
  _try_ralph_dispatch (Discord/TG nu sunt afectate). NU acoperim propose
  intentionat — descrierea liberă e prea fragilă pentru parsing text-only.

Tests: 49 noi (test_ralph_usage 28 + test_whatsapp_keywords 21) + 4 noi în
test_dashboard_ralph_endpoint pentru /api/ralph/usage. Toate trec; regression
suite (test_router, test_router_planning, test_dashboard_ralph_endpoint,
test_whatsapp) — 90/90 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:05:50 +00:00
655ed3ae09 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>
2026-04-26 18:36:35 +00:00
c146d68498 fix(dashboard): remove broken grup-sprijin nav link
Pagina cerea un index.json inexistent și nu mai este necesară.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-25 21:51:03 +00:00
2dd5aee9a7 chore: auto-commit from dashboard 2026-04-21 13:56:53 +00:00
0ac0f3b907 feat(dashboard): consolidate /api/git-commit into /api/eco/git-commit 2026-04-21 07:17:11 +00:00
e0abe5cdfc feat(dashboard): drop /api/agents and /api/activity endpoints 2026-04-21 07:16:20 +00:00
b00d9d6fbd refactor(dashboard): split api.py into handler modules 2026-04-21 07:11:41 +00:00
ca9167d129 refactor(dashboard): normalize paths with constants block for echo-core 2026-04-21 07:02:56 +00:00
cd07e43533 feat(dashboard): copy from clawd 2026-04-21 07:01:30 +00:00