| name | advisor-maintenance |
| description | How to safely change the WhatsApp advisor's (მრჩეველი) behaviour — the constitution/glossary prompt layers, code guards, flags, tests, and the release checklist. Use whenever editing tools/core/advisor_constitution.py, advisor_glossary.py, the advisor prompts in whatsapp_assistant.py, or rolling out an ASSISTANT_* flag. |
Advisor (მრჩეველი) Maintenance
The advisor is a LIVE student-facing bot in the course WhatsApp groups. Its
behaviour is governed by layered, versioned rules — change them here, never by
ad-hoc prompt edits scattered in whatsapp_assistant.py.
The layers (what goes where)
| Layer | File | Use for |
|---|
| Constitution | tools/core/advisor_constitution.py | Durable behaviour rules: trigger/restraint policy, grounding, context comprehension, pedagogy, appropriateness, canonical self-description, humor gating. Versioned (CONSTITUTION_VERSION). |
| Glossary | tools/core/advisor_glossary.py | STABLE product facts the bot must copy verbatim (identities, vendors, canonical commands). Never volatile facts (prices, limits, versions). |
| Code guards | whatsapp_assistant.py + server.py | Deterministic enforcement: per-chat lock, idMessage dedup, output script sanitizer, URL-fetch-failed note, own-reply history. |
| Agentic tools | tools/services/advisor_tools.py + advisor_agentic_loop.py | Read-only tools for the bounded reasoning loop. group/user/mode are ALWAYS server-bound via closure — never model args. |
| Flags | Railway env (ASSISTANT_*) | Rollout/kill switches. New risky behaviour defaults OFF in code. |
Prompt assembly: reasoner = base role + reasoner_trigger_instruction() +
reasoner_core_rules() + glossary_block() + capability block; writer = base
rules + writer_core_rules() + glossary_block(). Both live in
_decide_and_reason / _write_response.
Adding or changing a rule — checklist
- Edit the named constant in
advisor_constitution.py (or add a section and
include it in reasoner_core_rules() / writer_core_rules()).
- Bump
CONSTITUTION_VERSION.
- Add/adjust a rule-presence test in
tools/tests/test_advisor_constitution.py
— every rule earned its place from a real production failure; the test
pins it.
- Run:
py -3.12 -m pytest tools/tests/test_advisor_constitution.py tools/tests/test_whatsapp_assistant.py -q and ruff check.
- PR → operator merges (agent cannot self-merge without explicit user auth).
Hard-won traps (do not relearn these)
- Never edit
server.py or whatsapp_assistant.py with the Edit tool —
the formatter hook reformats the whole file (~500-line churn). Patch via an
anchored Python script (assert count(anchor) before replacing; expect some
anchors to appear in BOTH the live and catch-up send paths — cover both).
- Never deploy or merge during a lecture (Mon/Tue/Thu/Fri 20:00–22:00
Tbilisi ± the 18:00 reminder). A mid-pipeline restart strands recordings.
- The 2
TestWhatsAppExtendedTextMessage failures in full-suite order are
PRE-EXISTING cross-file pollution (reproduce on clean main) — not yours.
railway variables --set sometimes does NOT auto-redeploy — verify a new
deployment id appears; if not, the operator runs railway redeploy -y.
- After enabling a webhook-affecting flag,
POST /admin/whatsapp-webhook-repair
reboots the Green API instance and can stall the WhatsApp session while
still reporting authorized — confirm messages actually flow afterwards.
- Flags the classifier treats as prod changes must be set BY the operator
(named explicitly or run via
!).
Flag rollout order (memory/agentic)
One at a time, verify cost/latency between steps:
ASSISTANT_PERSIST_OUTGOING (ON since 2026-07-10) → ASSISTANT_MEMORY_ASSEMBLER
→ ASSISTANT_STUDENT_PROFILE → ASSISTANT_AGENTIC_LOOP → retrieval flags.
Kill switches: ASSISTANT_RESTRAINED_MODE=0 (restraint), ASSISTANT_HUMOR=0
(humor), ASSISTANT_AGENTIC_LOOP=0 (loop) — env-only, instant after redeploy.
Behaviour evals (before enabling something student-visible)
Replay the golden failure set from 2026-07-08..10 against the new prompts
(transcripts in the ops session scratchpad / memory): the Razer 3-GPU link,
Antigravity "easter egg", the claude-cli package invention, Vladimer's
empty quote-reply, the "დაშოშმინდი" over-participation evening. The right
outcomes: silence, grounded uncertainty, or the glossary fact — never a guess.