Files
Toju/agents-docs/LESSONS.md

5.1 KiB

Agent Lessons

Durable rules for AI agents working on this project. Read this file at session start. Append to it when this session produces a correction worth remembering.

How to use this file

At session start: scan the rules below. If any match the work you're about to do, apply them.

During the session: if the user corrects you, reverts your edit, or re-prompts with the same instruction — that is a signal to record a lesson before closing the task. See the trigger list in agents-docs/AGENT_WORKFLOW.md.

Format of a lesson: every entry uses the four-slot template below. Brevity matters — if you can't state the rule in one sentence, the lesson isn't sharp enough yet.

### <short imperative title>

- **Trigger:** what you were about to do that turned out wrong (one line, concrete enough to pattern-match against)
- **Rule:** what to do instead (one sentence, imperative voice)
- **Why:** the consequence of getting it wrong — past incident, hidden constraint, user preference
- **Example:** one concrete instance, ideally a code or command snippet

Keep lessons sharp. Tag each rule with one or two tags in square brackets after the title (e.g. [testing] [migrations]) so future agents can grep for relevance. If a rule no longer applies, delete it — stale rules drown the real ones.


Lessons

Re-clear visible notification channels after recompute [notifications] [startup]

  • Trigger: fixing startup unread badges by only changing read-marker writes or initial hydration.
  • Rule: also check later loadMessagesSuccess and syncMessages recomputes, and re-clear the focused visible channel after applying derived unread counts.
  • Why: the startup-selected server can load or sync messages after it was marked read, reintroducing a channel unread badge even though the user is viewing that channel.
  • Example: NotificationsService.refreshRoomUnreadFromMessages(...) should clear activeChannelId for currentRoom after recalculating counts from a startup message batch.

Disambiguate nested chat cards [chat] [ui]

  • Trigger: removing a visual treatment from chat history when a system message has both an outer row wrapper and an inner pill/card.
  • Rule: preserve the intended inner timeline pill unless the user explicitly targets it; render system messages outside the themed chatMessageBubble wrapper and keep data-message-id off direct child divs.
  • Why: PM call-started history should stay as a compact centered pill, while theme CSS such as app-chat-message-item > div[data-message-id] can turn the full-width row around it into the unnecessary card.
  • Example: In chat-message-item.component.html, keep data-testid="chat-system-message" with rounded-full border bg-secondary/45, put appThemeNode="chatMessageBubble" only on the non-system branch, and place [attr.data-message-id] on the nested pill instead of the system row wrapper.

Use terminal Vitest when the test tool hangs [testing]

  • Trigger: VS Code test execution stays at "Starting test run..." without producing Vitest output.
  • Rule: run the focused spec through the terminal with cd toju-app && npx vitest run <spec-path> and report the direct Vitest result.
  • Why: the test integration can hang before starting the runner, while the terminal Vitest command returns quickly and gives actionable failures.
  • Example: cd toju-app && npx vitest run src/app/domains/game-activity/application/game-activity.service.spec.ts.

Do not add fake chrome around screenshots [website] [design]

  • Trigger: wrapping a real product screenshot in decorative titlebar/window chrome or placing oversized marketing headings beside copy without checking overlap.
  • Rule: use the screenshot's existing frame when it already includes app chrome, and top-align large heading/copy columns with explicit readable widths.
  • Why: duplicated chrome makes CTA/product previews look broken, and bottom-aligned large headings can cover accompanying text on the marketing site.
  • Example: website/src/app/pages/home/home.component.html should render the screenshot directly; host-section should use top-aligned heading and .host-section-copy columns.

Verify lint exits 0 before claiming done [verification]

  • Trigger: about to report a task as complete after running tests but skipping ESLint.
  • Rule: run npm run lint from the repo root and confirm exit code 0 before any "done" claim.
  • Why: npm run test only runs the toju-app Vitest suite — it doesn't cover the server, Electron, or website packages. ESLint (flat config in eslint.config.js) is the universal check across every package; type-style violations slip through tests and break Gitea Workflows for the next agent.
  • Example: npm run lint && echo OK — only claim done after seeing OK. For Electron type errors specifically, also confirm npm run build:electron succeeds (it invokes tsc -p tsconfig.electron.json).