Files
sales-trainer/docs/HANDOFF.md

6.8 KiB
Raw Blame History

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):

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.
  • 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).