Files
sales-trainer/docs/HANDOFF.md

106 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HANDOFF — Sales Trainer
> Another AI should be able to resume without chat history.
## Branch / repo / deploy
- Repo: `~/Gitea/Sales Trainer/`**git repo, remote = Gitea**.
- Remote: `https://git.moreminimore.com/kunthawat/sales-trainer.git` (GITEA_TOKEN via credential
helper; never committed).
- **Live deploy:** `https://moreminimoreapps-saletrainer.ahkhwd.easypanel.host` — EasyPanel,
auto-redeploys from Gitea on push to `main` via webhook (≈3 min). Dockerfile ships prebuilt
`frontend/dist/` (no npm in image). LLM vars set in EasyPanel env.
## What this is
Corporate multi-user **sales-training simulator**: admins create persona groups from a
product/service/idea (โฟกัส "สินค้า/บริการ/ไอเดีย"), app auto-generates **15 customer personas**
(5/tier A/B/C) via LLM; trainees pick a **scenario (social / พบหน้า)**, chat 1:1 one-shot to close a
sale; a **per-turn + final judge LLM** evaluates feelings and scores/coaches. Vue SPA + Flask API +
filesystem JSON storage (no SQL). i18n TH/EN. No self-registration (admin provisions).
## Roles
- **super_admin** (bootstrap `admin`) — full recipe (secret persona fields) + tenant admin.
- **admin** — manages groups/users, sees personas with **secret fields stripped** (IP protection).
- **user** (trainee) — trains against personas, own board.
## Current state — COMPLETE core + hardened
All backend + frontend built. **11 test suites green** (mock LLM):
```bash
cd backend
uv run python scripts/test_m0.py # auth/roles/no-self-reg
uv run python scripts/test_m1.py # group create + role visibility
uv run python scripts/test_setup.py # first-time admin setup (email+password+ToS)
uv run python scripts/test_security.py # path traversal / IDOR / XSS
uv run python scripts/test_scenario.py # 2 scenarios (social/f2f_call), recontact default
uv run python scripts/test_e2e.py # full flow -> won via judge
uv run python scripts/test_ip_protection.py # secret fields hidden from admin
uv run python scripts/test_saas_tenant.py # tenant isolation + rate-limit + audit
uv run python scripts/test_user_journey.py # idea-flow end-to-end
uv run python scripts/test_variant.py # clone-persona-from-persona
uv run python scripts/test_resume_decision.py # resume + per-turn LLM decision
# run backend (serves SPA from frontend/dist)
cd backend && uv run python run.py # Flask :5001
```
## Key behaviors (implemented)
- **One-shot:** 1 persona = 1 chat per user; result final (won/lost). `SessionStore` enforces.
- **Resume:** unfinished session resumes on re-entry — **no** scenario re-pick (same session+scenario).
- **Win/loss = per-turn LLM judge** (`Simulator.evaluate_turn`): every customer reply is evaluated →
`{mood, decision(buy|walk|pending), score_delta, reason}`; session ends when decision = buy/walk.
**Not** fixed keywords.
- **2 scenarios only:** `social`, `f2f_call`. Unknown → social.
- **Recontact = persona trait** (not a scenario): chats normally, then at turn ≥ 2 a time-lapse
system note ("⏳ ผ่านไป 2-3 สัปดาห์…"), then re-engages warmer.
- **Persona variant:** `POST /api/groups/<gid>/personas/<pid>/variant` — new persona (new id) that
**locks** pains/objections/levers/tolerance/special/recontact/goal/budget/difficulty/tier/product
**but varies** identity (name/profession/age/location/background/personality/opener). Lets a
trainee re-practice the same challenge (one-shot is per-persona). UI button on finished personas.
- **Auto 15 personas** on create; no "เพิ่มเติม" button (TARGET=15, retry up to 3× + accept ≥ 8 so
real LLM under-count doesn't 500).
- **IP protection:** `SECRET_PERSONA_FIELDS` (pains, objections, negotiation_levers, opener,
tolerance, rootCause, resolutionConditions) stripped for `admin`; full only for `super_admin`.
- **SaaS Phase 13 done:** tenant isolation (`g.org_id` + `assert_tenant`), login/chat rate-limit,
audit log (`data/audit/audit.jsonl`), org plan/seats/active model + `PATCH /api/admin/orgs/<id>`,
ToS consent on setup, org-scoped signed expiring CSV export (5-min HMAC).
- **Reduce raw JSON in UI:** `list_groups` returns lightweight summary (persona_count, no full array);
persona detail rendered as readable form/cards (pain = line-by-line, not `[object Object]`).
## Credentials / data (testing)
- Bootstrap super-admin `admin` / `1234` → first login forces email + new password + ToS consent.
- Live test users: `testadmin` / `1234` (admin), `testuser` / `1234` (user).
- A test group "CRM ระบบจัดการลูกค้า" exists on live (user keeps it; will delete it themselves).
- **LLM key is a placeholder on local `.env`** (`replace_me`). Real analyze/chat needs a real
`LLM_API_KEY` (+ `LLM_PROVIDER`/`LLM_MODEL`/`LLM_BASE_URL`) in EasyPanel env then redeploy.
## Environment / gotchas
- **Python 3.11 only** (system default 3.14 incompatible). Use `backend/.venv` or
`cd backend && uv run python …`.
- **Tooling guard crash:** commands whose first token is `./.venv/bin/python` trip a lifecycle guard
→ always use `uv run python`. Prefix `PYTHONPATH=` when needed.
- **Frontend build:** `cd frontend && npm run build` (works even with allowScripts restrictions).
Commit `frontend/dist/` with `git add -f` (it's gitignored otherwise); the Dockerfile needs it.
- **Deploy pattern:** commit + push → webhook auto-deploys in ~3 min. Cannot run Docker locally
(no Docker on this Mac) → test with nginx/`python http.server` or `uv run python run.py`.
- **No remote push without asking** unless it's the established auto-deploy cadence.
- `search_files`/`read_file` sometimes misdetect files as binary (e.g. `users.py`, some `.vue`);
use `terminal` + `sed -n 'N,Mp' <file>` or `awk` for those.
## Wire-authorized / known-limits
- Chrome/Vivaldi drivable via computer-use; current model (DeepSeek V4 Flash) reads screenshots
imperfectly, and window-edge resize to a 320px viewport didn't land — **mobile visual QA at
320/500px still needs the user's eyes** (open live URL on phone, or DevTools device toolbar).
Responsive CSS (640px, single-column, `flex-wrap`, `.btn-back`) is present + deployed.
## Next actions / backlog (also docs/FUTURE_WORK.md)
- Real `/legal` page (setup links to it), billing/payments, per-tenant storage volume, compressed
persona recipe, export-token polish.
- Mobile visual polish per user feedback on real device.
- Deeper: letting admins bulk-import personas, analytics drill-down per persona variant.
## Related docs
- `docs/PLAN.md`, `docs/SAAS_PLAN.md`, `docs/FUTURE_WORK.md`.
- `docs/engineering-log.md` + `docs/engineering-log/2026-08-09-idea-flow-qa-deploy.md` (this session:
idea-flow UX, 2-scenario + recontact trait, live QA + auto-deploy, per-turn LLM judge, persona
variant, 15-persona auto-gen).