# WP4 — Owner "extra knowledge" field + "Refresh knowledge" button

## Goal
Let the program owner add free-text custom notes that the assistant will know (appended to the generated digest), and give a "Refresh knowledge" button that rebuilds the cached digest on demand. Owner-requested (Decision 5).

## Context
- BE `/home/moonui/moon-erp-be` (branch `hazemdev`, Pest sqlite, dev DB `moonui_dev_be` — run the migration same-step, ⛔ never fresh/wipe). FE `/home/moonui/public_html/moon-erp` (branch `hazemdev`, `ng build` green).
- AI settings today:
  - BE model `Modules/Core/app/Models/AiSetting.php` (`$fillable`: providers, keys, models, limits, cache flags, `is_enabled` — **NO prompt/knowledge column**). Service `AiSettingsService.php` (`getFormattedSettings()`). Controller `AiSettingController.php`. Routes `Modules/Core/routes/ai.php` (`GET/PUT /ai/settings`, guarded `permission:core.ai...`).
  - FE screen `src/app/features/ai-settings/ai-settings.component.{ts,html}` (tabs: Settings, Preferences, Usage, My Usage), service `src/app/core/services/ai-settings.service.ts` (`AiSettings` interface, `GET/PUT /ai/settings`). No prompt/knowledge field anywhere.
- `CapabilityDigestService` (WP1) exposes `refresh(): void` (clear cached digest) and `build()`; WP2 appends context into the system prompt.

## Deliverables
### Backend (migration + wiring)
1. **Migration** (timestamp AFTER all existing): add nullable `custom_knowledge` (TEXT) to the `ai_settings` table (per company). Run it on `moonui_dev_be` in the same step (`php artisan migrate --force`).
2. `AiSetting` model: add `custom_knowledge` to `$fillable`. `AiSettingsService` + `AiSettingController` + `AiSettingRequest` (if present): accept/return/validate it (nullable string, cap e.g. ≤ 4000 chars so it can't blow the token budget).
3. `CapabilityDigestService::build()` (or the WP2 assembly): **append** the company's `custom_knowledge` (if any) to the digest under a clearly-labelled "Lab/company notes" section — and include it in `version()` so editing it busts the cache.
4. **Refresh endpoint:** `POST /ai/knowledge/refresh` (guard `permission:core.ai.settings...` — same as settings-manage) that calls `CapabilityDigestService::refresh()` (clears the cached digest so the next chat rebuilds it). Returns `{ ok: true, version }`.

### Frontend
5. In the **Settings** tab of `ai-settings.component`: add an "Assistant knowledge" card — a textarea bound to `custom_knowledge` (saved via the existing `PUT /ai/settings`), with a short helper ("The assistant already knows all screens automatically; add lab-specific notes here"). Add a **"Refresh knowledge"** button calling the new `POST /ai/knowledge/refresh` with a success toast. i18n keys in `en.json`/`ar.json` (English-first).

## Acceptance criteria
- [ ] Owner can type notes in `/core/ai-settings` → Settings, save, reload → persisted (per company).
- [ ] The saved notes appear appended to the digest (Pest: build() includes the custom text; editing it changes `version()`).
- [ ] "Refresh knowledge" clears the cached digest (Pest/feature: cache miss → rebuild after refresh).
- [ ] `custom_knowledge` is length-capped and nullable; migration applied on dev; existing rows unaffected (null default).
- [ ] `ng build` green; existing AI tests green; new field validated.

## Tests
- BE: extend `AiSettingApiTest`/`AiSettingsServiceTest` (save/read/validate `custom_knowledge`) + a digest test (custom text appended + version change) + refresh endpoint. Migration runs clean on sqlite (test) and dev.
- FE: `ng build` green.

## Flags
- **migration: yes** (`ai_settings.custom_knowledge`) — new timestamp, run on dev same-step, ⛔ never fresh/wipe. No [FIN].

## Out of scope
- Changing the generated digest sources (WP1) or the chat wiring (WP2) beyond appending custom_knowledge.
