Files
ROMFASTSQL/proxmox/lxc171-claude-agent
Claude Agent ca6b53e0ca feat(maria): rank hibrid, escaladare la suport si dictionar de erori Oracle
Trei probleme legate, gasite testand cu capturi reale.

1. RASPUNSURI GENERICE. Cand raspunsul nu era in documente, modelul primea
   oricum top-3 chunk-uri si compunea ceva plauzibil — utilizatorul pleca cu
   impresia ca a primit ajutor. Acum, daca nu avem acoperire, modelul nu mai e
   intrebat deloc: intrebarea pleaca la suport, cu referinta (M-260831-A1B2) si
   confirmare onesta — "am trimis" doar daca notificarea chiar a plecat, altfel
   "am inregistrat, dar nu am putut trimite". Jurnalul se scrie intotdeauna, in
   ~/.maria-bridge/escalations/, si se vede in dashboard. Daca a fost o captura,
   imaginea insasi se retrimite la suport (endpoint nou /send-image, limitat la
   MEDIA_DIR).

2. ORDONARE (rank.py). Un prag pe cosinus nu putea decide "avem raspunsul?":
   masurat pe indexul viu, intrebarile bune dau 0,600-0,816 si cele straine
   0,534-0,685 — intervale care SE SUPRAPUN. Lipseau codurile: ORA-01722, D406,
   CIF sunt tokeni exacti pe care cautarea semantica ii topeste. Acum se ordoneaza
   de doua ori — embeddings si BM25 — si se fuzioneaza clasamentele (RRF), iar
   decizia de acoperire se ia pe dovezi: cosinus mare, sau cosinus de mijloc cu o
   fractiune din termenii distinctivi gasita chiar in chunk-uri. Fractiunea conteaza:
   cu un singur termen, "cum imi resetez parola de la Windows" trecea drept
   acoperita fiindca "parola" apare in documente.
   Pragurile sunt masurate, nu alese: ops/calibrate-rank.py ruleaza un set de cazuri
   pe indexul real si matura grila. 15/15 la strong=0.70 weak=0.58 ratio=0.5.

3. DICTIONAR DE ERORI ORACLE. 29 de erori uzuale, scrise pentru utilizatorul din
   fata aplicatiei: ce inseamna, ce poate incerca singur, cand sa sune. Fara nume
   de servere, IP-uri sau pasi de administrare — Maria e chatbot pentru clienti.
   Fisierul din git e SAMANTA: depozitul e oglinda Drive-ului, deci trebuie pus in
   document_store ca sa nu dispara la sincronizare.

Pe drum, doua lucruri gasite in log:
- fiecare mesaj din self-chat sosea de DOUA ori, pe @s.whatsapp.net si pe @lid,
  deci Maria raspundea de doua ori. Dedup pe key.id in punte.
- reindexarea reface toate embeddings-urile (~7 s fiecare pe CPU): adaugarea unui
  document la 170 de chunk-uri insemna 20 de minute. Acum refoloseste vectorii
  chunk-urilor nemodificate din indexul precedent, fara vreun fisier nou de stare.

Textul OCR se logheaza acum INTEGRAL, cu interogarea de cautare si sursele alese
cu scorurile lor — fara asta un raspuns gresit nu se poate explica: nu stiai daca
a citit prost captura sau a cautat prost in documente.

6 fisiere de test noi/extinse, 68 pass (de la 42).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
2026-08-31 22:08:50 +00:00
..

LXC 171 - Claude Agent (Development Environment)

Care chatbot e care? Exista trei lucruri numite „Maria", doi boti pe Discord si doua punti WhatsApp legate la acelasi numar. Inainte de a depana, citeste docs/chatboti-si-punti.md — spune care instanta raspunde de fapt.

Director: proxmox/lxc171-claude-agent/ VMID: 171 IP: 10.0.20.171 (intern) | 100.95.55.51 (Tailscale) Host Proxmox: pvemini (10.0.20.201) Rol: Mediu de dezvoltare izolat pentru Claude Code


Scripturi Disponibile

Script Descriere
scripts/start-agent.sh Pornește/atașează sesiune tmux "agent"
scripts/work.sh Meniu interactiv pentru workflow complet
scripts/new-task.sh Creează branch nou pentru task
scripts/finish-task.sh Finalizează task (commit + push)
scripts/reap-orphans.sh Curăță procese vscode-server orfane + sesiuni zombie (cron, anti-OOM)
discord-bridge/ Punte Discord → Claude Code: comanzi containerul dintr-un guild privat (README)
discord-bridge/dashboard/ Dashboard de control al punții: stare, restart, orfani, confirmări (README)

Informații Container

Parametru Valoare
VMID 171
Hostname claude-agent
IP intern 10.0.20.171
IP Tailscale 100.95.55.51
Host Proxmox pvemini (10.0.20.201)
User claude
Storage local-zfs (32GB)
RAM 16GB (swap 8GB — vezi nota OOM mai jos)
CPU 4 cores

Componente Instalate

  • Ubuntu 24.04 LTS
  • Node.js v20.x (via nvm)
  • Claude Code
  • tmux
  • Git (configurat pentru Gitea)
  • Tailscale

Conectare

De pe calculator (rețea internă)

ssh claude@10.0.20.171

De pe telefon/exterior (Tailscale)

ssh claude@100.95.55.51

VS Code Remote SSH

Config în ~/.ssh/config:

Host claude-agent
    HostName 10.0.20.171
    User claude

Scripturi Workflow

start-agent.sh

Pornește sau se atașează la sesiunea tmux "agent".

~/start-agent.sh

work.sh (recomandat)

Meniu interactiv pentru workflow complet:

  • Listează proiectele disponibile în /workspace
  • Permite crearea de branch-uri noi
  • Continuarea pe branch-uri existente
  • Finalizare task (commit + push)
  • Vizualizare branch-uri
~/work.sh

new-task.sh

Creează branch nou pentru un task (hardcodat pentru romfastsql).

~/new-task.sh fix/nume-bug

finish-task.sh

Finalizează task-ul curent (commit + push).

~/finish-task.sh

Workflow Complet

De pe telefon (JuiceSSH + Tailscale)

  1. Conectează-te la 100.95.55.51 cu user claude
  2. Rulează:
~/start-agent.sh    # pornește tmux
~/work.sh           # meniu interactiv
  1. Alege proiectul
  2. Alege acțiunea (task nou / continuă / finalizează)
  3. Lucrează cu Claude Code
  4. Când termini: ~/work.sh → opțiunea 3 (finalizează)

De pe calculator (VS Code)

  1. VS Code → Remote SSH → claude-agent
  2. Open Folder → /workspace/<proiect>
  3. Terminal → source ~/.nvm/nvm.sh && claude

Structura Directoare pe LXC

/home/claude/
├── .ssh/
│   ├── authorized_keys      # Chei SSH pentru acces
│   ├── gitea_ed25519        # Cheie pentru Gitea
│   └── config               # Config SSH pentru Gitea
├── .nvm/                    # Node Version Manager
├── .claude/
│   └── settings.json        # Permisiuni Claude Code
├── .tmux.conf               # Configurare tmux
├── start-agent.sh -> /workspace/start-agent.sh
└── work.sh -> /workspace/work.sh

/workspace/
├── start-agent.sh           # Script pornire tmux
├── work.sh                  # Script workflow interactiv
├── new-task.sh              # Script creare branch
├── finish-task.sh           # Script finalizare task
├── CLAUDE.md                # Info agent
├── SETUP-COMPLETE.md        # Documentație setup
├── romfastsql/              # Proiect clonat
└── test/                    # Alte proiecte

Comenzi tmux Utile

Comandă Acțiune
Ctrl+A, d Detașare din sesiune
Ctrl+A, c Fereastră nouă
Ctrl+A, n Fereastră următoare
Ctrl+A, p Fereastră anterioară
Ctrl+A, [ Mod scroll (q pentru ieșire)
tmux attach -t agent Reatașare la sesiune
tmux ls Listare sesiuni

Git / Gitea

Clonare proiect nou

cd /workspace
git clone git@gitea.romfast.ro:romfast/<nume-repo>.git

Workflow branch-uri

git checkout main
git pull
git checkout -b feature/nume-feature
# ... lucrezi ...
git add .
git commit -m "descriere"
git push -u origin feature/nume-feature
# Creează Pull Request în Gitea

Memorie & OOM (reaping orfane + zram)

Context (incident 2026-06-24)

Containerul a generat OOM-uri repetate, izolate în cgroup-ul /lxc/171 (NU la nivel de host — host-ul avea memorie liberă). Cauzele combinate:

  1. Swap fictiv: LXC 171 are memory: 16384 + swap: 8192, dar host-ul pvemini nu avea swap deloc → swap-ul containerului nu era backed de nimic. La atingerea celor 16GB se intra direct în OOM-kill, fără să poată face swap-out. Victimele tipice erau procese mici cu oom_score_adj ridicat (systemd, dbus-daemon, at-spi-bus-laun, sd-pam) din sesiunile user@1000.
  2. Acumulare de fond: forks ~/.vscode-server (servere VS Code Remote-SSH) rămase orfane după ce conexiunea SSH moare — reparentate la init (PPID=1), vechi de zile — plus sesiuni systemd-logind blocate în stare closing. Un spike ocazional de Chromium/Playwright împingea totalul peste 16GB → OOM.

Fix 1 — zram swap pe host (pvemini)

Root-ul pvemini e pe ZFS, deci NU se folosește swapfile (risc de deadlock). În loc, zram (swap comprimat în RAM):

# pe pvemini (host)
apt install -y zram-tools
cat > /etc/default/zramswap <<'EOF'
ALGO=zstd
SIZE=8192
PRIORITY=100
EOF
systemctl restart zramswap.service   # enabled persistent la boot
zramctl; swapon --show               # verificare: /dev/zram0 8G zstd

Acum cei 8GB swap din configul LXC 171 au backing real → vârfurile tranzitorii fac swap-out în loc de OOM-kill instant.

Același fix aplicat pe pve1 în 2026-07-31 (aceeași cauză: LXC 110 moltbot cu swap: 4096 fictiv → OOM-kill în cgroup + reboot). Config identic, SIZE=8192. Vezi ../cluster/incidents/2026-07-31-lxc110-dns-tailscale-oom.md.

Stare swap pe cluster (2026-07-31):

Nod Swap Tip
pvemini 8G zram0 (zstd, prio 100)
pve1 8G zram0 (zstd, prio 100)
pveelite 8G zvol /dev/zd64 (prio -2) — swap real, nu necesită zram

Fix 2 — reaping orfane (scripts/reap-orphans.sh, cron în 171)

Script conservator care rulează ca root în interiorul containerului, la fiecare 6 ore:

  • omoară forks ~/.vscode-server reparentate la init (PPID=1) și mai vechi de 24h (conexiune SSH moartă);
  • termină sesiunile logind în stare closing cu leader mort (leader=0).

Exclude explicit daemonul de bază /usr/lib/code-server (lansat de ttyd) și procesele Claude Code (pot fi task-uri lungi legitime). Log în /var/log/reap-orphans.log.

# instalare în container (din host)
pct push 171 reap-orphans.sh /usr/local/sbin/reap-orphans.sh   # sau deploy manual
pct exec 171 -- chmod +x /usr/local/sbin/reap-orphans.sh
# cron: /etc/cron.d/reap-orphans  ->  0 */6 * * * root /usr/local/sbin/reap-orphans.sh

# rulare manuală + verificare
pct exec 171 -- /usr/local/sbin/reap-orphans.sh
pct exec 171 -- tail /var/log/reap-orphans.log

⚠️ NU folosi loginctl terminate-session pe sesiuni closing care au leader != 0 — acelea pot fi sesiuni VS Code remote active de lucru. Doar zombiile cu leader=0 sunt sigure (asta verifică și scriptul automat).

Diagnostic rapid OOM

# pe host: confirmă că OOM e în cgroup-ul containerului, nu pe host
ssh root@10.0.20.201 "journalctl -k --since '1 hour ago' | grep -iE 'oom_memcg|Killed process'"
cat /sys/fs/cgroup/lxc/171/memory.events      # oom / oom_kill counters
cat /sys/fs/cgroup/lxc/171/memory.current     # consum curent vs memory.max (16G)

# în container: top consumatori + orfani + sesiuni
pct exec 171 -- bash -c "ps -eo pid,ppid,etimes,rss,comm --sort=-rss | head -20"
pct exec 171 -- loginctl list-sessions

Troubleshooting

Claude Code nu pornește

source ~/.nvm/nvm.sh
which claude
claude --version

tmux nu găsește sesiunea

tmux ls
tmux new -s agent -c /workspace

Git clone eșuează

# Testează conexiunea SSH la Gitea
ssh -T git@gitea.romfast.ro

Tailscale nu funcționează

sudo systemctl status tailscaled
sudo tailscale status
tailscale ip

Instalare Claude Code pe LXC nou (de la zero)

1. Creare LXC în Proxmox

# Pe Proxmox host (ex: pveelite)
pct create <VMID> local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
  --hostname claude-agent \
  --memory 4096 \
  --cores 2 \
  --rootfs local-zfs:32 \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
  --features nesting=1 \
  --unprivileged 1

pct start <VMID>
pct enter <VMID>

2. Setup sistem (ca root în LXC)

# Update și pachete de bază
apt update && apt upgrade -y
apt install -y curl git tmux sudo

# Creare user claude
useradd -m -s /bin/bash claude
echo "claude ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/claude
passwd claude  # setează parola

# Creare /workspace
mkdir -p /workspace
chown claude:claude /workspace

3. Setup user claude

su - claude

# Instalare nvm + Node.js
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20
nvm alias default 20

# Instalare Claude Code
npm install -g @anthropic-ai/claude-code

# Verificare
claude --version

4. Configurare Claude Code

mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "permissions": {
    "allow": [
      "Bash(git *)",
      "Bash(npm *)",
      "Bash(node *)",
      "Read",
      "Write",
      "Edit"
    ],
    "deny": []
  }
}
EOF

5. Configurare tmux

cat > ~/.tmux.conf << 'EOF'
set -g prefix C-a
unbind C-b
bind C-a send-prefix
set -g mouse on
set -g history-limit 50000
set -g default-terminal "screen-256color"
EOF

6. Configurare Git + SSH pentru Gitea

# Generare cheie SSH
ssh-keygen -t ed25519 -f ~/.ssh/gitea_ed25519 -N ""

# Config SSH
cat > ~/.ssh/config << 'EOF'
Host gitea.romfast.ro
    HostName gitea.romfast.ro
    User git
    IdentityFile ~/.ssh/gitea_ed25519
    IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config

# Afișează cheia publică (adaug-o în Gitea → Settings → SSH Keys)
cat ~/.ssh/gitea_ed25519.pub

# Config Git
git config --global user.name "Claude Agent"
git config --global user.email "claude@romfast.ro"
git config --global init.defaultBranch main

7. Instalare scripturi workflow

cd /workspace

# Copiază scripturile din acest repo (de pe mașina locală)
# SAU creează-le manual conform secțiunii "Scripturi Disponibile"

# Creare symlink-uri
ln -s /workspace/start-agent.sh ~/start-agent.sh
ln -s /workspace/work.sh ~/work.sh

chmod +x /workspace/*.sh

8. (Opțional) Instalare Tailscale

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Autentifică-te cu contul Tailscale
tailscale ip  # notează IP-ul

9. Clonare proiecte

cd /workspace
git clone git@gitea.romfast.ro:romfast/romfastsql.git
# alte proiecte...

10. Test final

~/start-agent.sh
# În tmux:
source ~/.nvm/nvm.sh
claude --version
~/work.sh

Copiere rapidă scripturi (dacă ai alt LXC configurat)

# De pe mașina locală
scp proxmox/lxc171-claude-agent/scripts/*.sh claude@<ip>:/workspace/
ssh claude@<ip> "chmod +x /workspace/*.sh && ln -sf /workspace/start-agent.sh ~/start-agent.sh && ln -sf /workspace/work.sh ~/work.sh"

Legături Utile


Data setup: 2025-12-31 Ultima actualizare: 2026-06-24 (zram swap pvemini + reap-orphans cron, anti-OOM)