Review-Haertung R1/R2/R4 + Repo-Waechter (Vorfall verlorener Merge 12.07.)
R1: Steckbrief-Hook erinnert Worker an kanban_complete/kanban_block-Pflicht
(Nacht-Karte 14.07. blockierte trotz fertiger Arbeit am fehlenden Aufruf).
R2: tabu-pfade-guard sperrt ~/.config/systemd/user fuer Worker — Unit-/
Override-Dateien nur noch ueber angenommene Karte.
R4: Orchestrator-/Wartungs-Worktrees von /tmp nach ~/.hermes/worktrees
(ueberleben Reboot, keine kaputten Registrierungen).
Neu: self-smoke Check 4 'Repo-Waechter' — Box-main mit Commits, die origin
fehlen, loest Alarm aus (so ging die angenommene Karte
wartung/lucy-annahme-fixes am 12.07. still verloren; am 15.07. als
rescue/-Branch gerettet und wieder gemergt).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@ hint=""
|
|||||||
ctx="$(cat <<EOF
|
ctx="$(cat <<EOF
|
||||||
[BOX-ORIENTIERUNG — du bist ein Hintergrund-Worker auf der lokalen AI-Box (Linux, Zeit UTC / lokal Europe/Berlin, locale de_DE), NICHT Lucy und kein Dev-Laptop. Du arbeitest EINE Kanban-Aufgabe ab.]
|
[BOX-ORIENTIERUNG — du bist ein Hintergrund-Worker auf der lokalen AI-Box (Linux, Zeit UTC / lokal Europe/Berlin, locale de_DE), NICHT Lucy und kein Dev-Laptop. Du arbeitest EINE Kanban-Aufgabe ab.]
|
||||||
Die Modelle / das "Hirn" laufen ausschliesslich ueber den Router llama-swap auf 127.0.0.1:8080 (startet je Modell einen llama-server) bzw. das OpenAI-kompatible Gateway von MC2 auf 127.0.0.1:9001/v1 — es gibt KEINEN anderen Modell-Server, also nicht danach suchen. Weitere Dienste: hermes-gateway :8642, mem0-Gedaechtnis :8765. Der MC2-Live-Checkout ~/mission-control-v2 ist nur zum LESEN da (Schreiben/committen TABU — Code-Arbeit immer im frischen Klon deines Task-Workspaces). Grenzen (was gehoert wohin): MC2 = Steuerpult (verwalten/klicken/zusehen, KEIN Chat-UI), Lucy = Chat & Stimme (eigenes Repo), Hermes-Quelle ist TABU (Agenten-Verhalten nur ueber Config/SOUL/Skill/Hook/MCP aendern). Feste Entscheide/Verbote + volle Grenzen-Landkarte: ~/mission-control-v2/docs/wissen/ (GRENZEN/VERDIKTE/FALLEN/STACK) + ~/wissens-vault/eigenbau-landkarte.md.${hint}
|
Die Modelle / das "Hirn" laufen ausschliesslich ueber den Router llama-swap auf 127.0.0.1:8080 (startet je Modell einen llama-server) bzw. das OpenAI-kompatible Gateway von MC2 auf 127.0.0.1:9001/v1 — es gibt KEINEN anderen Modell-Server, also nicht danach suchen. Weitere Dienste: hermes-gateway :8642, mem0-Gedaechtnis :8765. Der MC2-Live-Checkout ~/mission-control-v2 ist nur zum LESEN da (Schreiben/committen TABU — Code-Arbeit immer im frischen Klon deines Task-Workspaces). Grenzen (was gehoert wohin): MC2 = Steuerpult (verwalten/klicken/zusehen, KEIN Chat-UI), Lucy = Chat & Stimme (eigenes Repo), Hermes-Quelle ist TABU (Agenten-Verhalten nur ueber Config/SOUL/Skill/Hook/MCP aendern). Feste Entscheide/Verbote + volle Grenzen-Landkarte: ~/mission-control-v2/docs/wissen/ (GRENZEN/VERDIKTE/FALLEN/STACK) + ~/wissens-vault/eigenbau-landkarte.md.${hint}
|
||||||
|
PROTOKOLL-PFLICHT (15.07.): Beende deine Aufgabe IMMER mit dem Tool-Aufruf kanban_complete (fertig) oder kanban_block (Frage/Sackgasse). Eine Text-Zusammenfassung OHNE diesen Aufruf zaehlt als Absturz (Protokollverstoss) und blockiert die Karte — genau so ging am 14.07. eine fertige Arbeit verloren.
|
||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
|
|||||||
@@ -36,13 +36,18 @@ ti = payload.get("tool_input") or {}
|
|||||||
home = os.path.realpath(os.path.expanduser("~"))
|
home = os.path.realpath(os.path.expanduser("~"))
|
||||||
LIVE = os.path.join(home, "mission-control-v2")
|
LIVE = os.path.join(home, "mission-control-v2")
|
||||||
SRC = os.path.join(home, ".hermes", "hermes-agent")
|
SRC = os.path.join(home, ".hermes", "hermes-agent")
|
||||||
|
# R2 (Review 15.07.): systemd-User-Units. Die Nacht-Werkstatt hat am 14.07. einen Override
|
||||||
|
# DIREKT scharf geschaltet — ging gut, verletzt aber "jede Code-Zeile ist Klick-pflichtig".
|
||||||
|
# Unit-/Override-Dateien werden nur noch ueber eine angenommene Karte installiert.
|
||||||
|
SYSD = os.path.join(home, ".config", "systemd", "user")
|
||||||
|
|
||||||
MSG = (
|
MSG = (
|
||||||
"TABU (Faden 8): Schreiben an dieser Stelle ist fuer Worker gesperrt. Der Live-Checkout "
|
"TABU (Faden 8/R2): Schreiben an dieser Stelle ist fuer Worker gesperrt. Der Live-Checkout "
|
||||||
"~/mission-control-v2 und die Hermes-Quelle ~/.hermes/hermes-agent duerfen NIE veraendert "
|
"~/mission-control-v2, die Hermes-Quelle ~/.hermes/hermes-agent und die systemd-User-Units "
|
||||||
"werden. Arbeite im FRISCHEN Klon deines Task-Workspaces; MC2-Aenderungen kommen als "
|
"~/.config/systemd/user duerfen NIE direkt veraendert werden. Arbeite im FRISCHEN Klon "
|
||||||
"Vorschlags-Branch (nie am Live-Checkout), Hermes-Verhalten nur ueber Config/SOUL/Skill/"
|
"deines Task-Workspaces; MC2-Aenderungen kommen als Vorschlags-Branch, systemd-Unit-/"
|
||||||
"Hook/MCP. Siehe docs/wissen/GRENZEN.md."
|
"Override-Dateien werden nur ueber eine angenommene Karte installiert, Hermes-Verhalten "
|
||||||
|
"nur ueber Config/SOUL/Skill/Hook/MCP. Siehe docs/wissen/GRENZEN.md."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -52,7 +57,7 @@ def block():
|
|||||||
|
|
||||||
def under_tabu(path):
|
def under_tabu(path):
|
||||||
rp = os.path.realpath(path)
|
rp = os.path.realpath(path)
|
||||||
return rp == LIVE or rp == SRC or rp.startswith(LIVE + os.sep) or rp.startswith(SRC + os.sep)
|
return any(rp == t or rp.startswith(t + os.sep) for t in (LIVE, SRC, SYSD))
|
||||||
|
|
||||||
|
|
||||||
# --- Datei-Tools: Zielpfad kanonisch pruefen (zuverlaessig) -------------------------
|
# --- Datei-Tools: Zielpfad kanonisch pruefen (zuverlaessig) -------------------------
|
||||||
@@ -78,6 +83,7 @@ if tool == "terminal":
|
|||||||
tabu_forms = [
|
tabu_forms = [
|
||||||
LIVE, "~/mission-control-v2", "$HOME/mission-control-v2", "${HOME}/mission-control-v2",
|
LIVE, "~/mission-control-v2", "$HOME/mission-control-v2", "${HOME}/mission-control-v2",
|
||||||
SRC, "~/.hermes/hermes-agent", "$HOME/.hermes/hermes-agent", "${HOME}/.hermes/hermes-agent",
|
SRC, "~/.hermes/hermes-agent", "$HOME/.hermes/hermes-agent", "${HOME}/.hermes/hermes-agent",
|
||||||
|
SYSD, "~/.config/systemd/user", "$HOME/.config/systemd/user", "${HOME}/.config/systemd/user",
|
||||||
]
|
]
|
||||||
tabu_alt = "(?:" + "|".join(re.escape(t) for t in tabu_forms) + ")"
|
tabu_alt = "(?:" + "|".join(re.escape(t) for t in tabu_forms) + ")"
|
||||||
if not re.search(tabu_alt, cmd):
|
if not re.search(tabu_alt, cmd):
|
||||||
|
|||||||
@@ -83,6 +83,25 @@ else
|
|||||||
FAILED+=("Voice (Lucys Sprech-Pfad)")
|
FAILED+=("Voice (Lucys Sprech-Pfad)")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── 4) Repo-Wächter: verlorene Merges (Vorfall 12.–15.07.2026) ──────────────
|
||||||
|
# Der Annahme-Runner merged+pusht nach origin/main; klemmt der Push (Gitea-Auth
|
||||||
|
# flattert) oder überschreibt eine fremde Session origin/main, trägt Box-main
|
||||||
|
# Commits, die origin fehlen — der nächste deploy-Reset VERNICHTET sie still
|
||||||
|
# (so verlor die Box die angenommene Karte 'wartung/lucy-annahme-fixes' vom
|
||||||
|
# 12.07., bemerkt erst beim Review am 15.07.). Hier täglich gegenprüfen.
|
||||||
|
LIVE_CO="$HOME/mission-control-v2"
|
||||||
|
if git -C "$LIVE_CO" fetch -q origin 2>/dev/null; then
|
||||||
|
LOST=$(git -C "$LIVE_CO" log --oneline origin/main..main 2>/dev/null | head -3 | tr '\n' ' ')
|
||||||
|
if [ -n "$LOST" ]; then
|
||||||
|
say "FAIL · Box-main trägt ungepushte Commits (Deploy würde sie vernichten): $LOST"
|
||||||
|
FAILED+=("Repo (ungepushte Commits auf Box-main: $LOST— vor dem nächsten Deploy nach origin retten)")
|
||||||
|
else
|
||||||
|
say "PASS · Repo-Wächter (Box-main == origin/main)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
say "SKIP · Repo-Wächter (git fetch fehlgeschlagen)"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Meldung nur bei Rot ──────────────────────────────────────────────────────
|
# ── Meldung nur bei Rot ──────────────────────────────────────────────────────
|
||||||
if [ "${#FAILED[@]}" -eq 0 ]; then
|
if [ "${#FAILED[@]}" -eq 0 ]; then
|
||||||
say "Alle Selbst-Tests grün ($(date '+%F %H:%M'))."
|
say "Alle Selbst-Tests grün ($(date '+%F %H:%M'))."
|
||||||
|
|||||||
@@ -86,10 +86,12 @@ Bevor du selbst Tasks aufteilst, befragst du zwingend **`gpt-oss-120b`** nach ei
|
|||||||
3. Fuer jeden Teil-Task entscheide: (a) Artefakt, (b) Worker (`Qwen3-Coder-Next` + `build`/`refactor`), (c) Kontext.
|
3. Fuer jeden Teil-Task entscheide: (a) Artefakt, (b) Worker (`Qwen3-Coder-Next` + `build`/`refactor`), (c) Kontext.
|
||||||
|
|
||||||
### 2. Worktree anlegen (Slug = kurzer Kebab-Case-Name des Auftrags)
|
### 2. Worktree anlegen (Slug = kurzer Kebab-Case-Name des Auftrags)
|
||||||
|
Worktrees liegen unter `~/.hermes/worktrees/` (NICHT /tmp — ueberlebt keinen Reboot und
|
||||||
|
hinterlaesst kaputte Worktree-Registrierungen, Review-Befund 15.07.):
|
||||||
```
|
```
|
||||||
cd ~/mission-control-v2 && git fetch -q origin \
|
mkdir -p ~/.hermes/worktrees && cd ~/mission-control-v2 && git fetch -q origin \
|
||||||
&& git worktree add /tmp/orch-<slug> -b orchestrator/<slug> origin/main
|
&& git worktree add ~/.hermes/worktrees/orch-<slug> -b orchestrator/<slug> origin/main
|
||||||
mkdir -p /tmp/orch-<slug>-work # Ablage fuer rohe Worker-Ausgaben
|
mkdir -p ~/.hermes/worktrees/orch-<slug>-work # Ablage fuer rohe Worker-Ausgaben
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Routen — je Teil-Task ein Worker-Ein-Schuss (seriell)
|
### 3. Routen — je Teil-Task ein Worker-Ein-Schuss (seriell)
|
||||||
@@ -98,19 +100,19 @@ Fuer jeden Bau-Teil-Task:
|
|||||||
fertige Artefakte aus frueheren Schritten als Kontext mitgeben, wenn der Worker sie braucht.
|
fertige Artefakte aus frueheren Schritten als Kontext mitgeben, wenn der Worker sie braucht.
|
||||||
2. Ruf den Worker auf und fang die Ausgabe roh ab:
|
2. Ruf den Worker auf und fang die Ausgabe roh ab:
|
||||||
```
|
```
|
||||||
printf '%s' "$eingabe" | WORKER_ROLE=build ~/.hermes/scripts/worker.sh > /tmp/orch-<slug>-work/<n>.out
|
printf '%s' "$eingabe" | WORKER_ROLE=build ~/.hermes/scripts/worker.sh > ~/.hermes/worktrees/orch-<slug>-work/<n>.out
|
||||||
```
|
```
|
||||||
(Default-Modell ist `Qwen3-Coder-Next`. Fuer einen bewusst anderen Worker `WORKER_MODEL=<echte-id>`.)
|
(Default-Modell ist `Qwen3-Coder-Next`. Fuer einen bewusst anderen Worker `WORKER_MODEL=<echte-id>`.)
|
||||||
3. **Pruefe die Ausgabe, bevor du sie verwendest:** Beginnt sie mit `FEHLT:`, hast du zu wenig
|
3. **Pruefe die Ausgabe, bevor du sie verwendest:** Beginnt sie mit `FEHLT:`, hast du zu wenig
|
||||||
Kontext gegeben → nachliefern und erneut rufen. Hat der Worker versehentlich einen ```-Codezaun
|
Kontext gegeben → nachliefern und erneut rufen. Hat der Worker versehentlich einen ```-Codezaun
|
||||||
oder Prosa drumherum gesetzt, entferne ihn. Dann schreibe das saubere Artefakt mit deinen
|
oder Prosa drumherum gesetzt, entferne ihn. Dann schreibe das saubere Artefakt mit deinen
|
||||||
Datei-Tools an seinen Platz im Worktree (`/tmp/orch-<slug>/...`). Der Worker hat KEINE
|
Datei-Tools an seinen Platz im Worktree (`~/.hermes/worktrees/orch-<slug>/...`). Der Worker hat KEINE
|
||||||
Datei-Haende — das Schreiben machst DU.
|
Datei-Haende — das Schreiben machst DU.
|
||||||
4. **Schreibziel-Pflicht (Vorfall 09.07.2026):** JEDES write_file/patch-Ziel MUSS mit
|
4. **Schreibziel-Pflicht (Vorfall 09.07.2026):** JEDES write_file/patch-Ziel MUSS mit
|
||||||
`/tmp/orch-<slug>/` beginnen — vor dem ersten Schreiben einmal laut pruefen. NIEMALS nach
|
`~/.hermes/worktrees/orch-<slug>/` beginnen — vor dem ersten Schreiben einmal laut pruefen. NIEMALS nach
|
||||||
`~/mission-control-v2/...` schreiben (Live-Checkout!), NIEMALS Work-Dirs/Worktrees FREMDER
|
`~/mission-control-v2/...` schreiben (Live-Checkout!), NIEMALS Work-Dirs/Worktrees FREMDER
|
||||||
Slugs wiederverwenden (beim Doku-Lauf landete ein Artefakt im Live-Checkout, weil das alte
|
Slugs wiederverwenden (beim Doku-Lauf landete ein Artefakt im Live-Checkout, weil das alte
|
||||||
`/tmp/orch-hermes-desktop-work` recycelt wurde). Existiert dein `/tmp/orch-<slug>` noch nicht,
|
`/tmp/orch-hermes-desktop-work` recycelt wurde). Existiert dein `~/.hermes/worktrees/orch-<slug>` noch nicht,
|
||||||
ist das der Beweis, dass Schritt 2 fehlt — erst Worktree anlegen.
|
ist das der Beweis, dass Schritt 2 fehlt — erst Worktree anlegen.
|
||||||
5. **Grosse Artefakte NIE im Klartext in deine Antwort** — sie gehoeren in Dateien im Worktree.
|
5. **Grosse Artefakte NIE im Klartext in deine Antwort** — sie gehoeren in Dateien im Worktree.
|
||||||
Wer Dateiinhalte in die Antwort kippt, stirbt am Output-Limit mitten im Lauf (Doku-Lauf
|
Wer Dateiinhalte in die Antwort kippt, stirbt am Output-Limit mitten im Lauf (Doku-Lauf
|
||||||
@@ -148,7 +150,7 @@ Grund wie in der Werkstatt („wer seine eigenen Hausaufgaben benotet, stimmt si
|
|||||||
**Zuerst ALLES stagen** — sonst fehlen NEUE Dateien im Diff (haeufigste Falle: `git diff` ignoriert
|
**Zuerst ALLES stagen** — sonst fehlen NEUE Dateien im Diff (haeufigste Falle: `git diff` ignoriert
|
||||||
untracked Dateien, die Kritiker bekaemen einen LEEREN Diff und wuerden alles blind ablehnen):
|
untracked Dateien, die Kritiker bekaemen einen LEEREN Diff und wuerden alles blind ablehnen):
|
||||||
```
|
```
|
||||||
git -C /tmp/orch-<slug> add -A
|
git -C ~/.hermes/worktrees/orch-<slug> add -A
|
||||||
```
|
```
|
||||||
Dann die Eingabe EINMAL bauen (mit `--cached`, damit die neuen Dateien drin sind):
|
Dann die Eingabe EINMAL bauen (mit `--cached`, damit die neuen Dateien drin sind):
|
||||||
```
|
```
|
||||||
@@ -159,7 +161,7 @@ ZERLEGUNG (deine Teil-Tasks, je 1 Zeile):
|
|||||||
<1..n>
|
<1..n>
|
||||||
|
|
||||||
GIT-DIFF des Worktrees:
|
GIT-DIFF des Worktrees:
|
||||||
$(git -C /tmp/orch-<slug> diff --cached origin/main)"
|
$(git -C ~/.hermes/worktrees/orch-<slug> diff --cached origin/main)"
|
||||||
```
|
```
|
||||||
Ist dieser Diff LEER, hast du nicht gestaged (oder nichts gebaut) → NICHT weiter, erst beheben.
|
Ist dieser Diff LEER, hast du nicht gestaged (oder nichts gebaut) → NICHT weiter, erst beheben.
|
||||||
**Kritik A — Kompetenz** (`Qwen3-Coder-Next`, starker Coder, vom Bauen noch geladen → KEIN Swap):
|
**Kritik A — Kompetenz** (`Qwen3-Coder-Next`, starker Coder, vom Bauen noch geladen → KEIN Swap):
|
||||||
@@ -212,7 +214,7 @@ Zugriff aufs Repo. Er sieht NUR, was du ihm auf stdin gibst. Deshalb:
|
|||||||
den Fokus. Ziel: das kleinste, das den Teil-Task eindeutig macht.
|
den Fokus. Ziel: das kleinste, das den Teil-Task eindeutig macht.
|
||||||
|
|
||||||
## Nach dem Commander-Entscheid (kommt als neuer Auftrag)
|
## Nach dem Commander-Entscheid (kommt als neuer Auftrag)
|
||||||
- „verwerfen" → `git worktree remove /tmp/orch-<slug> --force && git branch -D orchestrator/<slug>`
|
- „verwerfen" → `git worktree remove ~/.hermes/worktrees/orch-<slug> --force && git branch -D orchestrator/<slug>`
|
||||||
(+ `rm -rf /tmp/orch-<slug>-work`; Remote-Branch loeschen, falls gepusht).
|
(+ `rm -rf ~/.hermes/worktrees/orch-<slug>-work`; Remote-Branch loeschen, falls gepusht).
|
||||||
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es nur dort).
|
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es nur dort).
|
||||||
Du pushst NIE nach main.
|
Du pushst NIE nach main.
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
|
|||||||
## Ablauf
|
## Ablauf
|
||||||
|
|
||||||
1. **Worktree anlegen** (Slug = kurzer Kebab-Case-Name des Auftrags):
|
1. **Worktree anlegen** (Slug = kurzer Kebab-Case-Name des Auftrags):
|
||||||
`cd ~/mission-control-v2 && git fetch origin && git worktree add /tmp/wartung-<slug> -b wartung/<slug> origin/main`
|
`mkdir -p ~/.hermes/worktrees && cd ~/mission-control-v2 && git fetch origin && git worktree add ~/.hermes/worktrees/wartung-<slug> -b wartung/<slug> origin/main`
|
||||||
|
(Worktrees NIE unter /tmp — ueberlebt keinen Reboot, Review-Befund 15.07.)
|
||||||
2. **Patch** nur im Worktree. Minimal-invasiv, Stil der umgebenden Datei übernehmen
|
2. **Patch** nur im Worktree. Minimal-invasiv, Stil der umgebenden Datei übernehmen
|
||||||
(deutsche Kommentare, bestehende Muster).
|
(deutsche Kommentare, bestehende Muster).
|
||||||
3. **Selbst-Gate** (was zutrifft):
|
3. **Selbst-Gate** (was zutrifft):
|
||||||
@@ -76,7 +77,7 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
|
|||||||
<der Auftrag>
|
<der Auftrag>
|
||||||
|
|
||||||
GIT-DIFF des Worktrees:
|
GIT-DIFF des Worktrees:
|
||||||
<git -C /tmp/wartung-<slug> diff origin/main>" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
|
<git -C ~/.hermes/worktrees/wartung-<slug> diff origin/main>" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Das läuft auf `Qwen3-Coder-Next` (128k, code-stark, anderes Modell als der Qwen3.6-Worker,
|
Das läuft auf `Qwen3-Coder-Next` (128k, code-stark, anderes Modell als der Qwen3.6-Worker,
|
||||||
@@ -113,7 +114,7 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
|
|||||||
|
|
||||||
## Nach dem User-Entscheid (kommt als neuer Auftrag)
|
## Nach dem User-Entscheid (kommt als neuer Auftrag)
|
||||||
|
|
||||||
- „verwerfen" → `git worktree remove /tmp/wartung-<slug> --force && git branch -D wartung/<slug>`
|
- „verwerfen" → `git worktree remove ~/.hermes/worktrees/wartung-<slug> --force && git branch -D wartung/<slug>`
|
||||||
(+ Remote-Branch löschen, falls gepusht: `git push origin --delete wartung/<slug>`)
|
(+ Remote-Branch löschen, falls gepusht: `git push origin --delete wartung/<slug>`)
|
||||||
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es
|
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es
|
||||||
nur dort). Du pushst NIE nach main — auch nicht mit Token.
|
nur dort). Du pushst NIE nach main — auch nicht mit Token.
|
||||||
|
|||||||
Reference in New Issue
Block a user