feat(curator): switch Hermes Curator to DeepSeek V4-Pro via deepseek_local adapter

A/B test (2026-05-05) showed DeepSeek V4-Pro is 2-3x faster and ~20x cheaper
than Sonnet for style/lexicon pattern analysis, with comparable quality.
Adds adapters/deepseek-paperclip-adapter/ package, documents adapter requirements
(env injection, run-id headers), updates CLAUDE.md with adapter integration notes,
and records lessons from ערר 1200-25 (block order for 1xxx, "להלן מתוך" pattern,
expanded factual background, bridge planning analysis, flat heading structure).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 05:58:52 +00:00
parent d81c3c37ab
commit 45341a0bc8
16 changed files with 1380 additions and 7 deletions

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env bash
# One-off A/B test runner: runs the Knowledge Curator (Hermes) on CMP-78 using
# DeepSeek V4-Pro instead of the default Sonnet 4.5 (via marcus/sonnet gateway).
# Compare against CMP-80 which runs with the default config.
set -euo pipefail
PROFILE_HOME="/home/chaim/.hermes/profiles/curator-cmp-deepseek"
PAPERCLIP_API_URL="http://localhost:3100/api"
# CMP curator agent's Paperclip key (from Infisical: nautilus /legal-ai HERMES_CURATOR_CMP_PAPERCLIP_KEY)
PAPERCLIP_API_KEY="pcp_c87edcf306d06fce13fac701bb6d747191d61dba5b51e903"
PAPERCLIP_TASK_ID="beb745e5-7195-40c5-9ac0-e9682c2c5184" # CMP-78
PAPERCLIP_TASK_KEY="$PAPERCLIP_TASK_ID"
PAPERCLIP_TASK_TITLE="[ערר 1130-25] סקירת ידע — Knowledge Curator (DeepSeek A/B test)"
PAPERCLIP_RUN_ID="deepseek-ab-$(date +%s)"
PAPERCLIP_WAKE_REASON="manual_deepseek_ab_test"
# Rendered prompt — copy of the curator template with mustache variables resolved
# manually for CMP-78. We also add a clear "[ניסוי DeepSeek V4-Pro]" prefix so
# the resulting comment is distinguishable from the default-Sonnet run on CMP-80.
read -r -d '' PROMPT <<'EOF' || true
אתה מנהל ידע (Knowledge Curator) של ועדת הערר. נעור על תיק שדפנה סימנה כסופי.
תיק: [ערר 1130-25] סקירת ידע — Knowledge Curator
issue ID: beb745e5-7195-40c5-9ac0-e9682c2c5184
run reason: manual_deepseek_ab_test
**הקשר חשוב — ניסוי A/B:** זוהי ריצה ידנית באמצעות DeepSeek V4-Pro במקום ה-Sonnet הרגיל. כל ה-comment שתפרסם חייב להתחיל בכותרת `[ניסוי DeepSeek V4-Pro]` כדי שנוכל להבדיל מהריצה המקבילה ב-CMP-80 (שרצה עם Sonnet). אל תעיר סוכנים אחרים. אל תיצור issues חדשים. אל תפתח interaction.
הוראות:
דפנה סימנה את ההחלטה הסופית של תיק 1130-25 כסופית.
קובץ סופי: `סופי-1130-25.docx`
סקור את ההחלטה מול skills/decision/SKILL.md ו-docs/legal-decision-lessons.md.
חפש 3-5 דפוסי סגנון/דיון שלא תועדו. כתוב comment בעברית, ניטרלי, ממוספר.
# שלבי ביצוע
## 1. קונטקסט
- קרא את MEMORY.md שלך (memory tool) — מה כבר זיהית.
- קרא `/home/chaim/legal-ai/skills/decision/SKILL.md` (file tool) — מה כבר תועד.
## 2. נתונים
- `mcp__legal-ai__case_get` עם case_number `1130-25` — מטא-דאטה.
- `mcp__legal-ai__case_get_final_text` עם case_number `1130-25` — קרא את הטקסט המלא של ההחלטה הסופית.
- אם רלוונטי: `mcp__legal-ai__search_decisions` להשוואה לחלטות קודמות.
## 3. ניתוח
חפש 3-5 דפוסים/פערים. לכל ממצא: מה ראיתי + מה זה אומר + הצעה ניסוחית מדויקת.
## 4. כתוב comment הממצאים
```bash
curl -sS -X POST -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d "$(jq -n --arg b "$BODY" '{body:$b}')" \
"$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID/comments"
```
פורמט ה-body:
- שורה ראשונה: `[ניסוי DeepSeek V4-Pro]`
- אחר כך פסקה אחת מבוא קצרה
- אחר כך הממצאים ממוספרים
## 5. סגור את ה-issue
```bash
curl -sS -X PATCH -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d '{"status":"done"}' "$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID"
```
# כללים
- אל תעדכן קבצים (skills/, lessons.py, DB) בעצמך. רק comment.
- אל תיצור issues חדשים.
- אל תעיר סוכנים אחרים.
- אל תפתח interaction.
- בעיה? comment קצר עם הסיבה + סגור (status=done).
EOF
export HERMES_HOME="$PROFILE_HOME"
export PAPERCLIP_API_URL PAPERCLIP_API_KEY PAPERCLIP_TASK_ID PAPERCLIP_TASK_KEY \
PAPERCLIP_TASK_TITLE PAPERCLIP_RUN_ID PAPERCLIP_WAKE_REASON
echo "=== DeepSeek V4-Pro Curator A/B test on CMP-78 ==="
echo "HERMES_HOME=$HERMES_HOME"
echo "TASK_ID=$PAPERCLIP_TASK_ID"
echo "RUN_ID=$PAPERCLIP_RUN_ID"
echo "Starting Hermes..."
echo "---"
hermes -z "$PROMPT" --yolo chat 2>&1

View File

@@ -0,0 +1,116 @@
#!/usr/bin/env bash
# A/B test runner #2: DeepSeek V4-Pro on CMP-78 — WITH interaction step
# (matching the full Sonnet baseline workflow on CMP-80, including ask_user_questions).
set -euo pipefail
PROFILE_HOME="/home/chaim/.hermes/profiles/curator-cmp-deepseek"
PAPERCLIP_API_URL="http://localhost:3100/api"
PAPERCLIP_API_KEY="pcp_c87edcf306d06fce13fac701bb6d747191d61dba5b51e903"
PAPERCLIP_TASK_ID="beb745e5-7195-40c5-9ac0-e9682c2c5184" # CMP-78
PAPERCLIP_TASK_KEY="$PAPERCLIP_TASK_ID"
PAPERCLIP_TASK_TITLE="[ערר 1130-25] סקירת ידע — DeepSeek V4-Pro test #2 (with interaction)"
PAPERCLIP_RUN_ID="deepseek-ab2-$(date +%s)"
PAPERCLIP_WAKE_REASON="manual_deepseek_ab_test_v2_with_interaction"
read -r -d '' PROMPT <<'EOF' || true
אתה מנהל ידע (Knowledge Curator) של ועדת הערר. נעור על תיק שדפנה סימנה כסופי.
תיק: [ערר 1130-25] סקירת ידע — Knowledge Curator
issue ID: beb745e5-7195-40c5-9ac0-e9682c2c5184
run reason: manual_deepseek_ab_test_v2_with_interaction
**הקשר חשוב — ניסוי A/B #2:** זוהי ריצה שנייה ידנית באמצעות DeepSeek V4-Pro, הפעם **עם interaction מלא** כדי להשוות הוגנת מול ריצת Sonnet ב-CMP-80. כל הפלטים שתפרסם חייבים להתחיל בכותרת `[ניסוי DeepSeek V4-Pro #2 — עם interaction]`. אל תעיר סוכנים אחרים. אל תיצור issues חדשים.
הוראות:
דפנה סימנה את ההחלטה הסופית של תיק 1130-25 כסופית.
קובץ סופי: `סופי-1130-25.docx`
סקור את ההחלטה מול skills/decision/SKILL.md ו-docs/legal-decision-lessons.md.
חפש 3-5 דפוסי סגנון/דיון שלא תועדו. כתוב comment בעברית, ניטרלי, ממוספר.
# שלבי ביצוע
## 1. קונטקסט
- קרא את MEMORY.md שלך (memory tool) — מה כבר זיהית.
- קרא `/home/chaim/legal-ai/skills/decision/SKILL.md` (file tool) — מה כבר תועד.
## 2. נתונים
- `mcp__legal-ai__case_get` עם case_number `1130-25` — מטא-דאטה.
- `mcp__legal-ai__case_get_final_text` עם case_number `1130-25` — קרא את הטקסט המלא של ההחלטה הסופית.
## 3. ניתוח
חפש 3-5 דפוסים/פערים. לכל ממצא: מה ראיתי + מה זה אומר + הצעה ניסוחית מדויקת.
## 4. כתוב comment הממצאים
```bash
curl -sS -X POST -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d "$(jq -n --arg b "$BODY" '{body:$b}')" \
"$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID/comments"
```
פורמט ה-body:
- שורה ראשונה: `[ניסוי DeepSeek V4-Pro #2 — עם interaction]`
- אחר כך פסקה אחת מבוא קצרה
- אחר כך הממצאים ממוספרים
## 5. פתח interaction מסוג ask_user_questions
זה השלב שעבד את Sonnet הרבה זמן — בוא נראה כמה זמן יקח לך.
```bash
curl -sS -X POST -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
"$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID/interactions" \
-d '{
"kind": "ask_user_questions",
"idempotencyKey": "curator-deepseek-v2:'"$PAPERCLIP_TASK_ID"':select",
"title": "[DeepSeek] איזה ממצאים שווים עדכון?",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"submitLabel": "אשר בחירה",
"questions": [{
"id": "findings_to_propose",
"prompt": "סמן את הממצאים שאני אכין כהצעת עדכון ל-style guide",
"selectionMode": "multi",
"options": [
{"id":"f1","label":"<מילוי לפי ממצא 1>","description":"<תקציר>"},
{"id":"f2","label":"<מילוי לפי ממצא 2>","description":"<תקציר>"}
]
}]
}
}'
```
מלא את ה-options לפי הממצאים שלך — אופציה אחת לכל ממצא ממוספר.
## 6. עדכן issue ל-status=in_review (לא done — ממתינים לבחירת חיים)
```bash
curl -sS -X PATCH -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d '{"status":"in_review"}' "$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID"
```
# כללים
- אל תעדכן קבצים (skills/, lessons.py, DB) בעצמך. רק comment + interaction.
- אל תיצור issues חדשים.
- אל תעיר סוכנים אחרים.
- בעיה? comment קצר עם הסיבה + סגור (status=done).
EOF
export HERMES_HOME="$PROFILE_HOME"
export PAPERCLIP_API_URL PAPERCLIP_API_KEY PAPERCLIP_TASK_ID PAPERCLIP_TASK_KEY \
PAPERCLIP_TASK_TITLE PAPERCLIP_RUN_ID PAPERCLIP_WAKE_REASON
echo "=== DeepSeek V4-Pro #2 (with interaction) — CMP-78 ==="
echo "HERMES_HOME=$HERMES_HOME"
echo "TASK_ID=$PAPERCLIP_TASK_ID"
echo "RUN_ID=$PAPERCLIP_RUN_ID"
echo "Started: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "---"
START_EPOCH=$(date +%s)
hermes -z "$PROMPT" --yolo chat 2>&1
END_EPOCH=$(date +%s)
DURATION=$((END_EPOCH - START_EPOCH))
echo ""
echo "=== Run finished ==="
echo "Ended: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "Duration: ${DURATION}s ($((DURATION/60))m $((DURATION%60))s)"

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env bash
# A/B test #3: Sonnet 4.5 re-run on CMP-78 — same task as DeepSeek #2 but with Sonnet.
# Goal: check if Sonnet is consistent across runs (esp. the case-outcome detection),
# given that the original Sonnet baseline on CMP-80 misread the outcome as "דחייה"
# while the actual result is "קבלה חלקית".
set -euo pipefail
PROFILE_HOME="/home/chaim/.hermes/profiles/curator-cmp" # default Sonnet profile
PAPERCLIP_API_URL="http://localhost:3100/api"
PAPERCLIP_API_KEY="pcp_c87edcf306d06fce13fac701bb6d747191d61dba5b51e903"
PAPERCLIP_TASK_ID="beb745e5-7195-40c5-9ac0-e9682c2c5184" # CMP-78
PAPERCLIP_TASK_KEY="$PAPERCLIP_TASK_ID"
PAPERCLIP_TASK_TITLE="[ערר 1130-25] סקירת ידע — Sonnet rerun (consistency check)"
PAPERCLIP_RUN_ID="sonnet-rerun-$(date +%s)"
PAPERCLIP_WAKE_REASON="manual_sonnet_consistency_rerun"
read -r -d '' PROMPT <<'EOF' || true
אתה מנהל ידע (Knowledge Curator) של ועדת הערר. נעור על תיק שדפנה סימנה כסופי.
תיק: [ערר 1130-25] סקירת ידע — Knowledge Curator
issue ID: beb745e5-7195-40c5-9ac0-e9682c2c5184
run reason: manual_sonnet_consistency_rerun
**הקשר חשוב — ניסוי A/B #3:** זוהי ריצה חוזרת ידנית באמצעות Sonnet 4.5 (אותו מודל שהריץ ב-CMP-80) — בדיקת עקביות. כל הפלטים שתפרסם חייבים להתחיל בכותרת `[ניסוי Sonnet 4.5 — ריצה חוזרת על CMP-78]`. אל תעיר סוכנים אחרים. אל תיצור issues חדשים.
הוראות:
דפנה סימנה את ההחלטה הסופית של תיק 1130-25 כסופית.
קובץ סופי: `סופי-1130-25.docx`
סקור את ההחלטה מול skills/decision/SKILL.md ו-docs/legal-decision-lessons.md.
חפש 3-5 דפוסי סגנון/דיון שלא תועדו. כתוב comment בעברית, ניטרלי, ממוספר.
# שלבי ביצוע
## 1. קונטקסט
- קרא את MEMORY.md שלך (memory tool) — מה כבר זיהית.
- קרא `/home/chaim/legal-ai/skills/decision/SKILL.md` (file tool) — מה כבר תועד.
## 2. נתונים
- `mcp__legal-ai__case_get` עם case_number `1130-25` — מטא-דאטה.
- `mcp__legal-ai__case_get_final_text` עם case_number `1130-25` — קרא את הטקסט המלא של ההחלטה הסופית.
**שים לב במיוחד**: זהה במדויק את **תוצאת ההחלטה** (קבלה / קבלה חלקית / דחייה) על סמך הטקסט עצמו, לא על סמך הנחות.
## 3. ניתוח
חפש 3-5 דפוסים/פערים. לכל ממצא: מה ראיתי + מה זה אומר + הצעה ניסוחית מדויקת.
## 4. כתוב comment הממצאים
```bash
curl -sS -X POST -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d "$(jq -n --arg b "$BODY" '{body:$b}')" \
"$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID/comments"
```
פורמט ה-body:
- שורה ראשונה: `[ניסוי Sonnet 4.5 — ריצה חוזרת על CMP-78]`
- שורה שנייה: `**תוצאת ההחלטה הזו: <קבלה / קבלה חלקית / דחייה>** — ציין מפורשות
- אחר כך פסקה אחת מבוא קצרה
- אחר כך הממצאים ממוספרים
## 5. פתח interaction מסוג ask_user_questions
זהה לפלואו של Sonnet באמת. אם תקבל "Agent run id required" — נסה כמה דרכים, ואם לא הולך, פרסם comment עם רשימת אופציות לבחירה.
```bash
curl -sS -X POST -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
"$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID/interactions" \
-d '{
"kind": "ask_user_questions",
"idempotencyKey": "curator-sonnet-rerun:'"$PAPERCLIP_TASK_ID"':select",
"title": "[Sonnet rerun] איזה ממצאים שווים עדכון?",
"continuationPolicy": "wake_assignee",
"payload": {"version": 1, "submitLabel": "אשר בחירה",
"questions": [{"id": "findings_to_propose", "prompt": "סמן ממצאים", "selectionMode": "multi", "options": []}]}}'
```
## 6. עדכן issue ל-status=in_review
```bash
curl -sS -X PATCH -H "Authorization: Bearer $PAPERCLIP_API_KEY" -H "Content-Type: application/json" \
-d '{"status":"in_review"}' "$PAPERCLIP_API_URL/issues/$PAPERCLIP_TASK_ID"
```
# כללים
- אל תעדכן קבצים בעצמך. רק comment + interaction.
- אל תיצור issues חדשים.
- אל תעיר סוכנים אחרים.
EOF
export HERMES_HOME="$PROFILE_HOME"
export PAPERCLIP_API_URL PAPERCLIP_API_KEY PAPERCLIP_TASK_ID PAPERCLIP_TASK_KEY \
PAPERCLIP_TASK_TITLE PAPERCLIP_RUN_ID PAPERCLIP_WAKE_REASON
echo "=== Sonnet 4.5 rerun (consistency check) — CMP-78 ==="
echo "HERMES_HOME=$HERMES_HOME"
echo "TASK_ID=$PAPERCLIP_TASK_ID"
echo "RUN_ID=$PAPERCLIP_RUN_ID"
echo "Started: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "---"
START_EPOCH=$(date +%s)
hermes -z "$PROMPT" --yolo chat 2>&1
END_EPOCH=$(date +%s)
DURATION=$((END_EPOCH - START_EPOCH))
echo ""
echo "=== Run finished ==="
echo "Ended: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "Duration: ${DURATION}s ($((DURATION/60))m $((DURATION%60))s)"

View File

@@ -10,7 +10,7 @@
|--------|------|---------|-----------|
| `pc.sh` | bash | **wrapper לכל קריאות Paperclip API מסוכנים** — מוסיף Authorization, X-Paperclip-Run-Id (audit trail), Content-Type, base URL. תחביר: `pc.sh <METHOD> <PATH> [BODY_JSON]`. אסור `curl` ישיר ל-`$PAPERCLIP_API_URL`. ראה `HEARTBEAT.md §0`. counterpart ב-Python: `web/paperclip_api.py`. | נקרא ע"י סוכנים |
| `sync_missing_agent_skills.py` | python | סקריפט "אל-כשל" להוספת `paperclipSkillSync` ל-`הגהת מסמכים` ו-`מנתח משפטי` שפיספסו את ה-sync ההיסטורי (Gap #28). תומך `--verify`/`--dry-run`/`--apply`. גיבוי אוטומטי ל-`agents-pre-skill-sync-*.sql`. דורש `PAPERCLIP_BOARD_API_KEY` (Infisical /paperclip ב-nautilus env). idempotent. | חד-פעמי (בוצע 2026-05-04). שמור לרפרנס |
| `sync_agents_across_companies.py` | python | **סנכרון סוכנים מ-CMP (1xxx, master) ל-CMPA (8xxx, mirror)** — Gap #25. משווה adapter_config (model/timeout/instructions/skills/etc), runtime_config (heartbeat), ושדות top-level (budget/metadata/icon/title/role). מסנן אוטומטית local skills שלא קיימים ב-mirror. לוגיקת subset (mirror יכול להחזיק יותר skills כי ה-API מוסיף required runtime skills). תומך `--verify`/`--dry-run`/`--apply [--only NAME]`. גיבוי אוטומטי. דורש `PAPERCLIP_BOARD_API_KEY`. **להריץ אחרי כל שינוי הגדרות ב-CMP.** | ידני אחרי כל שינוי |
| `sync_agents_across_companies.py` | python | **סנכרון סוכנים מ-CMP (1xxx, master) ל-CMPA (8xxx, mirror)** — Gap #25. משווה adapter_config (model/timeout/instructions/skills/etc), runtime_config (heartbeat), ושדות top-level (budget/metadata/icon/title/role). מסנן אוטומטית local skills שלא קיימים ב-mirror. לוגיקת subset (mirror יכול להחזיק יותר skills כי ה-API מוסיף required runtime skills). תומך `--verify`/`--dry-run`/`--apply [--only NAME]`. גיבוי אוטומטי. דורש `PAPERCLIP_BOARD_API_KEY`. **להריץ אחרי כל שינוי הגדרות ב-CMP.** **⚠ אם `adapter_type` שונה בין CMP ל-CMPA — הסקריפט מדלג על הסוכן עם warning. בעת מעבר adapter (למשל ל-`deepseek_local`) חובה לעדכן ידנית בשתי החברות לפני sync.** | ידני אחרי כל שינוי |
| `fix_paperclipai_skills_drift.py` | python | סקריפט חד-פעמי (בוצע 2026-05-04) שניקה drift על `paperclipai/*` skills בין CMP ל-CMPA. הסיר `paperclip-dev` מכל 14 הסוכנים, ודאג ש-`paperclip-converting-plans-to-tasks` קיים רק על CEO ו-analyst. תומך `--apply` (ברירת מחדל: dry-run). דורש `PAPERCLIP_BOARD_API_KEY`. נשמר לרפרנס למקרה שhdrift חוזר. | חד-פעמי (בוצע) |
| `auto-sync-cases.sh` | bash | סנכרון תיקי ערר ל-Gitea — רץ כל דקה | `* * * * *` (cron) |
| `backup-db.sh` | bash | גיבוי PostgreSQL יומי ל-`data/backups/` (gzip) | לתזמן: `0 2 * * *` |
@@ -54,6 +54,9 @@
| `seed-appeals.py` | seeding תיקי ערר ראשוניים ל-DB | MCP: `case_create()` |
| `seed-knowledge.py` | seeding לקחים, ביטויי מעבר, פסיקה | MCP: `record_chair_feedback()`, `precedent_attach()` |
| `validate-decision.py` | ולידציה מול block-schema | MCP: `validate_decision()` + `qa_validator.py` |
| `run_curator_deepseek_test.sh` | A/B test #1 (2026-05-05) — Hermes Curator על CMP-78 דרך DeepSeek V4-Pro ב-`provider:custom`, ללא interaction. תוצאה: 6:33 דק׳, 5 ממצאי סגנון/לקסיקון, פי 3 מהיר מ-Sonnet baseline (CMP-80) ופי ~20 זול. **הסקריפט נקודתי לתיק 1130-25 — לא להריץ שוב** | החלפת Curator לאדפטר DeepSeek מקומי (בתהליך) |
| `run_curator_deepseek_test_v2.sh` | A/B test #2 (2026-05-05) — אותו run אבל עם interaction. תוצאה: 9:08 דק׳, 5 ממצאים, היחיד מ-4 הריצות שזיהה תוצאה עובדתית נכונה (קבלה חלקית). interaction נכשל ב-API ("Agent run id required" בריצה ידנית). | החלפת Curator לאדפטר DeepSeek מקומי |
| `run_curator_sonnet_rerun.sh` | A/B test #3 (2026-05-05) — ריצה חוזרת של Sonnet 4.5 על אותו CMP-78. תוצאה: 12:52 דק׳ (לעומת 20:13 בריצה המקורית — כי בלי לולאת interaction.json). זיהה תוצאה שגויה ("דחייה") **בעקביות עם הריצה המקורית** — Sonnet עקבי-בטעות, DeepSeek אקראי. | בדיקה חד-פעמית — לא להריץ שוב |
## סקריפטים שנמחקו (git history בלבד)