Files
sales-trainer/docs/engineering-log/2026-08-07-build-out.md

4.0 KiB
Raw Permalink Blame History

2026-08-07 — Sales Trainer build-out (M0M7)

Summary

Built the first complete version of the Sales Trainer app — corporate multi-user sales-training simulator — in ~/Gitea/Sales Trainer from the detailed plan in docs/PLAN.md (which records all user decisions from the planning discussion).

Plan status

  • M0M7 all complete (see engineering-log.md status table).

What was built

Backend (Flask + JWT + filesystem JSON):

  • app/config.py (env/.env, LLM resolve), app/llm.py (OpenAI-compatible client + JSON/conv helpers)
  • app/storage/store.py (durable JSON store, lock + atomic write)
  • app/auth/users.py (UserStore: password hash, JWT, roles, no self-reg bootstrap)
  • app/services/: file_parser (pdf/txt/md), analyzer (sales kit + initial pain-fit), persona_prompts + persona_generator (15 personas, 5/tier, wrong_text special), store (persona shape + revealable_view), report, groups, sessions, simulator (chat + judge), trainee (weak-areas, MyPersonaStore), own_persona
  • app/api/: auth, admin, groups, chat, me, analytics routes + JWT/RBAC helpers
  • app/factory.py: app factory, bootstrap admin, serves built Vue frontend (SPA fallback)
  • run.py entry

Frontend (Vue 3 + Vite): login, dashboard (role-based), group builder, group edit (admin) , personas (trainee revealable-only + win/lose), chat (FB/LINE thread + seller-task + debrief overlay), my-sessions, weak-areas, gen-persona, admin users, analytics. EN+TH i18n.

Verified commands / results

backend:  uv venv --python 3.11 .venv
          uv pip install -r requirements.txt --python .venv/bin/python
          uv run python scripts/test_m0.py        -> ALL M0 TESTS PASSED
          uv run python scripts/test_m1.py        -> ALL M1/M2-IMPORT TESTS PASSED
          uv run python scripts/test_routes.py    -> ALL ROUTE REGISTRATION TESTS PASSED
          uv run python scripts/test_e2e.py       -> ALL E2E TESTS PASSED
frontend: npm install && npm run build            -> builds 11 route-split chunks (423ms)
live HTTP (Flask dev on :5001):
          GET /  -> 200 (SPA)
          POST /api/auth/register -> 404 (no self-reg)
          POST /api/auth/login -> 200 (JWT)
          POST /api/groups -> 201 (draft group)

Mock-LLM E2E covers: analyze→15 personas (+wrong_text)→revealable-only→customer/seller-initiated sessions→debrief(latent reveal+coaching)→one-shot→board→weak-areas→gen-persona→analytics.

Engineering notes / issues

  1. Tooling: the Hermes terminal life-cycle guard crashes ("embedded null byte") on direct .venv/bin/python <script> invocation. Workaround: run scripts via uv run python scripts/x.py.
  2. Static serving path: initially pointed at backend/frontend/dist (wrong) → GET / 404. Fixed to repo-root frontend/dist, and made the SPA fallback accept all HTTP methods so /api/* returns 404 (not 405), preserving no-self-registration.
  3. Mock vs real LLM: tests use scripts/mock_llm.py (deterministic). Real model path requires a live LLM_API_KEY in .env — NOT yet exercised live.

Current state / runtime

  • Backend runs via cd backend && uv run python run.py; frontend dev via cd frontend && npm run dev (proxies /api -> :5001).
  • Default super-admin: admin / 1234 (bootstrap; forces email + password change on first login).
  • Deploy files: root Dockerfile, docker-compose.yml, .env.example; repo-root frontend/dist build.

Risks / remaining

  • Real-LLM end-to-end not verified (needs a live key). Next: run analyze + persona + chat + judge against the configured provider (DeepSeek/OpenAI/custom).
  • Docker build not run locally (no Docker on this Mac — per environment note). Dockerfile follows the EasyPanel single-container pattern; remote build+run should be validated on EasyPanel.

Next action

  1. Set a real LLM_API_KEY (and provider) in .env, run a live smoke test of analyze→personas→chat→debrief.
  2. Push to Gitea remote (repo currently local git, no remote yet).
  3. Validate Docker image build on EasyPanel.