# Agent Lessons — Index **Session start:** read this file only. Match tags to the task. Open the matching lesson body in `agents-docs/LESSONS.md` — do **not** load every lesson. When adding a lesson: append the full entry near the top of `LESSONS.md` (under `## Lessons`) **and** add one bullet here. Tags help grepping: `rg '\\[attachments\\]' agents-docs/LESSONS-INDEX.md` ## Index - Keep `NgOptimizedImage` off runtime blob and data URLs — `[angular] [images]` - Read the exact Obsidian bug note before diagnosing a named ticket — `[workflow] [bugs]` - Run `npm run i18n:sync` after editing any `public/i18n/catalog/*.json` file — `[i18n] [testing]` - Match direct-call recipients against every local identity alias, exactly like DMs already do — `[direct-call] [identity]` - Resolve outbound direct-call recipient ids to the peer's connected signal identity — `[direct-call] [identity] [signaling]` - Canonicalize direct conversation ids across cross-signal actor aliases — `[direct-message] [identity]` - Decide attachment receive admission once at request time; never re-gate size in the chunk handler — `[attachments]` - Re-queue attachment auto-downloads on every message/room binding event; never trust one transport's ordering — `[attachments] [realtime]` - Scope per-user UI state by user id, not by the client database — `[persistence] [multi-user] [custom-emoji]` - Don't strand signed-out mobile users on a logged-out dashboard — `[auth] [mobile] [routing]` - "Shared from your device" must gate on local bytes, not uploader user id — `[attachments] [multi-device]` - Generate Android brand icons from the source mark; guard against stock Capacitor placeholders — `[mobile] [android] [assets]` - Bind chat attachments to a pre-allocated message id, never by matching content — `[attachments] [chat] [mobile]` - Attachment file persistence must be platform-agnostic, not Electron-only — `[attachments] [persistence] [mobile]` - Never count duplicate chunks toward transfer progress, and never finalize on byte counters — `[attachments] [webrtc]` - Don't bump E2E timeouts for sync flakes - gate on presence and read server logs — `[testing] [realtime]` - When renaming an Angular route, sweep every navigate/url-match/doc reference — `[routing]` - Server discovery must fan out across all endpoints and self-heal on 404 — never hardcode a host capability blocklist — `[server-directory]` - Server registration needs `ownerPublicKey: oderId || id`, and must not be fire-and-forget — `[server-directory] [rooms]` - Identify must fall back to the legacy session token, not only the new credential store — `[realtime] [authentication]` - Keep the per-signal-URL identify credential resolvable from the store — `[realtime] [authentication]` - Store clientInstanceId in sessionStorage not localStorage — `[realtime] [multi-device]` - Revalidate IndexedDB scope without reinitializing on every read — `[persistence] [performance]` - Restore local user scope before protected writes — `[authentication] [persistence]` - Persisted local user state still requires a session token — `[authentication] [signaling]` - Declare MODIFY_AUDIO_SETTINGS for Android WebRTC mic capture — `[mobile] [android]` - Do not override Tailwind with box-sizing inherit — `[mobile] [css]` - Use the app-shell servers rail for mobile discovery pages — `[mobile] [layout]` - Defer attachment blob hydration on Electron startup — `[attachments] [electron]` - Lazy-load Capacitor modules on Electron/desktop — `[mobile] [electron]` - Use the upgrade transaction during IndexedDB schema migrations — `[persistence] [browser]` - Wait for authenticateUser storage prep before post-login navigation — `[authentication] [browser]` - Use dense arrays for chunked transfer buffers — `[custom-emoji] [webrtc]` - Route custom emoji right-click through the native context menu — `[custom-emoji] [ux]` - Separate known emoji assets from saved library — `[custom-emoji] [ux]` - Chunk custom emoji assets over data channels — `[custom-emoji] [webrtc]` - Re-clear visible notification channels after recompute — `[notifications] [startup]` - Disambiguate nested chat cards — `[chat] [ui]` - Use terminal Vitest when the test tool hangs — `[testing]` - Do not add fake chrome around screenshots — `[website] [design]` - Verify lint exits 0 before claiming done — `[verification]` - Use blob URLs for inline attachment previews — `[attachments] [electron]` - Resolve Electron drag-and-drop file paths with webUtils — `[attachments] [electron]` - Preserve uploader local attachment paths across sync — `[attachments] [persistence]` - Prove the asked behavior; unit-green is not done — `[verification] [testing] [workflow]` - Default to `toju-app/` + targeted `electron/` + CI; do not crawl the monorepo — `[workflow] [tokens] [scope]` - Write HANDOFF.md and ask the user for a new chat — agents cannot open chats — `[workflow] [tokens] [handoff]`