# סיכום סשן — 0026
תאריך: 2026-05-25 00:30
אפליקציה: Vitruvius
נושא: Ribbon-1-button + BackupDiscovery + pipe-deadlock fix

## מה נבנה/הושלם

### Ribbon Consolidation (החלטת משתמש: 6 → 1 כפתור)
- **לפני:** 6 כפתורים נפרדים — סריקת פונטים · החל תיקון · הזז SHX · החזר SHX · הפוך עברית · אודות. כל אחד עם TaskDialog משלו, דרישת Manage Links → Reload ידני אחרי.
- **אחרי:** SplitButton יחיד. Top half = "תקן ג'יבריש" (default action). Dropdown arrow = "חזור למקור". כל הזרימה מאחורי הקלעים, ללא הודעות ביניים.
- **`IsSynchronizedWithCurrentItem = false`** — הכפתור הראשי לא מתחלף ל-Restore גם אם המשתמש קרא לו פעם.

### FixGibberishCommand (האורקסטרטור החדש)
**File:** `src\Vitruvius.Revit2024\Commands\FixGibberishCommand.cs`
Pipeline בלחיצה אחת:
1. סורק את כל ה-DWG/DXF links במודל
2. מציג WPF picker עם checkboxes (default: הכל מסומן) + badge "תוקן בעבר"
3. למה שנבחר: כותב fontmap blanket (FontRecommender.AllKnown — כל 14 ה-SHX→Vitruvius Hebrew Visual), מעביר SHX לארכיון, עושה reverse לתוכן (DXF ישירות + DWG דרך accoreconsole), רושם ב-StateCache
4. **`CADLinkType.Reload()` תכנותי** על כל element שתוקן — המשתמש לא נוגע ב-Manage Links
5. Toast 3s להצלחה / TaskDialog רק על שגיאה
`TransactionMode.Manual` (לא ReadOnly) כי Reload משנה את ה-doc.

### RestoreToOriginalCommand
**File:** `src\Vitruvius.Revit2024\Commands\RestoreToOriginalCommand.cs`
- WPF picker רק עם קבצים שיש להם state-cache entry **או** backup על הדיסק
- משחזר מ-`backups.FindOldestBackup()` (הקובץ המקורי של היועץ, לא backup ביניים מתיקון חוזר)
- מסיר entry מ-StateCache
- אם בתיקייה אין יותר קבצים מתוקנים → גם ShxArchiveService.Restore אוטומטית
- `CADLinkType.Reload()` תכנותי

### VitruviusStateCache (Core)
**File:** `src\Vitruvius.Core\State\VitruviusStateCache.cs`
JSON-on-disk cache ב-`%APPDATA%\Vitruvius\state.json`:
```json
{"schemaVersion": 1, "entries": [{"originalPath":"...","backupPath":"...","fixedAt":"...","format":"DWG"}]}
```
JSON serializer/parser **ידני** — אין Newtonsoft/STJ. Core נשאר netstandard2.0 בלי deps נוספים. Save()/Load() עטופים try/catch — אסור שטלמטריה תקרוס flow.

### BackupDiscoveryService (Core)
**File:** `src\Vitruvius.Core\State\BackupDiscoveryService.cs`
Regex: `\.before-vitruvius(?:-dwg|-reverse)?-(\d{8})_?(\d{4})\.bak$`
מזהה גם:
- `*.before-vitruvius-{date}_{time}.bak` (DxfTextReverser)
- `*.before-vitruvius-dwg-{date}_{time}.bak` (DwgReverseService)
- `*.before-vitruvius-reverse-{datetime}.bak` (Python script הישן מסשן 0025)

FindOldestBackup = הקובץ המקורי של היועץ. FindNewestBackup שמור לעתיד ("undo last fix").

**זה פתר את התלונה הראשונית של המשתמש** — `restore` הציג "אין מקור לשחזור" כי state.json היה ריק (תיקונים מסשן 0025 קודמים ל-cache). עכשיו גם תיקונים ישנים ניתנים לשחזור.

### LinkSelectionDialog (WPF picker)
**File:** `src\Vitruvius.Revit2024\UI\LinkSelectionDialog.cs`
- בנוי **תכנותית בלי XAML** (אין צורך ב-UseWPF — refs ידניים: PresentationCore/Framework/WindowsBase/System.Xaml/System.Drawing)
- RTL, dark theme (#2B2B2B background, #F0F0F0 text)
- Row per link: checkbox + filename + folder path + format pill + "תוקן בעבר" badge
- כפתורים: בחר הכל / נקה הכל / תקן (או שחזר) / ביטול
- `LinkSelectionBuilder.BuildFixItems` + `BuildRestoreItems` — בונים את הרשימה לפי mode

### VitruviusToast (notification)
**File:** `src\Vitruvius.Revit2024\UI\VitruviusToast.cs`
חלון WPF non-modal, no title bar, rounded corners, DispatcherTimer 3s. ירוק להצלחה / אדום לשגיאה. WindowStartupLocation = bottom-right של ה-WorkArea.
**Gotcha:** `System.Windows.Shapes.Ellipse` הוא **sealed** — אסור לרשת. ליצור instance ישירות.

### VitruviusLog (diagnostics)
**File:** `src\Vitruvius.Core\State\VitruviusLog.cs`
Append-only log ב-`%APPDATA%\Vitruvius\diagnostic.log`. נקרא מ-Commands כדי שאם משהו לא קורה כצפוי, אפשר לדבג בלי attach debugger. lock-protected, never throws.

## החלטות שהתקבלו
- **M4 (Overlay Stub) בוטל** — DXF reverse + TTF פתרו את הבעיה ויזואלית כבר ב-M3. Phase 2 לא יכלול overlay גם הוא.
- **About button הוסר** — לא מחויב משפטית (MIT attribution ל-IxMilia.Dxf אפשר לקיים עם LICENSES.txt בהתקנה). יתווסף מאוחר יותר רק אם יידרש UI להגדרות טלמטריה (M2 ראה PLAN).
- **דיאלוג בחירה לכל פעולה** (החלטת משתמש) — גם תקן וגם שחזור פותחים picker. ברירת מחדל: הכל מסומן.
- **"חזור למקור" משחזר מהגיבוי הישן ביותר**, לא החדש — כי הוא הקובץ המקורי של היועץ, לא backup ביניים.
- **Timeout נשאר 5 דקות** ל-accoreconsole (אחרי תיקון pipe drain). היה הניסיון להאריך ל-15 דקות אבל זה היה treating the symptom.

## בעיות שנפתרו

### 🔥 הבאג הקריטי: accoreconsole pipe deadlock
**Symptom:** "תקן ג'יבריש" timed out ב-5 דקות. הארכתי ל-15 דקות — עוד timeout.
**Investigation:** הרצתי את accoreconsole **ישירות מ-PowerShell** עם אותו DWG ו-script — **2 שניות**! אז זה לא cold-start.
**Root cause:** `DwgReverseService.RunAccoreScript` הגדיר `RedirectStandardOutput=true + RedirectStandardError=true` אבל **לא קרא את ה-pipes**. accoreconsole מוציא ~10KB stdout per run (SYSVARMONITOR notices, command echoes, status). אחרי 4KB (גודל ברירת המחדל של pipe buffer ב-Windows) — accoreconsole נחסם על הכתיבה הבאה, ו-`WaitForExit` חיכה לעולם.
**Fix:** `proc.BeginOutputReadLine()` + `proc.BeginErrorReadLine()` עם handlers no-op לפני `WaitForExit`. אם רוצים את הפלט — מחברים את ה-handlers; אם לא, פשוט שואבים אותו ל-/dev/null. הוא חייב לזרום.
**Result:** מ-15-min-timeout ל-5-second-success עם 678 טקסטים הופכו.

### "אין מקור לשחזור" כש-state.json ריק
**Symptom:** המשתמש לחץ "חזור למקור", קיבל toast "אין קישורים לשחזור" אף שיש קבצים מתוקנים על הדיסק.
**Cause:** state.json נוצר רק עם first fix של ה-build החדש. תיקונים מסשנים קודמים לא נרשמו.
**Fix:** `BackupDiscoveryService` סורק את התיקייה אחר קבצי `.bak`. `BuildRestoreItems` כולל כל קובץ עם cache entry **או** backup על הדיסק.

### Revit "Security - Unsigned Add-In" autonomous click
**Symptom:** ה-autonomous test script ניסה ללחוץ "Always Load" עם Win32 SendMessage(BM_CLICK) — נכשל.
**Cause:** הכפתורים של ה-Security dialog הם **Panes class `CCPushButton`** (Autodesk custom), לא Win32 Button.
**Fix:** Click via BoundingRectangle center עם SetCursorPos + mouse_event. (תיעוד ב-feedback-do-everything-autonomous memory ציין שזה Pane, אבל ב-Win32 ניסיתי SendMessage קודם.)

### Revit "Unresolved References" מופיע פעמיים
**Symptom:** dismiss אחד, אחר כך עוד אחד חוסם.
**Cause:** Revit מציג את הדיאלוג פעמיים — פעם אחת מוקדם (במהלך load) ופעם שנייה אחרי full load.
**Fix:** ה-autonomous handler ללא ב-loop במקום one-shot.

## מה לא עבד / צריך להיזהר

- **`<UseWPF>true</UseWPF>` עם net48 SDK-style csproj** — תיאורטית עובד אבל סבוך. במקום זה: refs ידניים ל-PresentationCore/PresentationFramework/WindowsBase/System.Xaml/System.Drawing. WPF נטען ב-Revit כך או כך.
- **DataTemplate מ-XamlReader.Load string** — אסור לשים `{StaticResource}` כי resource lookup לא עובד טוב על DataTemplate נטען בנפרד. עדיף לבנות את ה-Row תכנותית עם FrameworkElementFactory או ידנית (כפי שעשיתי).
- **`System.Windows.Shapes.Ellipse` is sealed** — אסור לרשת ממנו. ליצור instance ישירות.
- **`Path` כשם property בכיתה שמשתמשת ב-`System.IO.Path`** — מסך static lookup. שיניתי ל-`FilePath`.
- **`$PID` ב-PowerShell** — read-only built-in. לא להשתמש כשם משתנה. השתמש ב-`$winPid` או דומה.
- **`-match` עם array ב-PowerShell** מחזיר elements שמתאימים, לא bool. הוא truthy אם יש התאמה, אבל לא ניתן להוציא את הערך כך.

## קבצים שנוצרו/שונו

### נוצרו:
- `Vitruvius\src\Vitruvius.Core\State\VitruviusStateCache.cs`
- `Vitruvius\src\Vitruvius.Core\State\BackupDiscoveryService.cs`
- `Vitruvius\src\Vitruvius.Core\State\VitruviusLog.cs`
- `Vitruvius\src\Vitruvius.Revit2024\UI\LinkSelectionDialog.cs`
- `Vitruvius\src\Vitruvius.Revit2024\UI\VitruviusToast.cs`
- `Vitruvius\src\Vitruvius.Revit2024\Commands\FixGibberishCommand.cs`
- `Vitruvius\src\Vitruvius.Revit2024\Commands\RestoreToOriginalCommand.cs`
- `Vitruvius\tools\auto-flow-v2.ps1` + `revit-dialog-handler.ps1` (autonomous testing — לא חלק מהפלאגין)
- `Vitruvius\_M4-decision-briefing.html` (working brief — בדפדפן בלבד)

### שונו:
- `Vitruvius\src\Vitruvius.Revit2024\VitruviusApp.cs` — Ribbon ל-SplitButton
- `Vitruvius\src\Vitruvius.Revit2024\Vitruvius.Revit2024.csproj` — refs WPF
- `Vitruvius\src\Vitruvius.Core\Fonts\FontRecommender.cs` — הוסף `AllKnown()`
- `Vitruvius\src\Vitruvius.Core\Dwg\DwgReverseService.cs` — **`BeginOutputReadLine` fix**
- `Vitruvius\PLAN.md` — M1/M2/M3 ✓, M4 = N/A
- `D:\Vitruvius Ecosystem\CLAUDE.md` — section "Session 0026" + הצעד הבא מ-M4 ל-M5

### Memory:
- `C:\Users\elyas\.claude\projects\D--Vitruvius-Ecosystem-Vitruvius\memory\accoreconsole-cold-start.md` ← עודכן ושונה ל-`accoreconsole-pipe-deadlock` (הסיבה האמיתית)
- `MEMORY.md` — עודכן

### Deployment:
DLL חדש ב-`C:\ProgramData\Autodesk\Revit\Addins\2024\Vitruvius\`:
- `Vitruvius.Core.dll` 54KB
- `Vitruvius.Revit2024.dll` 53KB
- timestamp 2026-05-25 00:01

ארכוב ל-OLD\ (4 בילדים מהסשן):
- 2026-05-24_13-55 (deploy ראשון — M3 polish)
- 2026-05-24_18-44 (BackupDiscovery)
- 2026-05-24_23-34 (15-min timeout — לא הכרחי בדיעבד)
- 2026-05-25_00-01 (**pipe drain fix — ה-final**)

## הצעד הבא

**M5 — DwgReloadHandler (auto re-fix on link reload).**

לפי PLAN.md (שורות 126-131, 154):
> - `DwgReloadHandler` נרשם ל-`Application.DocumentChanged`
> - מזהה שינוי ב-`ImportInstance` (reload event)
> - בודק ב-`StateCache` אם ה-link הזה תוקן בעבר
> - מפעיל אוטומטית את `ScanAndFixCommand` עליו

תרגום למצב הנוכחי (אחרי הקונסולידציה):
1. צור `src\Vitruvius.Revit2024\Events\DwgReloadHandler.cs`
2. `VitruviusApp.OnStartup`: רישום ל-`controlledApp.ControlledApplication.DocumentChanged`
3. ב-handler: סקור את `args.GetModifiedElementIds()` — אם element הוא `ImportInstance` ויש לו `GetExternalFileReference()` שמצביע לקובץ ב-`VitruviusStateCache.Has()` → קרא לpipeline silent
4. **Pipeline silent:** הוצא שיטה `public static FixResult RunSilently(string path)` מ-FixGibberishCommand שלא פותחת picker — מקבלת path רגיל, רצה fontmap+archive+reverse+reload, מחזירה תוצאה.
5. Toast: "Vitruvius: עיבוד DWG מעודכן…" (תוך כדי), "תוקן" (אחרי).
6. **Gotcha צפוי:** `DocumentChanged` יורה הרבה. צריך לסנן ל-reload events בלבד — לא לכל modification. לפי תיעוד Revit: `args.Operation == UndoOperation.TransactionCommitted` + element type בדיקה.

אם async/איטי (סביב 5 שניות לפי הnew benchmark) → לעטוף ב-Task.Run אבל בלי לחסום Revit's UI thread.

הצעד שאחרי M5 לפי PLAN: **M6 UI מלא** — אבל אחרי הקונסולידציה זה ככל הנראה לא נדרש. הצעד האמיתי אחרי M5 = **M9 Installer (Inno Setup)** + **M11 בטא**.

## תרשימים שנוצרו
- אף תרשים חדש (לא תרשים session). הבא = **VIT-011** (בעתיד).

## Memory entries בסשן זה
- `accoreconsole-pipe-deadlock.md` — שונה משם מ-`accoreconsole-cold-start.md`. תיאור: "accoreconsole.exe deadlocks when its stdout/stderr are redirected but not drained. Fix is BeginOutputReadLine/BeginErrorReadLine, not a longer timeout."
