# ARCHITECTURE — מבנה היעד המבנה שאליו ה‑monorepo מתכנס. `core/` (+`config`/`calibration`/`pipeline`), `verticals/logistics/` ו‑`harness/` כבר במבנה היעד; `infra/` ו‑`delivery/` עדיין ב‑`legacy/` ומהגרות בשלבים הבאים (`MIGRATION_MAP.md`). ## עקרון מנחה תלות זורמת בכיוון אחד בלבד: ``` core ← verticals ← infra ← delivery ▲ │ └──────────────────────────────────┘ delivery ו-infra משתמשים ב-core; core לא יודע על אף אחד מהם ``` `core/` אסור שיֵדע על שום שכבה אחרת. אם משהו ב‑`core/` צריך לייבא מ‑`infra/` או מ‑`verticals/` — הוא לא שייך ל‑`core/`. ## השכבות ### `core/` — הליבה האנליטית ✅ הוגר ב-Stage 0 מודל הנתונים הקנוני והמתמטיקה הדטרמיניסטית. stdlib בלבד, ללא I/O, ללא state. - `events.py` — `CanonicalEvent` - `state.py` — `EntityState` - `ontology.py` — `Entity`, `ENTITY_TYPES` - `signals.py` — Δ, ψ, ξ, γ, κ, Ω (signal math) - `drift.py` — `DriftIssue`, `drift_score`, `severity_from_score` - `decisions.py` — `DecisionItem`, `recommendation_for_issue` זו השכבה היחידה שחייבת להיות מכוסה ב‑100% בבדיקות correctness אמיתיות. היום: 36 בדיקות, כולל בדיקת lead‑time אינטגרטיבית (`tests/test_core_integration.py`). ### `verticals/` — adapters לאנכים ✅ Stage 1 (logistics) adapter עושה עבודה אחת: ממפה סכמה גולמית של לקוח ל‑canonical events/metrics ש‑`core/` מבין. **שום לוגיקה אנליטית ב‑adapter** — הוא תרגום בלבד. `logistics/` הוא ה‑adapter הראשון (`config.yaml` + `adapter.py`). `team_drift_detector.py` הוגר לכאן — detector, לא core, superseded ע"י הצינור הגנרי. ### `harness/` — harness אימות ✅ Stage 2 מחולל תרחישים מתויגים ומודד את המנוע מול ground truth: precision, recall, detection delay, lead‑time. תלוי ב‑`core/` בלבד. גם שער CI וגם הדמו של המוצר (`python -m harness`). ### `infra/` — שכבת תשתית (Stage 3, בפרוסות) **3a ✅** `infra/storage/` — אחסון: tenants, calibrations, runs (SQLite היום, ה‑`Database` ב‑`db.py` הוא ה‑seam ל‑Postgres). `infra/service.py` — `OrgStateService`, שכבת התזמור שמחברת `core` ל‑`storage`. **3b ✅** `infra/api/` — shell דק של HTTP: `handlers.py` (לוגיקה טהורה, ללא fastapi), `errors.py` (מודל שגיאות), `app.py` (חיווט FastAPI). השרשרת: FastAPI app → handlers → OrgStateService → core+storage. **3c ✅** `infra/ingestion/` — `connectors.py` (`Connector` ABC, `InMemoryConnector`, `CSVFolderConnector`, `build_connector`) + `scheduler.py` (`Schedule` נשמר, `is_due`/`due_schedules` טהורים, `IngestionService`, `run_scheduler` loop דק). connector = "מאיפה הדאטה", ה‑adapter עדיין בעל מיפוי הסכמה. **3d ✅** `infra/deployment/` — `settings.py` (`RuntimeSettings` מ‑env), `observability.py` (logging מובנה JSON), `scheduler_service.py` (entry point של ה‑worker). `Dockerfile` + `docker-compose.yml` ברמת ה‑repo — api ו‑scheduler כשני processes על image אחד שחולקים DB אחד דרך `ORGSTATE_DB_PATH`. נותר: auth/RBAC (`auth_*.py`) ו‑backend Postgres — פרוסות נפרדות דרך ה‑seam. ### `delivery/` — פלט מול לקוח (Stage 4) דוח ניהולי, תור החלטות, evidence views, דשבורדים, branded report builder, PDF export. היום ב‑`legacy/`: `customer_report_builder.py`, `executive_audit_report_builder.py`, `branded_report_builder_v31.py`, `*_dashboard*.py`, `evidence_view_builder.py`, `pdf_exporter_v28.py`. ## נתיב הנתונים (כשהמבנה יושלם) ``` מקור דאטה של לקוח → verticals/ (מיפוי סכמה → CanonicalEvent) → core (EntityState → signals Δψξγκ → Ω → drift_score → DecisionItem) → infra (persist, schedule, serve via API) → delivery (executive report, decision queue, evidence view) ``` ## החלטות מבנה מודעות - **`infra/` ולא `platform/`** — `platform` מצל על מודול stdlib בשם זה. - **`core/` ללא תלויות** — כדי שהבדיקות יהיו מהירות, ושאי אפשר יהיה "להבריח" I/O או state לתוך הליבה. - **`legacy/` נשאר רץ** — לא משברים כלום. כל שלב מהגר רכיב, מחליף את ה‑import, ומוחק את המקור מ‑`legacy/` רק כשהבדיקות ירוקות.