diff --git a/HANDOFF.md b/HANDOFF.md index 7e8f641f0..c0ea1c998 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,7 +1,48 @@ # HANDOFF -## Current state -Rebrand implementation is in `/Users/kunthawat/Gitea/Chatwoot`; committed and pushed to Gitea (branch `develop`). +## ═══════ SESSION 2026-08-19 — Moreminimore Chat: rebrand + M1 + M2 work ═══════ + +## Current state (2026-08-19) +Repo `/Users/kunthawat/Gitea/Chatwoot`, branch `develop`, **pushed to Gitea**. +Remote origin = `ssh://git@moreminimoreapps-gitea.ahkhwd.easypanel.host:2222/kunthawat/moreminimore-chat` (NOT github). +SSH push via port **2222** (the HTTPS path git.moreminimore.com gets nginx 413; SSH port 22 is not Gitea SSH). +HEAD = `ccff2dfca`. Worktree clean except untracked `.hermes/plans/` (never commit). + +### Completed this session (all through independent five-key reviews, deployed by user) +- **Rebrand → Moreminimore Chat** complete (phases 1-3 + Dockerfile + brand DB fix): f17ce89, d925ab1, 18e6fc28a, bee28c32e, d77d60443, 4b35130ae. +- **Docker/build**: root `Dockerfile` added (4b35130ae) so EasyPanel 'Dockerfile' builder works instead of Nixpacks rbenv stack. nixpacks.toml added then removed (wrong approach). +- **M1 — per-account OpenAI custom base URL** (the /app/accounts/{id}/settings/integrations/openai page): commit f9628db0e. Adds optional custom OpenAI-compatible base_url per account (apps.yml schema+form, llm_base_service api_base priority hook.base_url→CAPTAIN_OPEN_AI_ENDPOINT→api.openai.com, key_validator base_url kwarg, hook https validation). NOTE: an earlier wrong-scope Captain-level provider switch (46fe70398) was reverted (961ecd388) — the Captain CAPTAIN_OPEN_AI_ENDPOINT already supports custom URL as original behavior, so no change needed there. +- **M2 — analytics foundation** (self-improving chatbot, admin-only): + - 9fbb0da9b `conversation_daily_metrics` (per account/day; tags, deal outcomes, peak hours, agent/team/channel/inbox breakdown) + - 0fad9ce6b `customer_daily_metrics` (per customer/day; agent_ids) + - 161e4210b `product_catalog_entries` (per-account hierarchical product reference: group>subgroup>product+aliases) + - ccff2dfca `lib/llm/resolver.rb` (LLM cascade: per-account openai hook → Captain → nil; https-only api_base) +- **DB brand fix** done by user on prod (login no longer shows Chatwoot / logo loads). + +### M2 design decisions (approved by user — IMPORTANT for remaining work) +- Analyze EVERY chat of EVERY account daily (high LLM cost accepted — selling point is self-improving chatbot). +- LLM cascade: per-account openai → fallback Captain config → if neither, feature disabled (LLM integration effectively always on unless Captain unset). +- Use Chatwoot's ORIGINAL conversation tags (ActsAsTaggableOn tag_list) — do NOT add many tag fields. Product/sale tag goes into the same tag list, prefixed (e.g. lines like `group>subgroup>product` joined, or `สินค้า:...`/`กลุ่ม:...`). Daily metric `top_tags` aggregates from these. +- **No `tagged_at`** (user decided to skip time-tracking to avoid DB complexity). +- Per-day stats are IMMUTABLE snapshots; conversation live tags get re-tagged on later analysis (e.g. session now about product B → product A tag removed). The daily snapshot preserves the earlier state. +- Report page **admin-role ONLY** (agent must NOT see deep analytics). Filter by agent/team/inbox/channel/tag/sale-tag/time + cross-analysis. Break down per CUSTOMER and per AGENT. +- Weekly (Mon 10:00) LLM summarizes 7 days → persona improvement recommendation (summary only, NOT full prompt). Delivered via preferred channel: Line (has quick-replies) / Telegram (inline keyboard) / webhook (3rd party). Admin chooses approve / view-full-prompt / reject; viewing full prompt → re-approve; on approve → webhook with prompt (admin sets URL+secret). +- Product list: per-account, admin-only menu (like report), import via copy/paste or CSV/XLSX. Multi-level hierarchy (big group>subgroup>product>display) — LLM matches from lowest level first, tags ancestors; supports multiple products/groups per chat. + +### NEXT TO DO (M2 remaining — biggest remaining work) +1. **part2b-ii**: LLM classifier service — read conversation (latest message + history for context), classify → tags (topic + product from catalog using '>' join) + deal (won/lost/undecided). Cascade via Llm::Resolver. +2. **part2b-iii**: daily batch job (sidekiq-cron) at ~02:00-03:00 in the SUPER ADMIN timezone (single TZ, no hourly-check) → auto-write tags to conversation, aggregate into conversation_daily_metrics + customer_daily_metrics (immutable counts; re-tag live). +3. **phase 2**: monthly/yearly rollup (sum daily) + admin-only report dashboard (filters agent/team/inbox/channel/tag/sale/time, cross-analysis) + deep per-customer/per-agent views. +4. **phase 3**: product-list import UI (admin-only, copy/paste + CSV + XLSX), weekly persona eval + approval flow (Telegram inline button, Line quick-reply, webhook) + docs. + +### Verification notes / blockers +- Ruby env active is 2.6.10; target 3.4.4. Rails/RSpec/RuboCop cannot be reliably claimed passed. Ruby `ruby -c` syntax + YAML validity + isolated smoke tests used instead. +- Full Vitest baseline is clean under TZ=UTC: 414 files / 4176 tests, 0 failed. +- Enterprise (EE) files still read CAPTAIN_OPEN_AI_ENDPOINT directly and won't honor per-account base_url gating — intentional (out of OSS scope), note as follow-up. +- No secrets committed. Temporary test helpers under /tmp only. + +## ───────── historical (2026-08-16, before this session) ───────── + ### Latest handoff — 2026-08-16 (updated after rebrand + push) - Rebrand to **Moreminimore Chat** complete across all phases (committed): `f17ce89` (phase 1 configurable brand core: logo/config/mailer defaults/views), `d925ab1` (phase 2a cleanup + 512px thumbnail), `18e6fc28a` (phase 2b color theme: black #333333 primary + Moreminimore yellow #FED400 accent), `bee28c32e` (phase 3 visible surfaces: app.json + mailers + 56 locales + prompts). All phases passed independent five-key reviews (deleg_a733cdf4, deleg_37455fbd, deleg_9b054593, deleg_892d115f).