# Kālāma recommendation demo — operator guide / Hướng dẫn sử dụng

This is the operator guide for the staff-assisted recommendation demo. It is a
development and classroom tool, not a production ordering system.

Đây là hướng dẫn sử dụng cho bản demo gợi ý món có nhân viên hỗ trợ. Đây là công cụ
phát triển và dùng trong lớp học, không phải hệ thống đặt món thật.

The shared model rules are a separate document (`/api/rules`, `shared-rules.md`).
They are not this guide. / Bộ quy tắc chung cho mô hình là tài liệu riêng
(`/api/rules`, `shared-rules.md`), không phải hướng dẫn này.

---

## Tiếng Việt

### 1. Trước khi bắt đầu

- **Thực đơn:** phần *Thiết lập và bằng chứng* phải hiện thực đơn đã nhập với trạng thái nguồn
  đã xác nhận. Thực đơn chưa xác nhận thì không gợi ý được. Thực đơn hiện tại là **tập con có
  giới hạn** (20 trong 94 dòng đã ghi), **không phải toàn bộ menu**. **Nguồn** đã được Co-Founder
  xác nhận ngày 2026-10-20, nhưng **giá từng món là do hệ thống ghi lại**: giá đồ uống đọc từ ảnh
  menu chị gửi, còn **giá bánh là suy ra từ vị trí sticker** trên sổ bánh, chị chưa nói thành lời.
  Vì vậy **các món bánh chưa nên dùng làm đáp án chuẩn** cho tới khi chị xác nhận bốn mức giá; đánh
  giá chỉ dùng đồ uống thì có thể tiến hành.
- **Đăng nhập nhân viên:** cần mật khẩu nhân viên do quản trị viên cấu hình trên máy chủ.
  Nếu chưa cấu hình, ứng dụng khoá mọi thao tác ghi.
- **Nhà cung cấp AI:** phải có ít nhất một nhà cung cấp *đã cấu hình* **và** có *chính
  sách ngân sách đã được người vận hành phê duyệt*. Hai điều kiện này khác nhau và được
  hiển thị riêng. Ứng dụng chỉ ghi nhận **cam kết** của người vận hành (đúng gateway,
  đúng hạn mức), và **không tự kiểm chứng** hạn mức đó có thực sự được thực thi: trường
  `spend_ceiling_enforcement_verified` luôn là `false`. Khi chưa có phê duyệt đó, gọi
  trả phí bị chặn.
- Phần **Sẵn sàng** ở đầu trang liệt kê đúng những việc còn thiếu.

### 2. Chế độ chạy

- **Gợi ý cho nhân viên (một nhà cung cấp)** — mặc định. Gửi yêu cầu tới một nhà cung cấp,
  nên nhà cung cấp còn lại vắng mặt hoặc lỗi không chặn được kết quả.
- **So sánh (cả hai nhà cung cấp)** — dành cho bài tập trên lớp. Cùng yêu cầu, cùng thực
  đơn, cùng chính sách cho cả hai; báo cáo riêng, **không gộp thành một người thắng**.

### 3. Phạm vi đơn

- **Có ít nhất một đồ uống và một món ăn kèm** — đơn phải có mặt cả hai nhóm.
- **Chỉ đồ uống (không món ăn kèm)** — nghiêm ngặt: nếu mô hình trả về món ăn kèm, cả đơn
  bị từ chối, không tự động bỏ món.
- **Mọi tổ hợp món có trong thực đơn** — không ràng buộc nhóm.

### 4. Ràng buộc và câu hỏi tiếp theo

- Các **ô điều khiển là căn cứ chính thức**. Câu chữ trong ô yêu cầu **không** làm thay đổi
  chúng.
- **Giới hạn đã biết:** ứng dụng chỉ so sánh các ô điều khiển. Nó **không đọc được câu chữ**
  và **không** tự phát hiện câu văn mâu thuẫn với ô điều khiển.
- Vì vậy **mỗi câu hỏi tiếp theo đều cần bạn xác nhận** trước khi gửi. Màn hình xác nhận
  liệt kê ràng buộc hiệu lực; nếu câu chữ của bạn muốn đổi ràng buộc (ví dụ "đổi sang không
  sữa"), hãy **cập nhật ô điều khiển trước**, rồi xác nhận.
- **Ràng buộc cho cả đơn, không theo từng người.** Ứng dụng **không** có cơ chế gán ràng
  buộc riêng cho từng người. Yêu cầu trộn nhiều người có nhu cầu khác nhau (một người cần
  ít caffeine, một người không) sẽ **không được tự động diễn giải**: hãy hỏi lại khách và
  gửi một ràng buộc chung cho cả đơn. Nếu bạn áp ràng buộc chặt nhất cho cả đơn, đó là lựa
  chọn của bạn, có thể loại bỏ một đơn lẽ ra hợp lệ; ứng dụng không tự làm điều đó và không
  coi đó là xử lý theo từng người.
- Ngân sách là **số nguyên VND cho cả đơn**. Ứng dụng tính tiền từ thực đơn, không tin số
  tổng do mô hình trả về, và **không tự nới ngân sách**.

### 5. Đọc kết quả

- Kết quả ghi rõ **nhà cung cấp, mô hình, tuyến (route), chế độ truy xuất và ngôn ngữ trả lời**.
- **Chưa xác nhận** không có nghĩa là an toàn: thuộc tính ăn uống chưa biết vẫn là **chưa
  biết** và cần nhân viên kiểm tra. Đây không phải tư vấn dị ứng.
- Nhãn **Không đậu phộng và hạt cây** chỉ nói về đậu phộng và hạt cây trong nguyên liệu đã
  được xác nhận; không bao gồm mọi loại hạt và không phải bảo đảm an toàn dị ứng.
- Giá là **giá niêm yết trong thực đơn**, chưa gồm thuế, phí hay khuyến mãi.

### 6. Ghi quyết định của nhân viên và xuất bằng chứng

- Chọn một kết quả, rồi ghi **Chấp nhận / Chấp nhận kèm chỉnh sửa / Từ chối**, kèm lý do
  ngắn không bắt buộc.
- Quyết định được **gắn với đúng yêu cầu và đúng kết quả gốc** (theo mã lượt chạy, nhà cung
  cấp, số lượt), nên không bị gắn nhầm sang kết quả sau. Kết quả gốc được lưu **tách biệt**
  với ghi chú của nhân viên.
- Đây là **đánh giá của nhân viên**, không phải kết quả đã được kiểm chứng độc lập.
- Nút **Tải quyết định của nhân viên** xuất một tệp JSON. Ghi chú của nhân viên do người
  nhập nên **không bảo đảm không có thông tin cá nhân**: hãy **kiểm tra tệp trước khi chia sẻ**.

### 7. Cảnh báo mất dữ liệu phiên

**Hội thoại, kết quả và quyết định của nhân viên chỉ nằm trong bộ nhớ trang.** Tải lại
trang, đóng tab hoặc đổi thực đơn sẽ **xoá sạch** chúng. Hãy xuất bằng chứng trước khi tải
lại. Bấm **Phiên mới** cũng xoá phiên hiện tại.

### 8. Ngôn ngữ

Nút **Tiếng Việt / English** đổi ngôn ngữ giao diện. Yêu cầu đã nhập, ràng buộc, kết quả gốc
và quyết định của nhân viên **được giữ nguyên**. Kết quả đã nhận **không bị dịch lại hay
dán nhãn lại**: văn bản mô hình trả về giữ đúng ngôn ngữ gốc. Ngôn ngữ trả lời của các yêu
cầu **về sau** đi theo ngôn ngữ giao diện đang chọn.

---

## English

### 1. Before you start

- **Menu:** the *Setup and evidence* area must show an imported menu whose source is marked
  confirmed. An unconfirmed menu cannot produce a recommendation. The current menu is a **bounded
  subset** (20 of 94 transcribed rows), **not the full menu**. Its **source** was confirmed by the
  Co-Founder on 2026-10-20, but **item prices are as recorded by the system**: drink prices were
  transcribed from the menu photo she sent, and **snack prices are inferred from sticker position**
  on the stock sheet — she never stated them in words. So **snack items should not be used as
  definitive answer keys** until she confirms the four values; a drink-only evaluation can proceed.
- **Staff sign-in:** requires the staff passphrase an administrator configured on the server.
  If it is not configured, the app blocks every write action.
- **AI provider:** at least one provider must be *configured* **and** have an *operator-approved
  budget policy*. Those are different conditions and are shown separately. The app records an
  operator **assertion** (correct gateway, stated amount) and does **not** verify that the limit
  is actually enforced: `spend_ceiling_enforcement_verified` is always `false`. Without that
  approval, paid calls stay blocked.
- The **Readiness** list at the top of the page names exactly what is still missing.

### 2. Run mode

- **Staff recommendation (one provider)** — the default. Sends the brief to one provider, so
  an absent or failing second provider cannot block the result.
- **Comparison (both providers)** — for the classroom exercise. Same brief, menu and policy
  for both; reported separately with **no merged winner**.

### 3. Order scope

- **At least one drink and one snack** — the order must include both categories.
- **Drinks only (no snack)** — strict: if the model returns a snack, the whole order is
  rejected rather than silently dropping the item.
- **Any listed item combination** — no category constraint.

### 4. Constraints and follow-ups

- The **controls are authoritative**. Wording in the request box does **not** change them.
- **Known limitation:** the app compares controls only. It **cannot read your wording** and
  does **not** detect a sentence that contradicts a control.
- Therefore **every follow-up needs your confirmation** before it is sent. The confirmation
  panel lists the effective constraints; if your wording is meant to change a constraint (for
  example "make it dairy-free"), **update the control first**, then confirm.
- **Whole-order restrictions, not per-person.** The app has **no** mechanism for assigning a
  constraint to an individual. A mixed request with different needs (one person caffeine-free,
  another not) is **not interpreted automatically**: ask the customer again and send one shared
  constraint for the whole order. If you choose to apply the strictest reading to the whole
  order, that is your choice and it may rule out an order that was actually valid; the app does
  not do it for you, and it is not per-person handling.
- Budget is an **integer VND amount for the whole order**. The app computes money from the
  menu, never trusts a model-reported total, and **never relaxes the budget silently**.

### 5. Reading a result

- Each result states its **provider, model, route, retrieval mode and answer language**.
- **Unconfirmed is not safe:** an unknown dietary attribute stays **unknown** and needs staff
  to check. This is not allergen advice.
- The **No peanuts or tree nuts** label covers peanuts and tree nuts in confirmed ingredients
  only; it does not cover every seed or nut and is not an allergy safety guarantee.
- Prices are the **listed menu prices**, excluding tax, fees or promotions.

### 6. Staff decisions and evidence export

- Select a result, then record **Accept / Accept with edits / Reject**, with an optional short
  reason.
- A decision is **bound to the exact request and the exact original result** (run id, provider,
  turn), so it cannot drift onto a later result. The original result is stored **separately**
  from the staff notes.
- This is a **staff evaluation**, not independently reviewed benchmark truth.
- **Download staff decisions** writes a JSON file. Staff notes are typed by staff and are
  **not guaranteed PII-free**: **check the file before sharing it**.

### 7. Session-loss warning

**Conversation, results and staff decisions live only in this page's memory.** Reloading the
page, closing the tab or changing the menu **discards them**. Export evidence before
reloading. **New session** also discards the current session.

### 8. Language

The **Tiếng Việt / English** switch changes the interface language. Your entered request,
constraints, original results and staff decisions are **preserved**. Results already received
are **not retranslated or relabelled**: model text keeps its original language. The answer
language for **future** requests follows the currently selected interface language.
