Some checks failed
Lock Threads / action (push) Has been cancelled
Frontend Lint & Test / test (push) Has been cancelled
Run Chatwoot CE spec / security-scan (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Sync GHSA advisories to Linear / sync (push) Has been cancelled
Record current session state: rebrand + M1 (per-account openai custom base URL) + M2 analytics foundation committed and pushed to Gitea. Includes the approved M2 design decisions (daily immutable snapshots, live re-tag, admin-only report, product catalog, weekly persona eval + approval flow via Line/Telegram/webhook) and the remaining M2 parts 2b-ii/iii + phases 2-3.
14 KiB
14 KiB
HANDOFF
═══════ 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
Dockerfileadded (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):
9fbb0da9bconversation_daily_metrics(per account/day; tags, deal outcomes, peak hours, agent/team/channel/inbox breakdown)0fad9ce6bcustomer_daily_metrics(per customer/day; agent_ids)161e4210bproduct_catalog_entries(per-account hierarchical product reference: group>subgroup>product+aliases)ccff2dfcalib/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>productjoined, orสินค้า:.../กลุ่ม:...). Daily metrictop_tagsaggregates 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)
- 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.
- 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).
- 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.
- 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 -csyntax + 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). - PUSHED to Gitea via SSH port 2222: branch
develop(HEADbee28c32e) now onkunthawat/moreminimore-chat. Remoteorigin=ssh://git@moreminimoreapps-gitea.ahkhwd.easypanel.host:2222/kunthawat/moreminimore-chat. HTTPS push togit.moreminimore.comis blocked by nginx 413 (client_max_body_size < ~237MB pack); SSH port 22 is NOT Gitea SSH — use 2222.upstream(github.com/chatwoot) removed; Gitea rejects shallow push, so unshallow first. SSH keymoreminimore-local-ed25519added via Gitea API. - Earlier checkpoints:
19dc449SM-07,2ef6fa5SM-07 remediation (approved deleg_087e4a3f),364e72fSM-08,8101395residual Hub removal (approved deleg_49d6ee2e + deleg_58a576e1).
Verified checkpoints
8ebb320— privacy/branding audit harness.832a7fd— Hub sync/registration/telemetry removal.1a3697f— restored only the compatibility APIs required by direct push/billing callers.8b1a033— removed the Chatwoot Hub push relay; exact post-commit independent review passed.3458272— removed cwctl telemetry from the installer; exact post-commit independent review passed.d9bf4c4— removed community signup/onboarding website-branding enrichment; split exact post-commit reviewsdeleg_5e2578c5(backend) anddeleg_ee3e217f(frontend) passed with empty blocking arrays.ced77af— SM-06 Product Analytics removal and dashboard config allowlist remediation; pre-commit reviewdeleg_f9644984and exact post-commit reviewdeleg_9b0a2f63passed with empty security/logic arrays.
Current work / uncheckpointed work
- SM-05 community signup enrichment removal is checkpointed at
d9bf4c4; pre-commit review, commit hooks, and split exact post-commit reviews passed. The enterprise service/spec remain unchanged and fail withNameError: uninitialized constant WebsiteBrandingService. This remains an explicit architecture/legal blocker; do not add a dummy service or restore remote enrichment. - SM-06 is verified at
ced77af. Its follow-up fix applies.slice(*GLOBAL_CONFIG_KEYS)before mergingapp_config, preventing stale/unrequested values such asCLOUD_ANALYTICS_TOKENfrom reaching serializedwindow.globalConfig. SM-07 local-only observability and the remaining SM-08 dashboard/config script-injection work are still uncheckpointed. The community Help Center SM-08 correction is committed as5619cc3: remove GTM remote-container execution, reject/remove legacy GTM config, and retain only fixed allow-listed provider snippets for explicit admin configuration. Exact post-commit reviewdeleg_dd3db5b7passed with empty blocking arrays. Enterprise marketing conversion tracking remains outside this community scope pending legal/compatibility review.
Evidence and blockers
- SM-03 exact post-commit review passed for
1a3697f..8b1a033; reviewer suggestions are to add explicit missing/blank/partial Firebase negative coverage and clarify legacy FCM configuration names in.env.example. - SM-04 exact post-commit review passed for
1a3697f..3458272; Bash 3.2 compatibility and fail-closed privacy-test behavior were verified. - SM-05 exact committed range
3458272..d9bf4c4passed split independent reviews: backenddeleg_5e2578c5and frontenddeleg_ee3e217f; both returned complete five-key verdicts with empty security and logic arrays. Frontend targeted run passed 9 suites/8 tests. Backend RSpec rerun is environment-blocked because Ruby 3.4.4 is required but only 3.4.10 is installed and the bundle has no usablerspecexecutable. - SM-06 exact committed range
a96b977..ced77afchanged one controller line and passed fresh pre-commit/post-commit independent review. Raw merge leaked a stubbed analytics token; the allowlist slice now removes unrequested keys before layout serialization. Committed Ruby syntax, diff check, and security scan passed. Rails RSpec/RuboCop remain blocked because the active Ruby is 2.6.10 and Bundler 2.5.16 is unavailable. - SM-08 exact post-commit review
deleg_dd3db5b7passed ford9bf4c4..5619cc3; 57 portal model/controller examples, GTM regression 3/3, Ruby/ERB syntax, RuboCop, ESLint/Prettier, Vite build and privacy-audit harness passed. Full Vitest withTZ=UTCpasses 414 files / 4176 tests, 0 failed. - No push or deploy has occurred.
- Approved product name, domains, logos/icons and sender/legal values are still missing; stop before SM-09/10.
- Full Rails/frontend suites, production-like DB checks, HTTP/DNS egress capture,
git fetch --unshallow, and upstream merge rehearsal remain outstanding. The full Vitest frontend baseline is clean underTZ=UTC: 414 files / 4176 tests passed, 0 failed (the earlier "407/15 failed" record was a non-UTC run artifact; timezone-sensitive tests all pass under UTC). - Temporary test services/configuration stay under
/tmp; never commit them or secrets.
Repository baseline
- Path:
/Users/kunthawat/Gitea/Chatwoot - Origin:
https://github.com/chatwoot/chatwoot.git - Branch:
develop - Initial baseline commit:
9a73c1473ffa0ae6a9c7725046b8ca17922dcc83 - Latest checkpoint:
ced77af(SM-06 Product Analytics plus dashboard config allowlist remediation; exact post-commit reviewdeleg_9b0a2f63passed). SM-08 Help Center remains separately verified at5619cc3. - Clone is shallow; fetch full upstream history before merge/rebase rehearsal.
Primary deliverable
.hermes/plans/2026-08-15_092534-chatwoot-private-rebrand.md- Small-model execution index:
.hermes/plans/chatwoot-private/README.md - The execution package contains
00-execution-contract.mdplus runbooks01–12with 58 uniqueSM-*tasks. Send only one task at a time and review its exact diff/test evidence before advancing.
Most important finding
DISABLE_TELEMETRY=true is not a complete opt-out. lib/chatwoot_hub.rb still posts instance_config to the Hub; it only omits instance_metrics. The corresponding behavior is asserted in spec/lib/chatwoot_hub_spec.rb.
Other unsolicited/vendor-controlled egress to remove
- Chatwoot Hub daily sync and onboarding registration
- Chatwoot Hub
/send_pushrelay fallback - Hub-hosted changelog fetch
- silent cwctl command reporting to the Hub
- automatic signup email-domain website/DNS branding enrichment
- Amplitude browser analytics
- Sentry/frontend/backend remote error reporting
- optional remote APM agents
- arbitrary dashboard scripts and remote GTM container execution
- enterprise marketing conversion tracking (proprietary/cloud-only; pending separate legal/compatibility decision)
Implementation order
- Follow dependency order in
.hermes/plans/chatwoot-private/README.md. - Establish the baseline and privacy audit harness before behavior changes.
- Remove Hub sync/registration/manual refresh, push relay, cwctl telemetry, signup-domain enrichment and remote changelog.
- Neutralize/remove analytics, remote error reporting/APM and script injection.
- Stop at the Runbook 09 input gate until approved brand values/assets are supplied.
- Add central brand defaults and replace visible assets/copy without renaming compatibility APIs.
- Run static and isolated dynamic egress gates, positive feature-traffic tests, full review and visual QA.
- Complete upstream-history and merge-rehearsal workflow; never mix upstream merge with customization commits.
User decisions required before implementation
- Product name, canonical/support/docs domains, logos/icons and email sender name
- Private Gitea repository name
- Whether to keep deprecated widget API aliases (recommended: yes)
- Whether local-only logs are sufficient or a self-hosted observability endpoint is required
- Push notification plan and own FCM/VAPID credentials
Safety/legal notes
- Root is MIT, but
enterprise/is proprietary; do not ship enterprise features without a separate license. - No remote repository was created, no files were pushed and no deployment was performed.