From e239915fd380f0e58a70dcc034191691ca854c52 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 6 Jun 2026 21:24:12 +0000 Subject: [PATCH] =?UTF-8?q?docs(paperclip-quirks):=20=C2=A75=20=E2=80=94?= =?UTF-8?q?=20pruned=20npx=20cache=20=E2=86=92=20500/crash-loop=20+=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the failure mode hit on 06/06/26: a pruned npx cache makes the running paperclip serve GET / → 500 (deleted ui-dist) and, on restart, crash-loop because the server's startup assertCloudDatabaseContract() out-races the post-exec patch loop. Records the synchronous pre-extract+patch gate now in start-paperclip.sh (paperclip-config c824e0f), the `--help` clean-extract trick, the three bugs found while building the fix (ui-dist vs dist marker, set -e on patch failure, pkill -f self-match), the manual recovery runbook, and the e2e verification. Invariants: docs-only; touches no G*/INV-* code paths. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/paperclip-quirks.md | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/paperclip-quirks.md b/docs/paperclip-quirks.md index cd1827b..5247a9d 100644 --- a/docs/paperclip-quirks.md +++ b/docs/paperclip-quirks.md @@ -155,3 +155,78 @@ CEO צריך להעביר את ה-issue ל-`in_review` (לא `in_progress`) כש ### סטטוס - **תיקון בכל הסקייל** (CLAUDE.md זיכרון: `reference_paperclip_wakeup.md`) + +--- + +## 5. מחיקת npx cache → crash-loop בהפעלה (השרת מנצח את הפאטצ') + +### מה קורה + +Paperclip מופעל דרך `exec npx -y paperclipai@ run` ב-[start-paperclip.sh](../../.paperclip/scripts/start-paperclip.sh). npx **עושה reuse** ל-cache שכבר חולץ (`~/.npm/_npx//node_modules/@paperclipai/server/`) — הוא **לא** מחלץ מחדש בכל הפעלה. כל עוד ה-cache קיים, הפאטצ'ים שהוחלו עליו פעם אחת נשמרים על פני ריסטארטים. + +הבעיה מתחילה כש-ה-cache **נמחק** (`npm cache clean`, prune, או ניקוי ידני) בזמן שהתהליך רץ. אז נוצרות שתי תקלות נפרדות: + +1. **התהליך הישן ממשיך "online" אבל שבור** — המודולים של node כבר טעונים בזיכרון, אז `/api/health` עדיין מחזיר 200, אבל `GET /` קורא את `ui-dist/index.html` **מהדיסק בכל בקשה** (`readFileSync`) → `ENOENT` → **HTTP 500** (`{"error":"Internal server error"}`). גם ה-URL הציבורי `pc.nautilus...` מחזיר 500. +2. **בריסטארט נכנסים ל-crash-loop** — npx מחלץ עותק **טרי ולא-מתוקן**. השרת מריץ `assertCloudDatabaseContract()` (ראה patch §4 ב-start script) שמסרב ל-embedded PG במצב authenticated/public → **קורס מיד**, לפני שלולאת-הרקע (5/20/60ש') מספיקה להחיל את פאטץ' ה-bypass. כל ריסטארט מחלץ-וקורס מחדש ⇒ עשרות ריסטארטים, שום דבר לא מאזין על 3100. + +### ראיה אמפירית — 06/06/26 + +``` +# התהליך הישן: online 5D אבל GET / נכשל +GET / 500 — ENOENT: no such file or directory, + open '.../@paperclipai/server/ui-dist/index.html' +/api/health → 200 # שורד כי לא קורא קבצים + +# אחרי restart: crash-loop +pm2 describe paperclip → status: "waiting restart", restarts: 36, nothing on :3100 +ERROR log → "Paperclip server failed to start. + authenticated public deployments require DATABASE_URL ...; + refusing embedded PostgreSQL fallback" +``` + +הורדת החבילה איטית (~30ש', native builds) — מה שמחמיר את ה-loop: `min_uptime` של PM2 קוטע את ה-npx **באמצע ההורדה** לפני שהוא מסיים לחלץ, כך שה-cache לעולם לא מתמלא. + +### ההשפעה על הצינור שלנו + +Paperclip מושבת לגמרי — ה-UI לא עולה לאף משתמש, וכל סוכני Paperclip (14 הסוכנים) לא יכולים לרוץ כי הם חולקים את התהליך הזה. + +### תיקון — שער סינכרוני לפני הפעלת השרת + +**שורש הבעיה:** פאטץ' ה-cloud-db-bypass חייב להיות על הדיסק **לפני** שהשרת רץ; לולאת-הרקע מאוחרת מדי. ב-[start-paperclip.sh](../../.paperclip/scripts/start-paperclip.sh) נוספה `ensure_patched_before_run()` (06/06/26) שרצה סינכרונית לפני `exec`: + +1. בודקת אם `@paperclipai/server/ui-dist/index.html` קיים ב-cache (ראה "מלכודות בדרך" — זה הסמן הנכון, לא `dist/index.js`). +2. אם לא — מריצה `npx -y paperclipai@ --help`. זה מאלץ את npx **לחלץ את כל החבילה** (כולל `ui-dist/`) כדי להריץ את ה-CLI, שמדפיס help ו**יוצא לבד ב-exit 0** — **לא** מפעיל שרת ולא תופס את 3100 (אומת). אין תהליך-רקע, אין שרת לא-מתוקן מוקדם, ואין מה להרוג. +3. מחילה את **כל** הפאטצ'ים (כולל bypass) על ה-cache המחולץ — עם guard שלא מפיל את ה-wrapper אם patch נכשל. +4. רק אז `exec npx ... run` — npx עושה reuse ל-cache המתוקן והשרת עולה נקי. + +לולאת-הרקע (post-exec) נשמרה כרשת-ביטחון idempotent. + +**אומת מקצה-לקצה (06/06/26):** מחיקת ה-cache בכוונה + `pm2 restart` → השער חילץ אוטומטית דרך `--help` (~64ש'), תיקן, והשרת עלה ל-200 ב-~72ש'. מונה הריסטארטים של PM2 **לא זז** (אפס crash-loop). + +> **מלכודות שהתגלו בדרך (גרסה ראשונה של הפיקס נכשלה):** +> 1. **סמן חילוץ שגוי** — `dist/index.js` נכתב ~שניות **לפני** `ui-dist/`. שער שממתין ל-`dist` ומריץ מיד → ui-dist עדיין חסר → 500. הסמן הנכון הוא `ui-dist/index.html` (הקובץ האחרון, וגם זה שגרם ל-500 המקורי). +> 2. **`set -e` + patch כושל** — אם `apply-hebrew.sh` רץ בלי ui-dist הוא מחזיר שגיאה, ותחת `set -e` ה-wrapper מת → crash-loop חדש. הפתרון: `apply_all_patches || echo WARNING`. +> 3. **`pkill -f "paperclipai@..."` תופס את עצמו** — מחרוזת הדפוס מופיעה ב-command line של ה-shell שמריץ את ה-pkill, אז הוא הורג את עצמו (exit 144). זו הסיבה שגישת spawn-`run`-then-`pkill` ננטשה לטובת `--help` שיוצא לבד. אם בכל זאת צריך להרוג — לפי PID (`kill $PID; pkill -P $PID`), לא לפי `-f`. + +**שחזור** — עם הפיקס פרוס, מספיק `pm2 restart paperclip` וה-`ensure_patched_before_run()` מתאושש לבד. אם צריך לעשות זאת ידנית (fix אחר, דיבוג): +```bash +pm2 stop paperclip # לעצור loop אם קיים +export PATH=/home/chaim/.nvm/versions/node/v24.14.0/bin:$PATH +npx -y paperclipai@2026.529.0 --help >/dev/null 2>&1 # חילוץ נקי שיוצא לבד (לא מפעיל שרת) +find ~/.npm/_npx -path "*@paperclipai/server/ui-dist/index.html" -type f # לאמת חילוץ מלא +# להחיל פאטצ'ים על ה-cache, ובמיוחד ה-bypass: +bash ~/.paperclip/hermes-patches/apply-cloud-db-bypass.sh +bash ~/.paperclip/hebrew/apply-hebrew.sh +bash ~/.paperclip/hermes-patches/apply-hermes-fixes.sh +bash ~/.paperclip/hermes-patches/apply-deepseek-reaper-fix.sh +grep -q HEBREW_PATCH_BYPASS_CLOUD_DB \ + ~/.npm/_npx/*/node_modules/@paperclipai/server/dist/index.js && echo "BYPASS OK" +pm2 start paperclip && pm2 save # reuse ל-cache המתוקן +``` +> אל תשתמש ב-`pkill -f "paperclipai@..."` / `-f "@paperclipai/server"` — הדפוס תופס את ה-shell של עצמך (exit 144). אם חייבים להרוג תהליך — לפי PID. + +### סטטוס + +- **תוקן ב-start script** ע"י `ensure_patched_before_run()` (06/06/26) — שער סינכרוני שמחלץ+מתקן לפני exec. +- **הערה מטעה תוקנה**: ההערה הישנה בראש ה-script טענה ש-`npx run` מחלץ-מחדש בכל הפעלה (לכן הסתמכו על לולאת-הרקע בלבד) — זה לא נכון, npx עושה reuse ל-cache תקין; הסכנה היא cache **מחוק**. +- **לקח כללי**: כל patch שה-target שלו הוא assert בזמן-startup חייב להיות מוחל לפני `exec`, לא בלולאת-רקע.