# LEDGER — AI Assistant Context (feed the assistant all program capabilities)

**Feature:** غذّي المساعد الذكي (Core `AiChatService`) بـ«ملخّص قدرات» مُولَّد تلقائيًا من الكود + الـCHANGELOG، فيعرف كل شاشات/فيتشرز البرنامج (القديمة والجديدة) بلا صيانة يدوية.
**Date:** 2026-07-17 · **Install:** moonui · BE+FE `hazemdev` · dev `moonui_dev_be`
**Source plan:** https://moonui.elbaset.com/his-analysis/ai-assistant-context-analysis.html (approved — ALL recommendations + WP4)
**Owner acceptance:** يفتح المساعد على أي شاشة، يسأل عن فيتشر جديد (عيادة/لويالتي) أو «فين شاشة X» → يرد صح ومحدّث ويوجّه للشاشة (لينك [نص](/route)). الملخّص مُولَّد من الكود فيفضل محدّث. المالك يقدر يضيف «معرفة إضافية» ويضغط «تحديث المعرفة» في /core/ai-settings.

## Decisions (owner approved ALL my recommendations — do NOT re-litigate)
1. مصدر خريطة الشاشات = **ملف قدرات JSON مُولَّد مشترك** (من nav-items.config الفرونت) يتقري بالباك — مصدر واحد بلا تكرار.
2. عمق الـCHANGELOG في الملخّص = **[Unreleased] + آخر نسختين** فقط (توكنز رخيصة؛ نرقّي لاحقًا لو احتجنا).
3. **كونتكست الشاشة** = نعمله (الفرونت يبعت الرَوت الحالي، الباك يحقنه).
4. الملخّص **مفلتر بصلاحيات المستخدم** (يقترح المتاح له فقط).
5. **WP4 معمول** (المالك طلبه صراحةً): حقل «معرفة إضافية» + زر «تحديث المعرفة».
6. تحديث الملخّص = **عند الديبلوي + زر يدوي** (cache versioned).
- المبدأ الحاكم (سابقة Fable): «الـAI = الواجهة؛ الكتالوج المُشتَق من الكود = المنتج» — ملخّص حتمي مُولَّد، مش نص حر. صفر PHI.

## Facts (verified — from Phase-1 explore agents)
- BE assistant: `Modules/Core/app/Services/AiChatService.php` — `getSystemPrompt()` :509 = static `config('ai.system_prompt')`; `buildMessages()` :491 = `[system, ...history, user]`. `complete()` :228 already accepts a dynamic `$systemPrompt` (precedent). Cache `AiResponseCache` keyed by `sha256(normalizeQuery(message))+company_id` — prompt-agnostic (must version).
- Endpoint `POST /api/ai/chat` (perm `core.ai.chat`, throttle `ai-chat`) — `AiChatController` + `AiChatRequest` (validates `message`,`history[]` only).
- `config/ai.php` static prompt lists only Acct/Inv/Sales/Purch/HR (missing LIS/Clinic/MFG/POS — already stale).
- `AiSetting` model has NO prompt/knowledge column. `AiSettingsService::getFormattedSettings()`.
- FE assistant: `shared/components/ai-assistant/ai-assistant.component.{ts,html}` (global via `main-layout.component.html:29`); `core/services/ai-assistant.service.ts` — **hardcoded `SYSTEM_PROMPT` :27-195 smuggled via fake history**; request body `{message,history[]}` :349; `parseContent`/`navigateTo` render `[label](/route)` as in-app nav. `features/ai-settings/*` = provider/keys/models/limits/cache (NO prompt field).
- Capability sources ranked: **nav-items.config.ts** (13 modules/121 screens/routes+perms, ~5-6k, labels are i18n keys) · **CHANGELOG** (bilingual narrative, auto-current, ~110-130k → chunk) · **PermissionCatalog.php** (Acct/Sales/Purch/Core rich) · **LisScreenCatalog.php** (LIS deep) · SettingDefinition seeders · i18n en/ar.json (label dict).

## WP table
| WP | Scope (one dense line) | Repo | Depends | Review | Migration? | Status | Commits |
|----|------------------------|------|---------|--------|-----------|--------|---------|
| WP1 | `CapabilityDigestService` (BE): build a deterministic, bilingual capability digest from a shared generated capability JSON (nav skeleton + i18n labels) + PermissionCatalog/LisScreenCatalog descriptions + a compact CHANGELOG "what's new" summary (**folds WP5**: [Unreleased]+last 2 versions, token-bounded); cache it versioned; filterable by user permissions. Pest. | BE | — | Codex/native | no | ✅ done | BE `5771755ed` — `CapabilityDigestService` (build/whatsNew/version/cached/refresh) + generated `capability-map.json` (13 mods/122 routes) + `gen-capability-map.mjs` + `config/ai.php` digest block. Digest ~11.7k AR/12.6k EN chars (<32k cap). LIS enriched from LisScreenCatalog (48), clinic/nphies/einvoicing from PermissionCatalog. **Native review APPROVE.** 9 new tests + 27 baseline green. |
| WP2 | Wire digest into `AiChatService`: `getSystemPrompt()`/`buildMessages()` dynamic (company+locale+user perms+page); **version the AiResponseCache key** (prompt-version + page) so contexts don't collide; keep `config/ai.php` as the framing template. Pest. | BE | WP1 | Codex/native | no | ✅ done | BE `132f599e0` — `getSystemPrompt(User,locale,?page)`/`buildMessages`/`chat` dynamic (wrapper + digest.cached + page line). Cache `query_hash=sha256(msg|version|permTag|pageTag)`, symmetric read/write, **same `resolveUserPermissions` for digest filter AND cache tag** → scope-consistent. **Native review APPROVE** (cross-scope no-leak test). No migration; `complete()` untouched. 41 passed (baseline 36). |
| WP3 | FE unify: remove the smuggled `SYSTEM_PROMPT` + fake-history from `ai-assistant.service.ts`; send current route/screen as page-context in the `/ai/chat` payload; BE (`AiChatRequest`+controller) accepts + injects "user is on screen X". ng build. | FE+BE | WP2 | Codex/native | no | ✅ done | FE `c6b5977` + BE `92aecf6a8` — removed hardcoded `SYSTEM_PROMPT`+fake-history (0 hits); FE sends `page={route,label}` (nav-matched, active-locale); BE validates (nullable max:200) + `pageContext()` locale-aware line → `chat()` 4th arg → WP2 cache pageTag. **Native APPROVE.** 34 passed + ng build EXIT=0. **CHANGELOG bullet added** (assistant knows real screens + page-aware; bilingual OK). |
| WP4 | Owner "extra knowledge" free-text field + "Refresh knowledge" button in `/core/ai-settings`; stored per-company (AiSetting new column → migration); appended to the digest; refresh rebuilds/clears the cached digest. Pest + ng build. | FE+BE | WP2 | Codex/native | **yes** (AiSetting column) | ✅ done | BE `882c9636c` + FE `e3e6200` — migration `2026_07_17_100000_add_custom_knowledge_to_ai_settings_table` (ran on dev, custom_knowledge EXISTS), model/service/resource/request (max:4000), `CapabilityDigestService::customKnowledge()`+notes section (company-scoped, folded into `version()` → no cross-company leak since response cache is company-keyed), `POST /ai/knowledge/refresh`. FE knowledge textarea + refresh button + 6 i18n keys. **Native APPROVE.** 51 passed + ng build green. CHANGELOG bullet added. |
| ~~WP5~~ | **FOLDED into WP1** (2026-07-17): CHANGELOG compaction is a thin internal helper of the digest — merging removes a needless BE serialization hop. Not scope change (my own decomposition). | — | — | — | — | ➖ merged→WP1 | |

## DAG / serialization
- WP1 FIRST (BE). WP2 depends WP1 (BE). WP3 & WP4 depend WP2 and both touch BE+FE — **serialize** (one writer per repo; do WP3 then WP4). Order: **WP1 → WP2 → WP3 → WP4**.
- ⛔ one writer per repo at a time — never two sub-agents in the same working tree concurrently.

## Baseline (2026-07-17)
- BE AI suite: **27 passed, 0 failures** (`AiChatApiTest`, `AiChatServiceTest`, `AiSettingApiTest`, `AiSettingsServiceTest`). No pre-existing failures in scope.
- FE `ng build`: green (built during today's /fullpush; bundle `main-HZZIWGCQ.js`).

## Deferrals / open items
- (empty)
