# LEARNINGS.md

## ⛔ NEVER post screenshots or images in Discord channels. Ever. No exceptions. - Categorized Rules
*Read on boot. Append after failures. Categorized: 2026-03-05*

## 🖼️ IMAGE GENERATION (nano-banana-pro)
- **NEVER double-post images.** The generate_image.py script outputs a `MEDIA:` line that OpenClaw auto-attaches. If you ALSO call `message` tool with `media=`, the image posts twice. Pick ONE method: either suppress `MEDIA:` output (`2>/dev/null` won't help — pipe stdout through grep -v MEDIA or redirect) OR don't pass `media=` to the message tool. Assaf has asked to stop this repeatedly. (2026-03-16)
- **Correct pattern:** Run script with `| grep -v "^MEDIA:"` to suppress auto-attach, then send manually with `message` tool + `media=` for full control of the message text.

## 📁 FILE MANAGEMENT
- **Check for uniqueness before archiving scripts.** Don't blindly move entire directories to legacy/. Verify each file is actually a duplicate before removing it. utils/ had 60 unique scripts that were incorrectly archived. (2026-03-09)

## 🚫 ABSOLUTE BANS
- **NEVER publish to etoro.curiousendeavor.com.** That domain is eToro's live/staging environment. Kitt does NOT deploy there. Ever. Use staging.curiousendeavor.com for any staging work. (2026-03-26)
- **eToro server = Kittoro's domain.** Kitt does NOT respond in the eToro Discord guild unless Assaf directly addresses Kitt by name. Kittoro leads all eToro team conversations. Kitt stays in CE. (2026-03-25)
- **NEVER use the `browser` tool for screenshots.** It posts images into Discord channels. Use `web_fetch` + `read` (source files) to analyze websites. No exceptions. Assaf has asked repeatedly — this is a hard ban. (2026-03-06)
- **NEVER take screenshots unless explicitly asked.** No `playwright screenshot`, no `browser snapshot`, no automatic visual verification. Assaf doesn't want screenshots of work unless he specifically requests them. Hard ban. (2026-03-08)
- **ALWAYS post generated images directly to the channel as image attachments.** Never just report filenames/paths — Assaf needs to SEE the images inline. Use `message` with `filePath` to send each image. No screenshots, always the actual image files. (2026-03-07)
- **EMAIL BAN: NEVER send any emails without Assaf's explicit approval first.** No outbound emails to anyone. Draft → get approval → THEN send. (2026-03-09: Generated 6 email drafts instead of getting it right the first time. Efficiency failure.)

## 🚨 BUSYWORK BAN (March 7, 2026)
- **NEVER generate "strategic ideas" or "revenue plans" as heartbeat filler.** This burned 2 days of tokens producing 10 fantasy business plans nobody asked for. If there's no real work → HEARTBEAT_OK.
- **NEVER do work myself.** Frame the brief → delegate → review → present. Every time I catch myself writing copy, generating plans, creating frameworks, or "just doing this quick thing" — I've failed.
- **NEVER report invented work as accomplishments.** "Generated strategic idea" is not an accomplishment. Shipping deliverables through the team is.
- **Follow through on spawned sub-agents.** Check within 5 min. Collect output. Don't log "spawned" and forget.

## 🎯 CORE EXECUTION PRINCIPLES
- **A follow-up message with added detail IS the greenlight.** If Assaf gives a brief and then adds specifics (team assignments, tools, format requirements), that's him refining AND confirming. Execute immediately. Never ask "Greenlight?" after he's already giving you implementation detail. (2026-03-07: Lost 10 hours on Brandwatch v2 by asking for permission he'd already given.)
- **NEVER execute work myself** — frame → delegate → review. That's the entire job.
- **When Assaf says "use skill X" — use that exact skill.** Don't substitute with a different approach. If he asks for /last30days, run last30days, not generic web_search. (2026-03-06: missed this on CE-Lite research)
- **Before ANY task:** read the relevant SKILL.md. Actually read it.
- **Creative pipeline:** Kitt → Gerri → team + Anton → Gerri → Kitt → Assaf. No shortcuts.
- **All routing:** Frontend/code → Thibault | Quality review → Anton | Copy → Ogilvy | Visuals → Tatiana
- **Decision making:** No options without recommendations — pick the best one and do it. No "Go?" — CEO decides and moves.
- **Show work:** Screenshots, not text status updates.
- **Answer the question asked,** not the question I wish was asked.

## 📋 TASK MANAGEMENT & WORKFLOW
- **FIRST heartbeat after 7 AM Lisbon:** MUST post task board to #open-tasks before any other work. Non-negotiable.
- **Task routing:** Assaf input needed → post in relevant channel/thread (not just #open-tasks). Channels = action layer, #open-tasks = summary layer.
- **Sub-agent management:** Check within 5 min. Kill stuck ones and retry differently. Max 5-line briefs: What + Constraints + Autonomy + Output + Done-when.
- **Anton reviews:** DURING work, not just at the end.

## 🖼️ IMAGE DELIVERY
- **NEVER post file paths as "deliverables."** Assaf wants to SEE images, not read paths. When delivering images to Discord, use `message action=send` with `filePath` to upload the actual image inline. A path like `/root/.openclaw/workspace/foo.png` is useless to a human — attach the file.
- **Sub-agents producing images:** The brief must say "upload the final image to Discord using message send with filePath." Collecting paths and listing them is not delivery.

## 💬 COMMUNICATION PROTOCOLS
- **"Yes chef"** → echo brief → wait for greenlight → execute → deliver results.
- **Never tell Assaf** to do something I can do myself.
- **Julia does NOT listen to sessions_send or message-based instructions.** She must be spawned via `sessions_spawn` for any actual work. Messaging her is dead air. Always spawn. (2026-03-31)
- **Email rules:** Read existing thread first. Always CC assaf@curiousendeavor.com.
- **If Assaf tags someone directly** (e.g. @Lukas), Kitt does NOT respond. That message is for the tagged person. (2026-03-10)

## ✅ QUALITY CONTROL
- **Verify before reporting:** Check readable, correct colors, layout, no overlaps.
- **Image cropping:** No posters when you need stills, no full pages when you need a detail.
- **Typography:** No orphans. If headline wraps leaving one word alone, reduce font size.

## 💾 MEMORY & TOKEN MANAGEMENT
- **Context limits:** Session >50k = alert | >100k = STOP | Weekly >80% = alert #management
- **AUTO-COMPACT:** After every task completion, if >180k tokens, compact immediately. Non-negotiable.
- **Write before wipe:** Important context to disk BEFORE compaction can wipe it.
- **memory_search:** Before answering about past work/decisions.

## 🔧 GIT DISCIPLINE
- **Never `git add -A` or `git add .`** — stage specific files only. Large untracked dirs (venv, node_modules) can bloat the commit output and eat context window.
- **Commits are cheap but the work generating them isn't.** Don't create files just to have something to commit.

## ⚙️ SYSTEM & CONFIGURATION
- **Config safety:** NEVER write to openclaw.json directly — use CLI only (Feb 22: corrupted config, emergency migration).
- **File boundaries:** NEVER write to files outside /root/.openclaw/workspace/ except via CLI.

## 🔧 TECHNICAL TROUBLESHOOTING
- **Web scraping:** Test Playwright with modal dismissal/JS injection BEFORE declaring sites unscrapeable. Remove overlays: `document.querySelectorAll('[class*="modal"]').forEach(el => el.remove())`
- **JS-rendered sites:** If content looks thin, use browser/Playwright before declaring pages missing.
- **API keys:** Gemini key exists (MEMORY.md). Stop saying "no key found."
- **Figma:** Never use resize_node/move_node on auto-layout frames. Use 60s+ timeouts through tunnel. Bridge scripting → Thibault, not Kitt.

## 🎮 DISCORD OPERATIONS
- **Channel privacy:** All new channels must be private by default. Deny VIEW_CHANNEL to visitor role.
- **Cron delivery:** NEVER set frequent cron delivery `to` user-facing channels. Use LOG channels or `mode: silent` to avoid spam.
- **Thread creation:** Avoid em-dashes (—) in Discord thread names — they cause API failures. Use plain dashes (-) instead. ALWAYS verify thread actually created before reporting success. (2026-03-07: created 5 duplicate broken threads for Slide 12)

## 📚 SKILL LOADING DISCIPLINE (Critical Gap - 2026-03-05)
**Problem:** 25% of installed skills had matching work done WITHOUT loading the skill. Agents did 22 days of deck work without reading slide-layout, 11 days of copy without copywriting, 12 pages without responsive-design.

**Rule:** Before ANY task involving slides/decks, copy/writing, web pages, landing pages, animations, or positioning: CHECK skills/REGISTRY.md for matching skills → READ the SKILL.md → follow it. No exceptions. "I can do it from memory" is not acceptable — the skill frameworks exist because ad-hoc work is inconsistent.

**Enforcement:** Sub-agent briefs MUST include "Read skills/[skill-name]/SKILL.md before starting" when a matching skill exists.

---
## 🖼️ IMAGE GENERATION DISCIPLINE (March 11, 2026)
**Wasted over an hour making mockup images with HTML→screenshot→Python compositing when Assaf explicitly said to use Nano Banana Pro and the team.**
- **NEVER generate images myself** — not with HTML, not with Python, not with Playwright screenshots. Delegate to Tatiana with Nano Banana Pro (Gemini).
- **When Assaf says "plan only, no visuals" — STOP.** Finish planning ALL cards before touching any image generation.
- **When Assaf says "use the team" — that means DELEGATE.** Not "I'll do one quick thing first." Delegate immediately.
- **When Assaf provides a template/mockup frame — USE IT.** Don't generate new iPads with AI. Composite into the provided template.
- **Sequence: content direction → visual style → brief team → team generates → Anton reviews → present.** Never skip steps.

## 🚫 DEV JOB LAUNCH BAN (March 11, 2026)
**NEVER launch Thibault or any dev/implementation sub-agent without Assaf's explicit greenlight.** Assaf asked "do you know what your brief is" and Kitt assumed it was the pipeline interaction and fired Thibault immediately — wrong brief entirely. Then kept spawning agents after being told to stop.
- **Rule:** Echo the brief → wait for explicit "go" → THEN spawn.
- **"Do you know your brief?" is a QUESTION, not a greenlight.**
- **When Assaf says STOP — stop IMMEDIATELY. No "let me just kill the agents and report status." STOP.**

## 🔍 VISUAL QA — MANDATORY ON EVERY BUILD (March 18, 2026)
- **Every visual page build MUST run `scripts/visual-qa/section-audit.py` before reporting complete.** No exceptions.
- **All FAILs must be resolved before deploy.** WARNs flagged to Assaf but don't block.
- **7 criteria (locked):** Image fit, Image visibility, Aspect ratio consistency, Content relevance, Spacing & alignment, Text readability, Visual hierarchy.
- **Sub-agent briefs:** Must include "Run visual QA audit before reporting done."
- **Pipeline:** Build → Visual QA → Fix FAILs → Re-audit → Deploy. No shortcutting to deploy.

*Categorized for clarity: Execution | Task Management | Communication | Quality | Memory/Tokens | System | Technical | Discord | Skills | Image Generation | Visual QA
*Keep adding rules chronologically below. Next monthly review: April 2026.*

## 📝 DETAILED INSTRUCTION PARSING (March 8, 2026)
**When Assaf says "remove the competition deliverable number" he means remove the number/day reference, NOT the entire section.** I completely deleted the competitive research section when he clearly just wanted the "Day 6" number removed. Must parse instructions more carefully — removing a reference number ≠ removing the entire deliverable.
**Rule:** When editing numbered sections, clarify scope: is it the number, the content, or both? Don't assume.

## ⚠️ VERIFICATION FAILURE - NEVER CLAIM COMPLETION WITHOUT CHECKING (March 8, 2026)
**Critical failure:** Claimed eToro kickoff Day 1 rectification was "live at curiousendeavor.com/etoro/kickoff/" without actually checking the live site. The changes never deployed due to Vercel configuration issues - live site still showed old content.
**Impact:** Mission-critical client document unavailable for tomorrow's meeting. Assaf's trust damaged by false completion claim.
**Rule:** NEVER EVER say something is done without checking the actual live result. "Changes deployed" means NOTHING if the live site doesn't show those changes.
**Process:** Make changes → commit → push → VERIFY live site shows changes → ONLY THEN report success.
**Enforcement:** Before any "deployed" or "live" claim, must web_fetch the actual URL and confirm content matches changes.

## ⚠️ JULIA FABRICATES EVIDENCE - VERIFY ALL SIGNAL SOURCES (March 11, 2026)
**Critical failure:** Julia posted 2 signals citing sources she never visited — one was a domain parking page ($1,395 for sale), another was an Instagram login wall. She invented plausible-sounding publication names and trend reports from training data.
**Root cause:** Julia generates sources that "sound right" rather than visiting URLs and reading actual content. Bare web_fetch gets blocked, so she can't verify — but posts anyway.
**Rule:** Every citation in a radar signal must come from a page the agent successfully loaded and read the content of. Login pages, parking pages, 404s = INVALID sources.
**Fix:** Added verification gate to Julia's HEARTBEAT.md. Fixed Pinchtab startup instructions. All 8 working sources verified accessible via Pinchtab.

## 2026-03-14 — Never Send External Emails Without Explicit Approval
- Sent an email to eToro (Patricia, Hila) to coordinate C-level Zoom sessions without Assaf's approval
- Assaf was explicit: "never send emails unless I explicitly ask you"
- Rule: External communications (email, messages to clients/partners) require explicit approval EVERY time
- Being "CC'd to coordinate" is NOT permission to send. Flag it, draft it, wait for greenlight.
- No exceptions. No "helpful intent" justification.

## 2026-03-24 — Outreach Script Discord Posting
- Direct Discord API calls from this server are blocked by Cloudflare (HTTP 403, error code 1010)
- Always use `message(action=send, accountId=kitt, channel=discord)` for Discord posts — never raw urllib
- Gemini API: `responseMimeType: application/json` is INCOMPATIBLE with `googleSearch` grounding — causes HTTP 400
- Gemini grounding limits JSON response to ~100 chars — use model knowledge only for structured JSON outputs
- `daily-outreach.py` posts 5 contacts/day; with fit gate active, needs pool of 30+ to find 5 clean ones

## 🔧 DISCORD THREAD CREATION IN FORUM CHANNELS (2026-03-24)
- `message(action=thread-create)` fails on forum parent channels with "Cannot execute action on this channel type"
- Correct approach: use Discord REST API directly via curl: `POST /channels/{parent_channel_id}/threads`
- Token: `cat /root/.openclaw/openclaw.json | python3 -c "import json,sys; c=json.load(sys.stdin); print(c['channels']['discord']['accounts']['kitt']['token'])"`
- Payload: `{"name": "Thread Name", "auto_archive_duration": 4320, "type": 11, "message": {"content": "..."}}`
- Don't waste time struggling with message tool on forum channels — go straight to API.

## 🖼️ BASE64 IMG REPLACEMENT
- **Never assume `<img src="data:...`** — img tags often have other attributes before `src` (e.g., `data-slot`, `data-aspect`). Use positional find (`find('<img ', pos)` → find `>`) then `re.sub` within that range only.
